import { expect, test } from "bun:test";
import type { OnlineRow } from "./online";
import { buildOnlineStats, gscPageMismatch } from "./online";

let n = 0;
function row(over: Partial<OnlineRow> = {}): OnlineRow {
  n += 1;
  return {
    id: `o${n}`,
    title: `art ${n}`,
    url: null,
    keywordTerm: null,
    keywordCountry: null,
    position: null,
    clicks: 0,
    impressions: 0,
    ctr: null,
    gscPage: null,
    ...over,
  };
}

test("buildOnlineStats sums clicks/impressions and averages position over rows-with-position", () => {
  const s = buildOnlineStats([
    row({ position: 8, clicks: 120, impressions: 2000 }),
    row({ position: 12, clicks: 30, impressions: 500 }),
    row({ position: null, clicks: 5, impressions: 100 }),
  ]);
  expect(s.published).toBe(3);
  expect(s.totalClicks).toBe(155);
  expect(s.totalImpressions).toBe(2600);
  expect(s.avgPosition).toBe(10); // (8+12)/2
});

test("gscPageMismatch: normalisation (slash final, host case), null-safe", () => {
  expect(gscPageMismatch("https://a.fr/p/", "https://A.fr/p")).toBe(false);
  expect(gscPageMismatch("https://a.fr/p", "https://a.fr/autre")).toBe(true);
  expect(gscPageMismatch(null, "https://a.fr/p")).toBe(false);
  expect(gscPageMismatch("https://a.fr/p", null)).toBe(false);
});

test("avgPosition null when no row has a position; empty input", () => {
  expect(buildOnlineStats([row()]).avgPosition).toBeNull();
  expect(buildOnlineStats([])).toEqual({
    published: 0,
    totalClicks: 0,
    totalImpressions: 0,
    avgPosition: null,
  });
});
