/**
 * Task 7 - listDocuments folder filtering (TDD).
 *
 * Exercises the three folderId modes: null (root only), a string (direct
 * children), and a string with includeDescendants=true (subtree). Mirrors the
 * pattern in document-folders-crud.test.ts: makePort returns a Port row, and
 * TEST_USER_ID is resolved once via beforeAll from any seeded user.
 */

import { describe, it, expect, beforeEach, beforeAll } from 'vitest';
import { eq } from 'drizzle-orm';

import { db } from '@/lib/db';
import { documents, documentFolders } from '@/lib/db/schema/documents';
import { user } from '@/lib/db/schema/users';
import { createFolder } from '@/lib/services/document-folders.service';
import { listDocuments } from '@/lib/services/documents.service';
import { makePort } from '../helpers/factories';

describe('documents.listDocuments folder filtering', () => {
  let portId: string;
  let testUserId: string;

  beforeAll(async () => {
    const [u] = await db.select({ id: user.id }).from(user).limit(1);
    if (!u) throw new Error('No user available; run pnpm db:seed first');
    testUserId = u.id;
  });

  beforeEach(async () => {
    const port = await makePort();
    portId = port.id;
    await db.delete(documents).where(eq(documents.portId, portId));
    await db.delete(documentFolders).where(eq(documentFolders.portId, portId));
  });

  it('filters by folderId (direct children only by default)', async () => {
    const root = await createFolder(portId, testUserId, { name: 'Root', parentId: null });
    const sub = await createFolder(portId, testUserId, { name: 'Sub', parentId: root.id });
    await db.insert(documents).values([
      {
        portId,
        documentType: 'other',
        title: 'In Root',
        createdBy: testUserId,
        folderId: root.id,
      },
      { portId, documentType: 'other', title: 'In Sub', createdBy: testUserId, folderId: sub.id },
      {
        portId,
        documentType: 'other',
        title: 'At Root (no folder)',
        createdBy: testUserId,
        folderId: null,
      },
    ]);

    const res = await listDocuments(portId, {
      page: 1,
      limit: 50,
      order: 'desc',
      includeArchived: false,
      includeDescendants: false,
      folderId: root.id,
    });
    const titles = (res.data as Array<{ title: string }>).map((d) => d.title);
    expect(titles).toContain('In Root');
    expect(titles).not.toContain('In Sub');
    expect(titles).not.toContain('At Root (no folder)');
  });

  it('includeDescendants=true pulls in children of children', async () => {
    const root = await createFolder(portId, testUserId, { name: 'Root', parentId: null });
    const sub = await createFolder(portId, testUserId, { name: 'Sub', parentId: root.id });
    await db.insert(documents).values([
      {
        portId,
        documentType: 'other',
        title: 'In Root',
        createdBy: testUserId,
        folderId: root.id,
      },
      { portId, documentType: 'other', title: 'In Sub', createdBy: testUserId, folderId: sub.id },
    ]);

    const res = await listDocuments(portId, {
      page: 1,
      limit: 50,
      order: 'desc',
      includeArchived: false,
      includeDescendants: true,
      folderId: root.id,
    });
    const titles = (res.data as Array<{ title: string }>).map((d) => d.title);
    expect(titles).toContain('In Root');
    expect(titles).toContain('In Sub');
  });

  it('folderId=null returns only docs at root', async () => {
    const root = await createFolder(portId, testUserId, { name: 'Root', parentId: null });
    await db.insert(documents).values([
      {
        portId,
        documentType: 'other',
        title: 'In Root',
        createdBy: testUserId,
        folderId: root.id,
      },
      {
        portId,
        documentType: 'other',
        title: 'At Root',
        createdBy: testUserId,
        folderId: null,
      },
    ]);

    const res = await listDocuments(portId, {
      page: 1,
      limit: 50,
      order: 'desc',
      includeArchived: false,
      includeDescendants: false,
      folderId: null,
    });
    const titles = (res.data as Array<{ title: string }>).map((d) => d.title);
    expect(titles).toEqual(['At Root']);
  });

  it('hides completed workflows when folderId is set', async () => {
    const folder = await createFolder(portId, testUserId, { name: 'ClientFolder', parentId: null });
    await db.insert(documents).values([
      {
        portId,
        documentType: 'eoi',
        title: 'In flight',
        createdBy: testUserId,
        folderId: folder.id,
        status: 'sent',
      },
      {
        portId,
        documentType: 'eoi',
        title: 'Completed workflow',
        createdBy: testUserId,
        folderId: folder.id,
        status: 'completed',
      },
    ]);

    const res = await listDocuments(portId, {
      page: 1,
      limit: 50,
      order: 'desc',
      includeArchived: false,
      includeDescendants: false,
      folderId: folder.id,
    });
    const titles = (res.data as Array<{ title: string }>).map((d) => d.title);
    expect(titles).toContain('In flight');
    expect(titles).not.toContain('Completed workflow');
  });
});
