import { describe, it, expect, beforeAll, afterEach, afterAll } from "vitest";
import { GET as listGET, POST as listPOST } from "@/app/api/projects/route";
import { GET as detailGET, DELETE as detailDELETE } from "@/app/api/projects/[id]/route";
import { prisma } from "@/lib/db";
import { signSession } from "@/lib/auth/session";

let cookieHeader: string;

beforeAll(async () => {
  process.env.PM_SESSION_SECRET = "test-secret-must-be-at-least-32-bytes-long-xx";
  const token = await signSession({ sub: "admin" });
  cookieHeader = `pm_session=${token}`;
});

afterEach(async () => {
  await prisma.project.deleteMany({});
});

afterAll(async () => {
  await prisma.$disconnect();
});

function authedReq(url: string, init: RequestInit = {}): Request {
  return new Request(url, {
    ...init,
    headers: { ...(init.headers ?? {}), cookie: cookieHeader, "Content-Type": "application/json" },
  });
}

describe("/api/projects", () => {
  it("requires auth (no cookie -> 401)", async () => {
    const res = await listGET(new Request("http://localhost/api/projects"));
    expect(res.status).toBe(401);
  });

  it("returns empty list when no projects", async () => {
    const res = await listGET(authedReq("http://localhost/api/projects"));
    expect(res.status).toBe(200);
    const body = await res.json();
    expect(body.projects).toEqual([]);
  });

  it("creates a project from a manual path payload", async () => {
    const res = await listPOST(
      authedReq("http://localhost/api/projects", {
        method: "POST",
        body: JSON.stringify({ name: "test-proj", path: "/tmp/test-proj", source: "manual" }),
      })
    );
    expect(res.status).toBe(201);
    const body = await res.json();
    expect(body.project.name).toBe("test-proj");
    expect(body.project.id).toBeTypeOf("string");
  });

  it("returns 409 on duplicate name", async () => {
    await prisma.project.create({ data: { name: "dup", path: "/tmp/dup", source: "manual" } });
    const res = await listPOST(
      authedReq("http://localhost/api/projects", {
        method: "POST",
        body: JSON.stringify({ name: "dup", path: "/tmp/dup", source: "manual" }),
      })
    );
    expect(res.status).toBe(409);
  });

  it("GET /:id returns project, DELETE removes it", async () => {
    const p = await prisma.project.create({ data: { name: "gone", path: "/tmp/gone", source: "manual" } });
    const get = await detailGET(authedReq(`http://localhost/api/projects/${p.id}`), { params: Promise.resolve({ id: p.id }) });
    expect(get.status).toBe(200);
    const del = await detailDELETE(authedReq(`http://localhost/api/projects/${p.id}`, { method: "DELETE" }), {
      params: Promise.resolve({ id: p.id }),
    });
    expect(del.status).toBe(200);
    const after = await prisma.project.findUnique({ where: { id: p.id } });
    expect(after).toBeNull();
  });
});
