import { beforeAll, expect, test } from "bun:test";
import { eq } from "drizzle-orm";
import { analyticsJobs } from "@/lib/db/domain-schema";
import { db } from "../src/db";
import { app } from "../src/index";
import { ensureTestSite, TEST_SITE as SITE } from "./fixtures/site";

// A real key exported in the developer's shell would turn these unauthenticated
// requests into 401s — the auth path has its own suite (auth.test.ts).
delete process.env.ANALYTICS_API_KEY;

beforeAll(ensureTestSite);
test("POST /jobs validates + inserts a queued job", async () => {
  const res = await app.request("/jobs", {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify({
      siteId: SITE,
      source: "semrush",
      objectKey: "exports/x.csv",
    }),
  });
  expect(res.status).toBe(200);
  const { id } = (await res.json()) as { id: string };
  const row = (
    await db.select().from(analyticsJobs).where(eq(analyticsJobs.id, id))
  )[0];
  expect(row.status).toBe("queued");
  expect(row.source).toBe("semrush");
  await db.delete(analyticsJobs).where(eq(analyticsJobs.id, id));
});
test("POST /jobs rejects an invalid source", async () => {
  const res = await app.request("/jobs", {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify({ siteId: SITE, source: "bogus", objectKey: "x" }),
  });
  expect(res.status).toBe(400);
});
test("POST /jobs accepts a site-crawl job (no source/objectKey), then 409 while active", async () => {
  const body = JSON.stringify({ type: "site-crawl", siteId: SITE });
  const headers = { "content-type": "application/json" };

  const res = await app.request("/jobs", { method: "POST", headers, body });
  expect(res.status).toBe(200);
  const { id } = (await res.json()) as { id: string };
  const row = (
    await db.select().from(analyticsJobs).where(eq(analyticsJobs.id, id))
  )[0];
  expect(row.type).toBe("site-crawl");
  expect(row.status).toBe("queued");
  expect(row.source).toBeNull();
  expect(row.objectKey).toBeNull();

  // A second crawl for the same site is refused while the first is active.
  const dup = await app.request("/jobs", { method: "POST", headers, body });
  expect(dup.status).toBe(409);

  await db.delete(analyticsJobs).where(eq(analyticsJobs.id, id));
});
