import { beforeEach, expect, test } from "bun:test";
import { eq } from "drizzle-orm";
import { assertTestDb } from "@/lib/db/assert-test-db";
import { organization, user } from "@/lib/db/auth-schema";
import { db } from "@/lib/db/client";
import { keywords as kw, sites } from "@/lib/db/domain-schema";
import { createGscKeywordsForSite } from "./discovery";

const SITE = "gsc-disc-site";
const ORG = "gsc-disc-org";
const USR = "gsc-disc-user";

beforeEach(async () => {
  await assertTestDb();
  await db.delete(kw).where(eq(kw.siteId, SITE));
  await db.delete(sites).where(eq(sites.id, SITE));
  await db.delete(organization).where(eq(organization.id, ORG));
  await db.delete(user).where(eq(user.id, USR));
  await db.insert(user).values({
    id: USR,
    name: "U",
    email: `gscdisc-${Date.now()}@example.com`,
    emailVerified: true,
  });
  await db.insert(organization).values({
    id: ORG,
    name: "O",
    slug: `gscdisc-${Date.now()}`,
    createdAt: new Date(),
  });
  await db.insert(sites).values({
    id: SITE,
    orgId: ORG,
    ownerUserId: USR,
    name: "S",
    url: "https://example.com",
    primaryLanguage: "fr",
    targetCountries: ["FR"],
  });
});

// NB: do NOT client.end() — the postgres client is a shared singleton; closing
// it here would break the other gsc tests in the same directory run.

const row = (query: string, impressions = 10) => ({
  query,
  clicks: 1,
  impressions,
  ctr: 0.1,
  position: 12,
});
const OPTS = {
  lang: "fr",
  country: "FR",
  stages: [] as ("research" | "planning")[],
};

test("creates GSC-only keywords with the right shape", async () => {
  const res = await createGscKeywordsForSite(
    SITE,
    [row("panneau solaire", 99)],
    OPTS,
  );
  expect(res).toEqual({ created: 1 });
  const [k] = await db.select().from(kw).where(eq(kw.siteId, SITE));
  expect(k.id).toBe(`${SITE}-panneau-solaire`);
  expect(k.primarySource).toBe("gsc");
  expect(k.sources).toEqual(["gsc"]);
  expect(k.metrics).toEqual({});
  expect(k.gsc?.impressions).toBe(99);
  expect(k.stages).toEqual([]);
});

test("is idempotent (second run creates 0) and skips existing ids", async () => {
  await createGscKeywordsForSite(SITE, [row("panneau solaire")], OPTS);
  const res = await createGscKeywordsForSite(
    SITE,
    [row("panneau solaire"), row("prix solaire")],
    OPTS,
  );
  expect(res).toEqual({ created: 1 }); // only the new one
  const rows = await db.select().from(kw).where(eq(kw.siteId, SITE));
  expect(rows.length).toBe(2);
});

test("routes stages per destination", async () => {
  await createGscKeywordsForSite(SITE, [row("solaire recherche")], {
    ...OPTS,
    stages: ["research"],
  });
  const [k] = await db.select().from(kw).where(eq(kw.siteId, SITE));
  expect(k.stages).toEqual(["research"]);
});
