// test/auth.test.ts — Bearer guard on POST /jobs (ANALYTICS_API_KEY).
// Self-sufficient fixtures (user/org/site) so the FK on analytics_jobs.site_id
// holds on a bare test DB.
import {
  afterAll,
  afterEach,
  beforeAll,
  beforeEach,
  expect,
  test,
} from "bun:test";
import { eq } from "drizzle-orm";
import { organization, user } from "@/lib/db/auth-schema";
import { analyticsJobs, sites } from "@/lib/db/domain-schema";
import { db } from "../src/db";
import { app } from "../src/index";

const SITE = "wt-analytics-auth-site";
const ORG = "wt-analytics-auth-org";
const USER = "wt-analytics-auth-user";
const KEY = "test-analytics-key";
const ORIGINAL = process.env.ANALYTICS_API_KEY;

function postJobs(headers: Record<string, string>) {
  return app.request("/jobs", {
    method: "POST",
    headers: { "content-type": "application/json", ...headers },
    body: JSON.stringify({
      siteId: SITE,
      source: "semrush",
      objectKey: "exports/auth-test.csv",
    }),
  });
}

async function cleanup() {
  await db.delete(sites).where(eq(sites.id, SITE)); // cascades analytics_jobs
  await db.delete(organization).where(eq(organization.id, ORG));
  await db.delete(user).where(eq(user.id, USER));
}

beforeAll(async () => {
  await cleanup();
  await db.insert(user).values({
    id: USER,
    name: "U",
    email: `wt-analytics-auth-${Date.now()}@example.com`,
    emailVerified: true,
  });
  await db.insert(organization).values({
    id: ORG,
    name: "O",
    slug: `wt-analytics-auth-${Date.now()}`,
    createdAt: new Date(),
  });
  await db.insert(sites).values({
    id: SITE,
    orgId: ORG,
    ownerUserId: USER,
    name: "Analytics Auth Site",
    url: "https://wt-analytics-auth.example.com",
  });
});

afterAll(async () => {
  // NB: no client.end() — the postgres singleton is shared by sibling test files.
  await cleanup();
});

beforeEach(() => {
  process.env.ANALYTICS_API_KEY = KEY;
});
afterEach(() => {
  // Restore so sibling test files (enqueue.test.ts) keep running unauthenticated.
  if (ORIGINAL === undefined) delete process.env.ANALYTICS_API_KEY;
  else process.env.ANALYTICS_API_KEY = ORIGINAL;
});

test("POST /jobs rejects without a bearer token when the key is set", async () => {
  const res = await postJobs({});
  expect(res.status).toBe(401);
});

test("POST /jobs rejects a wrong bearer token", async () => {
  const res = await postJobs({ authorization: "Bearer wrong-key" });
  expect(res.status).toBe(401);
});

test("POST /jobs accepts the right bearer token and enqueues", async () => {
  const res = await postJobs({ authorization: `Bearer ${KEY}` });
  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");
  await db.delete(analyticsJobs).where(eq(analyticsJobs.id, id));
});

test("POST /jobs stays open (dev) when the key is unset", async () => {
  delete process.env.ANALYTICS_API_KEY;
  const res = await postJobs({});
  expect(res.status).toBe(200);
  const { id } = (await res.json()) as { id: string };
  await db.delete(analyticsJobs).where(eq(analyticsJobs.id, id));
});
