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

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

describe('document-folders · deleteFolderSoftRescue', () => {
  let portId: string;
  let testUserId: string;

  beforeAll(async () => {
    const [u] = await db.select({ id: user.id }).from(user).limit(1);
    testUserId = u!.id;
  });

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

  it("moves child subfolders up to the deleted folder's parent", async () => {
    const root = await createFolder(portId, testUserId, { name: 'Root', parentId: null });
    const middle = await createFolder(portId, testUserId, { name: 'Middle', parentId: root.id });
    const leaf = await createFolder(portId, testUserId, { name: 'Leaf', parentId: middle.id });

    await deleteFolderSoftRescue(portId, middle.id, testUserId);

    const survivor = await db.query.documentFolders.findFirst({
      where: eq(documentFolders.id, leaf.id),
    });
    expect(survivor?.parentId).toBe(root.id);
  });

  it("moves child documents to the deleted folder's parent", async () => {
    const root = await createFolder(portId, testUserId, { name: 'Root', parentId: null });
    const child = await createFolder(portId, testUserId, { name: 'Child', parentId: root.id });

    const [doc] = await db
      .insert(documents)
      .values({
        portId,
        documentType: 'other',
        title: 'Orphan-rescue test',
        createdBy: testUserId,
        folderId: child.id,
      })
      .returning();

    await deleteFolderSoftRescue(portId, child.id, testUserId);

    const updatedDoc = await db.query.documents.findFirst({
      where: eq(documents.id, doc!.id),
    });
    expect(updatedDoc?.folderId).toBe(root.id);
  });

  it('moves root-folder children to root (folderId=null) when the deleted folder is at root', async () => {
    const folder = await createFolder(portId, testUserId, { name: 'TopLevel', parentId: null });
    const child = await createFolder(portId, testUserId, {
      name: 'Survivor',
      parentId: folder.id,
    });
    await deleteFolderSoftRescue(portId, folder.id, testUserId);
    const survivor = await db.query.documentFolders.findFirst({
      where: eq(documentFolders.id, child.id),
    });
    expect(survivor?.parentId).toBeNull();
  });

  it('throws NotFound for a folder in another port', async () => {
    const otherPort = await makePort();
    const folder = await createFolder(otherPort.id, testUserId, { name: 'X', parentId: null });
    await expect(deleteFolderSoftRescue(portId, folder.id, testUserId)).rejects.toThrow(
      /couldn't find/i,
    );
  });
});
