import { expect, test } from "bun:test";
import { buildKeywordOverview } from "./overview";
import type { GscTracking, Keyword, SearchIntent } from "./types";

const gsc = (position: number, clicks = 0, impressions = 0): GscTracking => ({
  clicks,
  impressions,
  ctr: 0,
  position,
  updatedAt: "2026-06-06",
});

let n = 0;
function kw(
  over: Partial<Omit<Keyword, "theme">> & { theme?: string | null } = {},
): Keyword {
  n += 1;
  return {
    id: `k${n}`,
    siteId: "site1",
    term: `kw ${n}`,
    locale: { lang: "fr", country: "FR" },
    theme: null,
    status: "idea",
    intent: ["informational"] as SearchIntent[],
    stages: [],
    primarySource: "mangools",
    sources: ["mangools"],
    metrics: {
      mangools: { volume: 100, kd: 30, cpc: 1, growthPct: null, updatedAt: "" },
    },
    gsc: null,
    trend: [],
    briefs: {},
    ...over,
  } as Keyword;
}

test("aggregates counts, distributions, opportunities and stages", () => {
  const ov = buildKeywordOverview(
    [
      kw({
        gsc: gsc(2),
        metrics: {
          mangools: {
            volume: 500,
            kd: 10,
            cpc: 1,
            growthPct: null,
            updatedAt: "",
          },
        },
      }),
      kw({
        gsc: gsc(15, 5, 900),
        intent: ["commercial"],
        stages: ["research"],
        theme: "energie",
      }),
      kw({ gsc: gsc(40), theme: "energie" }),
      kw({ gsc: null, stages: ["research", "planning"] }),
    ],
    [{ status: "live" }, { status: "live" }, { status: "prospect" }],
  );
  expect(ov.totalKeywords).toBe(4);
  expect(ov.positioned).toBe(3);
  expect(ov.positionedPct).toBe(75);
  expect(ov.quickWins).toBe(1); // position 15
  expect(ov.totalClicks).toBe(5);
  expect(ov.totalImpressions).toBe(900);
  expect(ov.positionDistribution.find((b) => b.key === "top3")?.count).toBe(1);
  expect(ov.positionDistribution.find((b) => b.key === "none")?.count).toBe(1);
  expect(ov.opportunities[0]?.term).toBe("kw 2"); // only the quickwin scores > 0
  expect(ov.opportunities.length).toBe(1);
  expect(ov.topByVolume[0]?.volume).toBe(500);
  expect(ov.stages).toEqual({ reservoir: 4, research: 2, planning: 1 });
  expect(ov.backlinks?.total).toBe(3);
  expect(ov.backlinks?.byStatus.find((s) => s.key === "live")?.count).toBe(2);
  expect(ov.byTheme.find((t) => t.key === "energie")?.count).toBe(2);
});

test("empty + no-backlinks", () => {
  const ov = buildKeywordOverview([], null);
  expect(ov.totalKeywords).toBe(0);
  expect(ov.positionedPct).toBe(0);
  expect(ov.avgPosition).toBeNull();
  expect(ov.avgCtr).toBeNull();
  expect(ov.backlinks).toBeNull();
  expect(ov.positionDistribution.length).toBe(6);
});
