import { describe, it, expect } from "vitest";
import { VOORBEELDSETS, voorbeeldSetOpId, genereerVoorbeeldFinaal } from "./voorbeeldsets";
import { seedModellen, seedOnderdelen } from "@/data/modeldocumenten";

// ── Voorbeeldsets → finale printklare ontwerpversie ──────────────────────────

const verkoopModel =
  seedModellen.find((m) => m.id === "verkoopakte-heldere-taal") ??
  seedModellen.find((m) => m.taal !== "fr" && m.akteType?.includes("verkoop")) ??
  seedModellen[0];

describe("VOORBEELDSETS", () => {
  it("bevat de gevraagde scenario's met unieke ids", () => {
    const ids = VOORBEELDSETS.map((s) => s.id);
    expect(new Set(ids).size).toBe(ids.length);
    expect(ids).toEqual(
      expect.arrayContaining([
        "huis-brussel",
        "appartement-vlaanderen",
        "grond-wallonie",
        "appartement-brussel",
        "verkoop-lijfrente",
        "schenking-woning-vlaanderen",
      ])
    );
  });

  it("elke expliciete set-hypothese verwijst naar een bestaand onderdeel én variant", () => {
    for (const set of VOORBEELDSETS) {
      for (const h of set.hypotheses ?? []) {
        const onderdeel = seedOnderdelen.find((o) => o.id === h.onderdeelId);
        expect(onderdeel, `${set.id}: onderdeel "${h.onderdeelId}" bestaat niet`).toBeDefined();
        expect(
          onderdeel!.varianten.some((v) => v.id === h.variantId),
          `${set.id}: variant "${h.variantId}" bestaat niet op "${h.onderdeelId}"`
        ).toBe(true);
      }
    }
  });

  it("voorbeeldSetOpId vindt een set en geeft undefined voor een onbekende", () => {
    expect(voorbeeldSetOpId("grond-wallonie")?.naam).toContain("Wallonië");
    expect(voorbeeldSetOpId("bestaat-niet")).toBeUndefined();
  });
});

describe("genereerVoorbeeldFinaal", () => {
  const set = voorbeeldSetOpId("huis-brussel")!;
  const finaal = genereerVoorbeeldFinaal(verkoopModel, seedOnderdelen, set);

  it("laat geen onbesliste hypothese-keuzemarkering achter (printklaar)", () => {
    expect(finaal).not.toContain("KIES DE TOEPASSELIJKE HYPOTHESE");
    expect(finaal).not.toContain("▸ HYPOTHESE");
  });

  it("laat geen inline [KIES: …]/[CHOISIR: …]-blok en geen nakijk-markering achter", () => {
    expect(finaal).not.toMatch(/\[(?:KIES|CHOISIR):/);
    expect(finaal).not.toContain("NAKIJKEN OF SCHRAPPEN");
  });

  it("vult alle {{parameters}} in (geen [AAN TE VULLEN] meer)", () => {
    expect(finaal).not.toContain("AAN TE VULLEN");
    expect(finaal).not.toMatch(/\{\{[^}]+\}\}/);
  });

  it("weerspiegelt de scenario-waarden (adres/prijs van de set)", () => {
    expect(finaal).toContain("675.000,00 EUR");
    expect(finaal.toLowerCase()).toContain("elsene");
  });

  it("genereert voor elke set een niet-lege finale zonder te crashen", () => {
    for (const s of VOORBEELDSETS) {
      const doc = genereerVoorbeeldFinaal(verkoopModel, seedOnderdelen, s);
      expect(doc.length).toBeGreaterThan(200);
      expect(doc).not.toContain("KIES DE TOEPASSELIJKE HYPOTHESE");
    }
  });
});

describe("expliciete set-hypotheses (lijfrente)", () => {
  const lijfrenteModel = seedModellen.find((m) => m.id === "verkoopakte-lijfrente");
  const lijfrenteModelFr = seedModellen.find((m) => m.id === "verkoopakte-lijfrente-fr");
  const set = voorbeeldSetOpId("verkoop-lijfrente")!;

  it("kiest de expliciete hypotheses (met bouquet + vruchtgebruik) i.p.v. de eerste variant", () => {
    if (!lijfrenteModel) return; // model (nog) niet in de seed — dan is er niets te kiezen
    const finaal = genereerVoorbeeldFinaal(lijfrenteModel, seedOnderdelen, set);
    // "met-bouquet" gekozen: het bouquetbedrag van de set staat erin.
    expect(finaal).toContain("80.000,00 EUR");
    // "vruchtgebruik" gekozen (NIET de eerste variant "vrij"): de finale spreekt
    // over voorbehoud van vruchtgebruik.
    expect(finaal.toLowerCase()).toContain("vruchtgebruik");
    expect(finaal).not.toContain("▸ HYPOTHESE");
  });

  it("past dezelfde NL-hypothese-ids toe op de FR-spiegel (via vertalingVanId)", () => {
    if (!lijfrenteModelFr) return;
    const finaal = genereerVoorbeeldFinaal(lijfrenteModelFr, seedOnderdelen, set);
    expect(finaal.toLowerCase()).toContain("usufruit");
    expect(finaal).not.toContain("▸ HYPOTH");
  });
});

describe("nieuwe sets — schone finale op hun natuurlijke model", () => {
  it("schenking-woning-vlaanderen levert een schone finale op de schenkingsakte", () => {
    const model = seedModellen.find((m) => m.id === "schenkingsakte-onroerend");
    if (!model) return;
    const finaal = genereerVoorbeeldFinaal(model, seedOnderdelen, voorbeeldSetOpId("schenking-woning-vlaanderen")!);
    expect(finaal).not.toContain("KIES DE TOEPASSELIJKE HYPOTHESE");
    expect(finaal).not.toContain("AAN TE VULLEN");
    expect(finaal.toLowerCase()).toContain("vruchtgebruik");
  });

  it("appartement-brussel levert de Brusselse waarden in de finale", () => {
    const finaal = genereerVoorbeeldFinaal(verkoopModel, seedOnderdelen, voorbeeldSetOpId("appartement-brussel")!);
    expect(finaal).toContain("385.000,00 EUR");
    expect(finaal.toLowerCase()).toContain("schaarbeek");
    expect(finaal).not.toContain("KIES DE TOEPASSELIJKE HYPOTHESE");
  });

  it("wet-breyne-nieuwbouw kiest de Breyne-hypotheses op het Breyne-compromis", () => {
    const model = seedModellen.find((m) => m.id === "verkoopovereenkomst-compromis-wet-breyne");
    if (!model) return;
    const finaal = genereerVoorbeeldFinaal(model, seedOnderdelen, voorbeeldSetOpId("wet-breyne-nieuwbouw")!);
    expect(finaal).not.toContain("▸ HYPOTHESE");
    expect(finaal).not.toContain("AAN TE VULLEN");
    // Ook de vrije-vorm keuze-instructies ("[KIES - indien …]"), werknoten
    // ([NAKIJKEN…]) en slash-alternatieven ("[ / …]") zijn weg.
    expect(finaal).not.toMatch(/\[(?:KIES|CHOISIR|NAKIJKEN)\b/);
    expect(finaal).not.toMatch(/\[\s*\//);
    // Expliciete hypotheses zichtbaar: bankwaarborg + prijsherzieningsformule.
    expect(finaal).toContain("KBC Bank NV");
    expect(finaal).toContain("p = P (0,20 + 0,30 s/S + 0,50 i/I)");
  });

  it("woning-verhuurd kiest de verhuurd-hypothese via het gebruik-kenmerk", () => {
    const finaal = genereerVoorbeeldFinaal(verkoopModel, seedOnderdelen, voorbeeldSetOpId("woning-verhuurd")!);
    expect(finaal.toLowerCase()).toContain("verhuur");
    expect(finaal).not.toContain("KIES DE TOEPASSELIJKE HYPOTHESE");
  });

  it("schenking-meerdere-begiftigden neemt de aanwas tussen begiftigden op", () => {
    const model = seedModellen.find((m) => m.id === "schenkingsakte-onroerend");
    if (!model) return;
    const finaal = genereerVoorbeeldFinaal(model, seedOnderdelen, voorbeeldSetOpId("schenking-meerdere-begiftigden")!);
    expect(finaal.toLowerCase()).toContain("aanwas");
    expect(finaal).not.toContain("KIES DE TOEPASSELIJKE HYPOTHESE");
    expect(finaal).not.toContain("AAN TE VULLEN");
  });
});
