import { describe, expect, it } from "vitest";
import { buildWall } from "../src/ops-summary.js";
import type { OpsSummary } from "@app/shared-types";

function baseSummary(overrides: Partial<OpsSummary> = {}): OpsSummary {
  return {
    app: { app: "cibello", generated_at: new Date().toISOString() },
    ekonomi: { mrr: 0, intakt_24h: 0, intakt_7d: 0, valuta: "SEK" },
    anvandare: { aktiva_nu: 0, dau: 0, mau: 0, nya_24h: 0, nya_7d: 0 },
    prenumerationer: {
      trial_aktiva: 0,
      trial_konverterade_24h: 0,
      trial_konverterade_7d: 0,
      konverteringsgrad_30d: null,
      betalande: 0,
      avslutade_24h: 0,
    },
    butik: { butik: null, all_fields_phase_2: null },
    feedback: { oppna: 0, nya_24h: 0, senaste: null },
    ai_scan: {
      scans_24h: 0,
      scans_7d: 0,
      lyckandegrad_24h: null,
      latens_p50_ms: null,
      latens_p95_ms: null,
      felfrekvens_24h: null,
      senaste_fel: null,
      kostnad_usd_mikrocent_manad: 0,
      kostnad_usd_mikrocent_24h: null,
      kostnad_usd_mikrocent_24h_uppskattad: false,
      budget_andel: null,
      as_of: new Date().toISOString(),
    },
    aktivering: {
      scan_inom_24h_andel: null,
      lagad_maltid_inom_7d_andel: null,
      hushall_andra_medlem_aktiv_andel: null,
      retention_d1: null,
      retention_d7: null,
      retention_d30: null,
    },
    engagemang: {
      lagade_maltider_24h: 0,
      lagade_maltider_7d: 0,
      rek_ctr_7d: null,
      puffar_skickade_24h: 0,
      puffar_atgardsgrad_7d: null,
    },
    betalning: {
      failed_nu: 0,
      grace_period_nu: 0,
      trials_utgar_48h: 0,
      aterbetalningar_7d: null,
      chargebacks_7d: null,
    },
    jobb: {
      vantande: 0,
      aktiva: 0,
      misslyckade_24h: 0,
      aldsta_vantande_sek: null,
      workers_ok: true,
    },
    sakerhet: {
      allergen_invariant_brott: 0,
      overifierade_visade: 0,
      food_safety_lint_avvisade_7d: null,
      senaste_kontroll: null,
    },
    wall: { boards: [] },
    as_of: new Date().toISOString(),
    ...overrides,
  };
}

/**
 * Wall-testet verifierar att buildWall är härlett uteslutande ur summary-värden.
 * Inga hårdkodade tal får förekomma.
 */
describe("buildWall", () => {
  it("formaterar MRR i öre till kr med mellanslag", () => {
    const summary = baseSummary({ ekonomi: { ...baseSummary().ekonomi, mrr: 1234567 } });
    const tile = buildWall(summary).boards[0]!.tiles.find((t) => t.label === "MRR")!;
    expect(tile.value).toBe("12 346 kr");
    expect(tile.tone).toBe("ok");
  });

  it("MRR null blir — med warn", () => {
    const summary = baseSummary({ ekonomi: { ...baseSummary().ekonomi, mrr: null } });
    const tile = buildWall(summary).boards[0]!.tiles.find((t) => t.label === "MRR")!;
    expect(tile.value).toBe("—");
    expect(tile.tone).toBe("warn");
  });

  it("aktiva nu och betalande visas som heltal", () => {
    const summary = baseSummary({
      anvandare: { ...baseSummary().anvandare, aktiva_nu: 42 },
      prenumerationer: { ...baseSummary().prenumerationer, betalande: 7 },
    });
    const tiles = buildWall(summary).boards[0]!.tiles;
    expect(tiles.find((t) => t.label === "Aktiva nu")!.value).toBe("42");
    expect(tiles.find((t) => t.label === "Betalande")!.value).toBe("7");
  });

  it("trial-konvertering blir procent; null blir —/warn", () => {
    const withValue = baseSummary({
      prenumerationer: { ...baseSummary().prenumerationer, konverteringsgrad_30d: 0.3149 },
    });
    const tileValue = buildWall(withValue).boards[0]!.tiles.find((t) => t.label === "Trial-konv")!;
    expect(tileValue.value).toBe("31 %");
    expect(tileValue.tone).toBe("ok");

    const withNull = baseSummary();
    const tileNull = buildWall(withNull).boards[0]!.tiles.find((t) => t.label === "Trial-konv")!;
    expect(tileNull.value).toBe("—");
    expect(tileNull.tone).toBe("warn");
  });

  it("workers ok → OK; nere → NERE/warn", () => {
    const ok = buildWall(baseSummary()).boards[0]!.tiles.find((t) => t.label === "Workers")!;
    expect(ok.value).toBe("OK");
    expect(ok.tone).toBe("ok");

    const nere = buildWall(
      baseSummary({ jobb: { ...baseSummary().jobb, workers_ok: false } }),
    ).boards[0]!.tiles.find((t) => t.label === "Workers")!;
    expect(nere.value).toBe("NERE");
    expect(nere.tone).toBe("warn");
  });

  it("allergen-brott 0 är ok; >0 varnar", () => {
    const zero = buildWall(baseSummary()).boards[0]!.tiles.find(
      (t) => t.label === "Allergen-brott",
    )!;
    expect(zero.value).toBe("0");
    expect(zero.tone).toBe("ok");

    const brott = buildWall(
      baseSummary({ sakerhet: { ...baseSummary().sakerhet, allergen_invariant_brott: 3 } }),
    ).boards[0]!.tiles.find((t) => t.label === "Allergen-brott")!;
    expect(brott.value).toBe("3");
    expect(brott.tone).toBe("warn");
  });

  it("alla sju tiles finns i rätt ordning", () => {
    const tiles = buildWall(baseSummary()).boards[0]!.tiles;
    expect(tiles.map((t) => t.label)).toEqual([
      "MRR",
      "Aktiva nu",
      "Betalande",
      "Trial-konv",
      "AI-budget",
      "Workers",
      "Allergen-brott",
    ]);
  });

  it("ändrat summary-värde ändrar tile (inga hårdkodade tal)", () => {
    const first = buildWall(
      baseSummary({ anvandare: { ...baseSummary().anvandare, aktiva_nu: 1 } }),
    );
    const second = buildWall(
      baseSummary({ anvandare: { ...baseSummary().anvandare, aktiva_nu: 2 } }),
    );
    expect(first.boards[0]!.tiles.find((t) => t.label === "Aktiva nu")!.value).toBe("1");
    expect(second.boards[0]!.tiles.find((t) => t.label === "Aktiva nu")!.value).toBe("2");
  });
});
