import { describe, expect, it } from 'vitest';
import type { Mission, Project, Task } from '@/lib/types';
import {
  validateMissionCollection,
  validateProjectCollection,
  validateProjectEntity,
  validateTaskCollection,
} from './validators';
import { missionFixtures, projectFixtures, taskFixtures } from '@/spa/pages/page-fixtures';

describe('validateTaskCollection', () => {
  it('accepts a well-formed task collection', () => {
    expect(validateTaskCollection(taskFixtures)).toEqual({
      data: taskFixtures,
      workspace: null,
    });
  });

  it('accepts an empty collection (a healthy empty state is a valid payload)', () => {
    expect(validateTaskCollection([])).toEqual({ data: [], workspace: null });
  });

  it.each([
    ['not an array', { items: [] }],
    ['item is not an object', ['nope']],
    ['missing id', [{ ...(taskFixtures[0] as Task), id: undefined }]],
    ['missing title', [{ ...(taskFixtures[0] as Task), title: undefined }]],
    ['unknown status enum', [{ ...(taskFixtures[0] as Task), status: 'finished' }]],
    ['unknown priority enum', [{ ...(taskFixtures[0] as Task), priority: 'urgent' }]],
    ['tags of the wrong type', [{ ...(taskFixtures[0] as Task), tags: 'spa' }]],
    ['metadata of the wrong type', [{ ...(taskFixtures[0] as Task), metadata: 'notes' }]],
    ['createdAt of the wrong type', [{ ...(taskFixtures[0] as Task), createdAt: 1234 }]],
    ['null sneaks past a required string', [{ ...(taskFixtures[0] as Task), title: null }]],
  ])('rejects a malformed payload: %s', (_label, value) => {
    expect(validateTaskCollection(value)).toBeNull();
  });
});

describe('validateMissionCollection', () => {
  it('accepts a well-formed mission collection', () => {
    expect(validateMissionCollection(missionFixtures)).toEqual({
      data: missionFixtures,
      workspace: null,
    });
  });

  it.each([
    ['not an array', null],
    ['item missing name', [{ ...(missionFixtures[0] as Mission), name: 42 }]],
    ['unknown status enum', [{ ...(missionFixtures[0] as Mission), status: 'canceled' }]],
    ['projectId of the wrong type', [{ ...(missionFixtures[0] as Mission), projectId: 7 }]],
  ])('rejects a malformed payload: %s', (_label, value) => {
    expect(validateMissionCollection(value)).toBeNull();
  });
});

describe('validateProjectCollection', () => {
  it('accepts a uniform workspace-scoped collection and reports its workspace', () => {
    expect(validateProjectCollection(projectFixtures)).toEqual({
      data: projectFixtures,
      workspace: 'user-1',
    });
  });

  it('accepts an empty collection with no workspace identity', () => {
    expect(validateProjectCollection([])).toEqual({ data: [], workspace: null });
  });

  it.each([
    ['not an array', 42],
    ['item missing userId', [{ ...(projectFixtures[0] as Project), userId: undefined }]],
    ['unknown status enum', [{ ...(projectFixtures[0] as Project), status: 'live' }]],
    ['description of the wrong type', [{ ...(projectFixtures[0] as Project), description: 1 }]],
  ])('rejects a malformed payload: %s', (_label, value) => {
    expect(validateProjectCollection(value)).toBeNull();
  });

  it('rejects a collection mixing workspace identities (cross-workspace leak)', () => {
    const mixed = [
      projectFixtures[0] as Project,
      { ...(projectFixtures[1] as Project), userId: 'user-2' },
    ];
    expect(validateProjectCollection(mixed)).toBeNull();
  });
});

describe('validateProjectEntity', () => {
  it('accepts a well-formed project and reports its workspace', () => {
    expect(validateProjectEntity(projectFixtures[0])).toEqual({
      data: projectFixtures[0],
      workspace: 'user-1',
    });
  });

  it.each([
    ['not an object', 'project-1'],
    ['null', null],
    ['array', [projectFixtures[0]]],
    ['missing userId', [{ ...(projectFixtures[0] as Project), userId: null }]],
  ])('rejects a malformed entity: %s', (_label, value) => {
    expect(validateProjectEntity(value)).toBeNull();
  });
});
