import { describe, it, expect } from "vitest";
import { seedModellen, seedOnderdelen, genereerDocument, pasKeuzesToe, standaardKeuzes } from "@/data/modeldocumenten";
import { analyseerKeuzeImpact } from "./keuze-impact";
import { kenmerkenNaarKeuzes, heldereTaalKeuzes, GEEN_VARIANT } from "./kenmerken";
import type { OntwerpKeuze } from "@/lib/handoff";

const compromisNL = seedModellen.find((m) => m.id === "verkoopovereenkomst-heldere-taal")!;

describe("model-engine is deterministisch", () => {
  it("identieke input → byte-identieke output (herhaalde generatie)", () => {
    const keuzes = [...kenmerkenNaarKeuzes({ gewest: "Vlaanderen", goedType: "appartement" }), ...heldereTaalKeuzes({ gewest: "Vlaanderen", goedType: "appartement" })];
    const run = () => genereerDocument(compromisNL, seedOnderdelen, pasKeuzesToe(compromisNL, keuzes), { prijs_cijfers: "€ 100.000" }, []);
    expect(run()).toBe(run());
  });

  it("kenmerkenNaarKeuzes is een zuivere functie (zelfde keuzes bij herhaling)", () => {
    const k = { gewest: "Brussel", goedType: "woning", metKrediet: true } as const;
    expect(kenmerkenNaarKeuzes(k)).toEqual(kenmerkenNaarKeuzes(k));
  });
});

describe("voorzichtig: zonder feiten wordt niets geschrapt", () => {
  it("lege kenmerken → geen enkele hypothese genarrowd, geen verplicht onderdeel weggelaten", () => {
    const impact = analyseerKeuzeImpact(compromisNL, seedOnderdelen, []);
    expect(impact.gekozenHypotheses).toEqual([]);
    // Geen waarschuwingen over geschrapte hypotheses; hooguit over facultatieve
    // onderdelen die standaard niet opgenomen zijn — nooit over verplichte.
    expect(impact.waarschuwingen.some((w) => w.includes("VERPLICHTE"))).toBe(false);
    // Alle onderdelen met meerdere hypotheses blijven ter keuze staan.
    expect(impact.behoudenTerKeuze.length).toBeGreaterThan(0);
  });

  it("standaardkeuzes laten elke variant van een opgenomen onderdeel staan ('alle')", () => {
    const std = standaardKeuzes(compromisNL);
    expect(std.every((k) => k.variantId === "alle")).toBe(true);
  });
});

describe("transparant: elke schrapping/weglating wordt uitdrukkelijk vermeld", () => {
  it("een feit dat een hypothese kiest, rapporteert de geschrapte hypotheses + waarschuwing", () => {
    const keuzes = heldereTaalKeuzes({ gewest: "Vlaanderen" });
    const impact = analyseerKeuzeImpact(compromisNL, seedOnderdelen, keuzes);
    // De energieprestatie-clausule wordt op de Vlaamse variant gezet → andere geschrapt.
    const energie = impact.gekozenHypotheses.find((g) => g.onderdeelId === "ht-energieprestatie");
    expect(energie).toBeDefined();
    expect(energie!.gekozen?.id).toBe("vlaanderen-epc");
    expect(energie!.geschrapt.length).toBeGreaterThan(0);
    expect(impact.waarschuwingen.some((w) => w.includes("Energie") || w.toLowerCase().includes("energiep"))).toBe(true);
  });

  it("GEEN_VARIANT (enkel basistekst) wordt als zodanig gemeld", () => {
    const override: OntwerpKeuze[] = [{ onderdeelId: "ht-mede-eigendom-statuten", variantId: GEEN_VARIANT, opnemen: true }];
    const impact = analyseerKeuzeImpact(compromisNL, seedOnderdelen, override);
    const g = impact.gekozenHypotheses.find((x) => x.onderdeelId === "ht-mede-eigendom-statuten");
    if (g && g.geschrapt.length > 0) {
      expect(g.gekozen).toBeNull();
      expect(impact.waarschuwingen.some((w) => w.includes("basistekst"))).toBe(true);
    }
  });

  it("zonder feit valt geen enkel facultatief onderdeel weg (veiligheid: behouden)", () => {
    const impact = analyseerKeuzeImpact(compromisNL, seedOnderdelen, []);
    expect(impact.weggelatenOnderdelen).toEqual([]);
  });

  it("een facultatief onderdeel dat op basis van een feit wordt geschrapt, levert een waarschuwing op", () => {
    // Een goedType ≠ appartement schrapt de mede-eigendomclausules (feit-gestuurd).
    const keuzes = heldereTaalKeuzes({ goedType: "woning" });
    const impact = analyseerKeuzeImpact(compromisNL, seedOnderdelen, keuzes);
    expect(impact.weggelatenOnderdelen.some((w) => w.reden === "feit")).toBe(true);
    expect(impact.waarschuwingen.some((w) => w.includes("Clausule geschrapt"))).toBe(true);
  });
});
