import { describe, it, expect } from "vitest";
import { euroVolledig } from "@/lib/format";
import {
  dossierNaarParameterwaarden,
  dossierNaarPartijHerhalingen,
  dossierNaarKeuzes,
} from "./parameters";
import { maakVeld, type Dossier, type Partij } from "./types";

function maakDossier(overschrijf: Partial<Dossier> = {}): Dossier {
  const verkoper: Partij = {
    naam: "Janssens",
    voornaam: "Marie",
    geboortedatum: "1980-03-15",
    rijksregisternummer: "80031512345",
    adres: "Kerkstraat 1, 3080 Tervuren",
    rol: "verkoper",
  };
  const koper: Partij = { naam: "Peeters", voornaam: "Jan", rol: "koper" };
  return {
    id: "d1",
    dossiertype: "verkoop-zonder-krediet",
    status: "compromis-ontvangen",
    partijen: maakVeld([verkoper, koper], "compromis"),
    goed: maakVeld(
      { adres: "Brusselsesteenweg 100, 3080 Tervuren", kadastraleGegevens: "Afd. 1, sectie A, nr. 123" },
      "kadastraal-uittreksel"
    ),
    prijs: maakVeld(350000, "compromis"),
    ontbrekendeStukken: [],
    tegenstrijdigheden: [],
    aangemaakt: "2026-06-01T00:00:00.000Z",
    aangepast: "2026-06-01T00:00:00.000Z",
    ...overschrijf,
  } as Dossier;
}

describe("dossierNaarParameterwaarden", () => {
  it("vult rolgebonden namen in voor verkoper en koper", () => {
    const w = dossierNaarParameterwaarden(maakDossier());
    expect(w.naam_verkoper).toBe("Marie Janssens");
    expect(w.naam_vervreemder).toBe("Marie Janssens");
    expect(w.naam_koper).toBe("Jan Peeters");
    // Partij 1/2 voor de elektronische-communicatie-/woonplaatskeuzeclausules.
    expect(w.partij_1).toBe("Marie Janssens");
    expect(w.partij_2).toBe("Jan Peeters");
    // Ondertekenaars van het compromis = alle partijen.
    expect(w.naam_ondertekenaar).toBe("Marie Janssens, Jan Peeters");
  });

  it("vult de generieke identificatie in bij een enige verkoper (ACHTERNAAM hoofdletters + voornamen)", () => {
    const w = dossierNaarParameterwaarden(maakDossier());
    expect(w.naam).toBe("JANSSENS Marie");
    expect(w.naam_voluit).toBe("JANSSENS Marie");
    expect(w.geboortedatum).toBe("15 maart 1980");
    expect(w.rijksregisternummer).toBe("80031512345");
    expect(w.adres).toBe("Kerkstraat 1, 3080 Tervuren");
    // Onbekend geslacht ⇒ de keuze-vorm blijft staan, nooit [AAN TE VULLEN].
    expect(w.aanspreking).toBe("De heer/Mevrouw");
  });

  it("mapt de huwelijksgegevens van een gehuwde enige verkoper (datum voluit)", () => {
    const w = dossierNaarParameterwaarden(
      maakDossier({
        partijen: maakVeld(
          [{ naam: "Janssens", voornaam: "Marie", rol: "verkoper", burgerlijkeStaat: "gehuwd", echtgenoot: "Jan Peeters", huwelijksplaats: "Tervuren", huwelijksdatum: "2010-06-12", huwelijksstelsel: "wettelijk stelsel" }],
          "compromis"
        ),
      })
    );
    expect(w.naam_echtgenoot).toBe("Jan Peeters");
    expect(w.plaats_huwelijk).toBe("Tervuren");
    expect(w.datum_huwelijk).toBe("12 juni 2010");
    expect(w.huwelijksstelsel).toBe("wettelijk stelsel");
  });

  it("leidt de aanspreking af uit het geslacht van een enige verkoper", () => {
    const vrouw = dossierNaarParameterwaarden(
      maakDossier({
        partijen: maakVeld(
          [{ naam: "Janssens", voornaam: "Marie", rol: "verkoper", geslacht: "vrouw" }],
          "compromis"
        ),
      })
    );
    expect(vrouw.aanspreking).toBe("Mevrouw");

    const man = dossierNaarParameterwaarden(
      maakDossier({
        partijen: maakVeld(
          [{ naam: "Peeters", voornaam: "Jan", rol: "verkoper", geslacht: "man" }],
          "compromis"
        ),
      })
    );
    expect(man.aanspreking).toBe("De heer");
  });

  it("vult géén generieke identificatie in bij meerdere verkopers", () => {
    const v1: Partij = { naam: "A", voornaam: "X", geboortedatum: "1970-01-01", rol: "verkoper" };
    const v2: Partij = { naam: "B", voornaam: "Y", geboortedatum: "1972-02-02", rol: "verkoper" };
    const koper: Partij = { naam: "Peeters", voornaam: "Jan", rol: "koper" };
    const w = dossierNaarParameterwaarden(
      maakDossier({ partijen: maakVeld([v1, v2, koper], "compromis") })
    );
    expect(w.naam_verkoper).toBe("X A, Y B");
    expect(w.naam).toBeUndefined();
    expect(w.geboortedatum).toBeUndefined();
  });

  it("formatteert de prijs op de gangbare aliassen", () => {
    const w = dossierNaarParameterwaarden(maakDossier());
    // Cijfers mét muntsymbool en 2 decimalen, zoals in een akte/compromis
    // naast het bedrag voluit in letters: "€ 350.000,00".
    expect(w.prijs_cijfers).toBe(euroVolledig(350000));
    expect(w.prix_chiffres).toBe(w.prijs_cijfers);
    // Heldere-taal "{{prijs_voluit}} euro ({{prijs_cijfers}})" → bedrag in letters.
    expect(w.prijs_voluit).toBe("driehonderdvijftigduizend");
    expect(w.prijs_letters).toBe("driehonderdvijftigduizend");
  });

  it("vult het adres en een samengestelde beschrijving van het goed in", () => {
    const w = dossierNaarParameterwaarden(maakDossier());
    expect(w.adres_goed).toBe("Brusselsesteenweg 100, 3080 Tervuren");
    expect(w.adres_verkocht_goed).toBe("Brusselsesteenweg 100, 3080 Tervuren");
    expect(w.beschrijving_goed).toContain("Brusselsesteenweg 100");
    expect(w.beschrijving_goed).toContain("Afd. 1, sectie A, nr. 123");
  });

  it("vult geboorteplaats in bij een enige verkoper", () => {
    const w = dossierNaarParameterwaarden(
      maakDossier({
        partijen: maakVeld(
          [{ naam: "Solo", geboorteplaats: "Leuven", rol: "verkoper" }],
          "compromis"
        ),
      })
    );
    expect(w.geboorteplaats).toBe("Leuven");
  });

  it("vult de gesplitste kadastrale gegevens in (sectie, perceelnummer, kadastraal inkomen)", () => {
    const w = dossierNaarParameterwaarden(
      maakDossier({
        goed: maakVeld(
          {
            adres: "Brusselsesteenweg 100, 3080 Tervuren",
            sectie: "A",
            perceelnummer: "123",
            kadastraalInkomen: 850,
          },
          "kadastraal-uittreksel"
        ),
      })
    );
    expect(w.sectie).toBe("A");
    expect(w.perceelnummer).toBe("123");
    expect(w.kadastraal_inkomen).toContain("850");
  });

  it("vult gemeente en afdeling in", () => {
    const w = dossierNaarParameterwaarden(
      maakDossier({
        goed: maakVeld(
          { adres: "Brusselsesteenweg 100, 3080 Tervuren", gemeente: "Tervuren", afdeling: "1e" },
          "kadastraal-uittreksel"
        ),
      })
    );
    expect(w.gemeente).toBe("Tervuren");
    expect(w.afdeling).toBe("1e");
  });

  it("vult het voorschot en het afgeleide saldo in", () => {
    const w = dossierNaarParameterwaarden(
      maakDossier({
        prijs: maakVeld(350000, "compromis"),
        voorschot: maakVeld(35000, "compromis"),
      })
    );
    expect(w.voorschot_cijfers).toContain("35");
    expect(w.saldo_cijfers).toContain("315");
  });

  it("schrijft prijs, voorschot en saldo ook voluit in letters", () => {
    const w = dossierNaarParameterwaarden(
      maakDossier({
        prijs: maakVeld(350000, "compromis"),
        voorschot: maakVeld(35000, "compromis"),
      })
    );
    expect(w.prijs_letters).toBe("driehonderdvijftigduizend");
    expect(w.voorschot_letters).toBe("vijfendertigduizend");
    expect(w.saldo_letters).toBe("driehonderdvijftienduizend");
  });

  it("leidt het saldo niet af wanneer het voorschot de prijs evenaart of overschrijdt", () => {
    const w = dossierNaarParameterwaarden(
      maakDossier({
        prijs: maakVeld(350000, "compromis"),
        voorschot: maakVeld(350000, "compromis"),
      })
    );
    expect(w.voorschot_cijfers).toContain("350");
    expect(w.saldo_cijfers).toBeUndefined();
  });

  it("vult de compromisdatum en het kredietbedrag in", () => {
    const w = dossierNaarParameterwaarden(
      maakDossier({
        compromisdatum: maakVeld("2026-05-12", "compromis"),
        kredietofferte: maakVeld({ bank: "KBC", bedrag: 280000, aanvaard: true }, "kredietofferte"),
      })
    );
    expect(w.datum_onderhandse_overeenkomst).toBe("12 mei 2026");
    expect(w.datum_overeenkomst).toBe("12 mei 2026");
    expect(w.kredietbedrag).toContain("280");
  });

  it("vult de kantoorgegevens (standplaats, plaats ondertekening, notaris) in", () => {
    const w = dossierNaarParameterwaarden(maakDossier());
    expect(w.standplaats).toBe("Tervuren");
    expect(w.plaats_ondertekening).toBe("Tervuren");
    expect(w.naam_notaris).toBeTruthy();
  });

  it("mapt de kantoorreferentie naar dossiernummer en referte", () => {
    const w = dossierNaarParameterwaarden(maakDossier({ referentie: "2026/0123" }));
    expect(w.dossiernummer).toBe("2026/0123");
    expect(w.referte).toBe("2026/0123");
  });

  it("mapt de kadastrale oppervlakte (niet die volgens titel)", () => {
    const w = dossierNaarParameterwaarden(
      maakDossier({ goed: maakVeld({ adres: "X", oppervlakte: 540 }, "kadastraal-uittreksel") })
    );
    expect(w.oppervlakte_recent_kadaster).toBe("540 m²");
    expect(w.oppervlakte_titel).toBeUndefined();
  });

  it("kadastrale aanduiding volgens titel en recent uittreksel: apart formaat, dezelfde oppervlakte → 'dezelfde oppervlakte'/'la même superficie' (Avenue des Cormorans)", () => {
    const w = dossierNaarParameterwaarden(
      maakDossier({
        goed: maakVeld(
          {
            adres: "Avenue des Cormorans 32",
            gemeente: "Woluwe-Saint-Pierre",
            sectie: "B",
            perceelnummer: "0060F22P0000",
            sectieTitel: "B",
            perceelnummerTitel: "60 F 22",
            oppervlakte: 450,
            oppervlakteTitel: "4a 50ca",
          },
          "kadastraal-uittreksel"
        ),
      })
    );
    expect(w.sectie_titel).toBe("B");
    expect(w.numero_cadastral_titre).toBe("60 F 22");
    expect(w.sectie_recent_kadaster).toBe("B");
    expect(w.numero_cadastral_extrait_recent).toBe("0060F22P0000");
    expect(w.superficie_titre).toBe("4a 50ca");
    expect(w.oppervlakte_recent_kadaster_vermelding).toBe("dezelfde oppervlakte");
    expect(w.superficie_extrait_recent_mention).toBe("la même superficie");
  });

  it("kadastrale aanduiding: geen sectieTitel/perceelnummerTitel aangeleverd → blijft open (geen gok dat titel en recent uittreksel identiek zijn)", () => {
    const w = dossierNaarParameterwaarden(
      maakDossier({
        goed: maakVeld({ adres: "X", sectie: "B", perceelnummer: "123/A" }, "kadastraal-uittreksel"),
      })
    );
    expect(w.sectie_titel).toBeUndefined();
    expect(w.numero_cadastral_titre).toBeUndefined();
    expect(w.sectie_recent_kadaster).toBe("B");
    expect(w.numero_cadastral_extrait_recent).toBe("123/A");
  });

  it("kadastrale aanduiding: verschillende oppervlakte tussen titel en recent uittreksel → beide expliciet vermeld", () => {
    const w = dossierNaarParameterwaarden(
      maakDossier({
        goed: maakVeld({ adres: "X", oppervlakte: 455, oppervlakteTitel: "4a 50ca" }, "kadastraal-uittreksel"),
      })
    );
    expect(w.oppervlakte_recent_kadaster_vermelding).toBe("een oppervlakte volgens recent kadastraal uittreksel van 455 m²");
    expect(w.superficie_extrait_recent_mention).toBe("une superficie selon extrait cadastral récent de 455 m²");
  });

  it("mapt de attesten (EPC, bodem, elektrische keuring) met datums voluit", () => {
    const w = dossierNaarParameterwaarden(
      maakDossier({
        attesten: {
          epc: { datum: "2025-09-01", nummer: "EPC-123", label: "C", geldigTot: "2035-09-01" },
          bodem: { datum: "2026-04-15", inhoud: "blanco" },
          elektrischeKeuring: { organisme: "BTV", datum: "2026-04-20", conclusie: "niet conform" },
        },
      })
    );
    expect(w.datum_epc).toBe("1 september 2025");
    expect(w.nummer_epc).toBe("EPC-123");
    expect(w.label_epc).toBe("C");
    expect(w.geldigheid_epc).toBe("1 september 2035");
    expect(w.datum_bodemattest).toBe("15 april 2026");
    expect(w.inhoud_bodemattest).toBe("blanco");
    expect(w.keuringsorganisme).toBe("BTV");
    expect(w.datum_keuring).toBe("20 april 2026");
    expect(w.conclusie_keuring).toBe("niet conform");
  });

  it("mapt stedenbouw, asbest en overstroming naar hun parameters", () => {
    const w = dossierNaarParameterwaarden(
      maakDossier({
        attesten: {
          stedenbouw: { datum: "2026-04-10", bestemming: "woongebied", vergunningen: "vergund geacht" },
          asbest: { datum: "2026-03-01", nummer: "ASB-123", conclusie: "veilig beheersbaar" },
          overstroming: { pScore: "A", gScore: "B" },
        },
      })
    );
    expect(w.datum_inlichtingen).toBe("10 april 2026");
    expect(w.bestemming).toBe("woongebied");
    expect(w.vergunningen).toBe("vergund geacht");
    expect(w.datum_asbestattest).toBe("1 maart 2026");
    expect(w.nummer_asbestattest).toBe("ASB-123");
    expect(w.conclusie_asbestattest).toBe("veilig beheersbaar");
    expect(w.p_score).toBe("A");
    expect(w.g_score).toBe("B");
  });

  it("de uiterste aktedatum is een vaste standaardtermijn in de clausuletekst, geen berekende parameter", () => {
    // "Binnen vier maanden na de ondertekening van deze overeenkomst door alle
    // partijen" staat vast in de clausule (heldere-taal.ts) — er wordt geen
    // absolute datum meer berekend of ingevuld.
    const compromis = dossierNaarParameterwaarden(
      maakDossier({ verkoopdocument: "compromis", compromisdatum: maakVeld("2026-05-12", "compromis") })
    );
    expect(compromis.uiterste_datum_akte).toBeUndefined();
    expect(compromis.date_limite_acte).toBeUndefined();
  });

  it("mapt één te royeren hypothecaire last naar schuldeiser en bedrag", () => {
    const w = dossierNaarParameterwaarden(
      maakDossier({
        hypothecaireLasten: maakVeld(
          [{ schuldeiser: "ING", bedrag: 120000, moetGeroyeerdWorden: true }],
          "hypotheekattest"
        ),
      })
    );
    expect(w.naam_schuldeiser).toBe("ING");
    expect(w.bedrag_inschrijving).toContain("120");
  });

  it("mapt geen hypothecaire last bij meerdere te royeren inschrijvingen", () => {
    const w = dossierNaarParameterwaarden(
      maakDossier({
        hypothecaireLasten: maakVeld(
          [
            { schuldeiser: "ING", bedrag: 120000, moetGeroyeerdWorden: true },
            { schuldeiser: "KBC", bedrag: 80000, moetGeroyeerdWorden: true },
          ],
          "hypotheekattest"
        ),
      })
    );
    expect(w.naam_schuldeiser).toBeUndefined();
    expect(w.bedrag_inschrijving).toBeUndefined();
  });

  it("vult de vennootschapsgegevens in op hun parameternamen", () => {
    const w = dossierNaarParameterwaarden(
      maakDossier({
        dossiertype: "aanpassing-statuten-vennootschap",
        partijen: maakVeld([], "manueel"),
        goed: undefined,
        prijs: undefined,
        vennootschap: maakVeld(
          { naam: "Tervuren BV", zetel: "Stationsstraat 1, 3080 Tervuren", ondernemingsnummer: "0123.456.789" },
          "manueel"
        ),
      })
    );
    expect(w.benaming).toBe("Tervuren BV");
    expect(w.benaming_vennootschap).toBe("Tervuren BV");
    expect(w.zetel_vennootschap).toBe("Stationsstraat 1, 3080 Tervuren");
    expect(w.ondernemingsnummer).toBe("0123.456.789");
  });

  it("vult naam_partner en namen_kinderen in op basis van de testamentrelatie", () => {
    const erflater: Partij = { naam: "Janssens", voornaam: "Marie", rol: "erflater" };
    const partner: Partij = { naam: "Peeters", voornaam: "Jan", rol: "erfgenaam", testamentRelatie: "partner" };
    const kind1: Partij = { naam: "Janssens", voornaam: "Lucas", rol: "erfgenaam", testamentRelatie: "kind" };
    const kind2: Partij = { naam: "Janssens", voornaam: "Emma", rol: "erfgenaam", testamentRelatie: "kind" };
    const w = dossierNaarParameterwaarden(
      maakDossier({
        dossiertype: "keuzetestament",
        partijen: maakVeld([erflater, partner, kind1, kind2], "manueel"),
        goed: undefined,
        prijs: undefined,
      })
    );
    expect(w.naam_partner).toBe("Jan Peeters");
    expect(w.namen_kinderen).toBe("Lucas Janssens, Emma Janssens");
  });

  it("laat onbekende velden weg (geen lege waarden)", () => {
    const w = dossierNaarParameterwaarden(
      maakDossier({
        partijen: maakVeld([{ naam: "Solo", rol: "verkoper" }], "compromis"),
        prijs: maakVeld(0, "compromis"),
        goed: maakVeld({ adres: "" }, "manueel"),
      })
    );
    expect(w.geboortedatum).toBeUndefined();
    expect(w.geboorteplaats).toBeUndefined();
    expect(w.prijs_cijfers).toBeUndefined();
    expect(w.adres_goed).toBeUndefined();
    expect(w.sectie).toBeUndefined();
    expect(w.perceelnummer).toBeUndefined();
    expect(w.kadastraal_inkomen).toBeUndefined();
    expect(w.naam_verkoper).toBe("Solo");
  });

  it("mapt de commerciële naam van het bemiddelende vastgoedkantoor (NL + FR), nooit een gok bij ontbreken", () => {
    const met = dossierNaarParameterwaarden(maakDossier({ makelaarNaam: "ENGEL & VÖLKERS" }));
    expect(met.makelaar_naam).toBe("ENGEL & VÖLKERS");
    expect(met.nom_agence_immobiliere).toBe("ENGEL & VÖLKERS");
    const zonder = dossierNaarParameterwaarden(maakDossier());
    expect(zonder.makelaar_naam).toBeUndefined();
    expect(zonder.nom_agence_immobiliere).toBeUndefined();
  });

  it("houdt cijfers en letters op hetzelfde bedrag: de 10%-waarborg-default wordt op hele euro's afgerond", () => {
    // Regressie: prijs 425.555 gaf een waarborg-default van 42.555,50 in
    // cijfers, maar "tweeënveertigduizend vijfhonderdvijfenvijftig" in letters
    // (getalInLetters negeert centen) — in een akte primeren de letters, dus
    // beweerden cijfers en letters een ANDER bedrag.
    const w = dossierNaarParameterwaarden(maakDossier({ prijs: maakVeld(425555, "compromis") }));
    expect(w.bedrag_waarborg).toBe(euroVolledig(42556)); // afgeronde default
    expect(w.bedrag_waarborg_voluit).toContain("tweeënveertigduizend vijfhonderdzesenvijftig");
    expect(w.saldo_prijs).toBe(euroVolledig(425555 - 42556));
  });

  it("laat het bedrag in letters OPEN bij een niet-geheel bedrag (nooit een fout bedrag beweren)", () => {
    const w = dossierNaarParameterwaarden(
      maakDossier({ prijs: maakVeld(300000, "compromis"), voorschot: maakVeld(29999.5, "compromis") })
    );
    // Cijfers exact (mét centen), letters bewust afwezig.
    expect(w.voorschot_cijfers).toBe("29.999,50");
    expect(w.voorschot_letters).toBeUndefined();
    expect(w.bedrag_waarborg).toBe(euroVolledig(29999.5));
    expect(w.bedrag_waarborg_voluit).toBeUndefined();
    expect(w.saldo_cijfers).toBe("270.000,50");
    expect(w.saldo_letters).toBeUndefined();
  });
});

describe("dossierNaarPartijHerhalingen", () => {
  it("bouwt één herhaling per partij, met rol+naam als label en gekende waarden", () => {
    const h = dossierNaarPartijHerhalingen(maakDossier());
    expect(h).toHaveLength(2);
    expect(h[0].label).toBe("VERKOPER — Marie Janssens");
    expect(h[0].waarden.naam_voluit).toBe("JANSSENS Marie");
    expect(h[0].waarden.geboortedatum).toBe("15 maart 1980");
    expect(h[0].waarden.adres).toBe("Kerkstraat 1, 3080 Tervuren");
    expect(h[1].label).toBe("KOPER — Jan Peeters");
    expect(h[1].waarden.naam_voluit).toBe("PEETERS Jan");
    // Onbekende velden ontbreken (worden later [AAN TE VULLEN]).
    expect(h[1].waarden.geboortedatum).toBeUndefined();
  });

  it("gebruikt de rol als label wanneer de naam onbekend is", () => {
    const h = dossierNaarPartijHerhalingen(
      maakDossier({ partijen: maakVeld([{ naam: "", rol: "schenker" }], "compromis") })
    );
    expect(h[0].label).toBe("SCHENKER");
  });

  it("zet de burgerlijke staat van de partij als variantId, voor automatische hypothesekeuze", () => {
    const v1: Partij = { naam: "A", rol: "verkoper", burgerlijkeStaat: "gehuwd" };
    const koper: Partij = { naam: "Peeters", rol: "koper" };
    const h = dossierNaarPartijHerhalingen(
      maakDossier({ partijen: maakVeld([v1, koper], "compromis") })
    );
    expect(h[0].variantId).toBe("gehuwd");
    expect(h[1].variantId).toBeUndefined();
  });
});

describe("dossierNaarKeuzes", () => {
  it("kiest de gewest-variant van de administratieve attesten", () => {
    const k = dossierNaarKeuzes(maakDossier(), "Vlaanderen");
    expect(k).toContainEqual({ onderdeelId: "administratieve-attesten", variantId: "vlaanderen" });
    const kBrussel = dossierNaarKeuzes(maakDossier(), "Brussel");
    expect(kBrussel).toContainEqual({ onderdeelId: "administratieve-attesten", variantId: "brussel" });
  });

  it("kiest de beschrijvingsvariant op basis van het goedtype", () => {
    const woning = dossierNaarKeuzes(
      maakDossier({ goed: maakVeld({ adres: "x", type: "woning" }, "manueel") }),
      "Vlaanderen"
    );
    expect(woning).toContainEqual({ onderdeelId: "beschrijving-onroerend-goed", variantId: "huis" });
    const appartement = dossierNaarKeuzes(
      maakDossier({ goed: maakVeld({ adres: "x", type: "appartement" }, "manueel") }),
      "Vlaanderen"
    );
    expect(appartement).toContainEqual({
      onderdeelId: "beschrijving-onroerend-goed",
      variantId: "appartement-mede-eigendom",
    });
  });

  it("toont de hypothecaire-inschrijvingvariant enkel bij een te royeren last", () => {
    const zonder = dossierNaarKeuzes(maakDossier(), "Vlaanderen");
    expect(zonder).toContainEqual({ onderdeelId: "hypothecaire-toestand", variantId: "__geen-variant__" });
    const met = dossierNaarKeuzes(
      maakDossier({ hypothecaireLasten: maakVeld([{ schuldeiser: "KBC", bedrag: 100000, moetGeroyeerdWorden: true }], "hypotheekattest") }),
      "Vlaanderen"
    );
    expect(met).toContainEqual({ onderdeelId: "hypothecaire-toestand", variantId: "bestaande-inschrijving" });
  });

  it("toont standaard enkel de gewone betalingsregeling (geen bijzondere prijs-hypotheses)", () => {
    expect(dossierNaarKeuzes(maakDossier(), "Vlaanderen")).toContainEqual({ onderdeelId: "prijs-en-betaling", variantId: "__geen-variant__" });
  });

  it("neemt de opschortende voorwaarde van financiering op bij een krediet-dossier", () => {
    const k = dossierNaarKeuzes(maakDossier({ dossiertype: "verkoop-met-krediet" }), "Vlaanderen");
    expect(k).toContainEqual({ onderdeelId: "opschortende-voorwaarde-financiering", opnemen: true });
  });

  it("neemt de opschortende voorwaarde niet op bij een dossier zonder krediet", () => {
    const k = dossierNaarKeuzes(maakDossier({ dossiertype: "verkoop-zonder-krediet" }), "Vlaanderen");
    expect(k.find((o) => o.onderdeelId === "opschortende-voorwaarde-financiering")).toBeUndefined();
  });

  it("kiest de risico-verzekeringsvariant op basis van het goedtype", () => {
    const woning = dossierNaarKeuzes(
      maakDossier({ goed: maakVeld({ adres: "x", type: "woning" }, "manueel") }),
      "Vlaanderen"
    );
    expect(woning).toContainEqual({ onderdeelId: "risico-verzekering", variantId: "huis" });
    const appartement = dossierNaarKeuzes(
      maakDossier({ goed: maakVeld({ adres: "x", type: "appartement" }, "manueel") }),
      "Vlaanderen"
    );
    expect(appartement).toContainEqual({ onderdeelId: "risico-verzekering", variantId: "mede-eigendom" });
    const grond = dossierNaarKeuzes(
      maakDossier({ goed: maakVeld({ adres: "x", type: "grond" }, "manueel") }),
      "Vlaanderen"
    );
    expect(grond).toContainEqual({ onderdeelId: "risico-verzekering", variantId: "grond" });
  });

  it("kiest geen risico-verzekeringsvariant bij een onbekend of 'ander' goedtype", () => {
    const ander = dossierNaarKeuzes(
      maakDossier({ goed: maakVeld({ adres: "x", type: "ander" }, "manueel") }),
      "Vlaanderen"
    );
    expect(ander.find((o) => o.onderdeelId === "risico-verzekering")).toBeUndefined();
  });

  it("dwingt 'niet van toepassing' af voor de keuring elektrische installatie bij een niet-woongelegenheid (grond/ander), ook zonder keuringsverslag", () => {
    const grond = dossierNaarKeuzes(maakDossier({ goed: maakVeld({ adres: "x", type: "grond" }, "manueel") }), "Vlaanderen");
    expect(grond).toContainEqual({ onderdeelId: "ht-elektrische-keuring", variantId: "keuring-niet-van-toepassing" });
    expect(grond).toContainEqual({ onderdeelId: "ht-elektrische-keuring-fr", variantId: "keuring-niet-van-toepassing" });
  });

  it("laat de keuring elektrische installatie open bij een woning zonder keuringsverslag (nooit gokken)", () => {
    const woning = dossierNaarKeuzes(maakDossier({ goed: maakVeld({ adres: "x", type: "woning" }, "manueel") }), "Vlaanderen");
    expect(woning.find((o) => o.onderdeelId === "ht-elektrische-keuring")).toBeUndefined();
  });

  it("onderdrukt de generieke 'facultatief onderdeel'-markering voor de gewestelijke registratiebelasting-clausule zodra het gewest gekend is (§43)", () => {
    const brussel = dossierNaarKeuzes(maakDossier(), "Brussel");
    expect(brussel).toContainEqual({ onderdeelId: "ht-registratiebelasting-brussel-wallonie", opnemen: true, conditieBevestigd: true, variantId: "bruxelles" });
    const vlaanderen = dossierNaarKeuzes(maakDossier(), "Vlaanderen");
    expect(vlaanderen).toContainEqual({ onderdeelId: "ht-registratiebelasting-brussel-wallonie", opnemen: false, conditieBevestigd: true, variantId: "bruxelles" });
  });
});

describe("identiteitsblok — canonieke clausule 'identiteit-partijen'/'identiteit-partijen-fr'", () => {
  const ontdaan = (s: string) => s.replace(/[]/g, ""); // vet-markers weghalen

  it("standaardformaat (enige partij, geen overbodig volgnummer): aanspreking + NAAM (hoofdletters, vet) + voornamen, geboorte/rijksregister/burgerlijke staat/woonplaats, huwelijksgegevens op een NIEUWE alinea, afgesloten met een verklaring", () => {
    const d = maakDossier({
      partijen: maakVeld(
        [{ naam: "peeters", voornaam: "Jan Pieter", rol: "verkoper", geslacht: "man", burgerlijkeStaat: "gehuwd", huwelijksstelsel: "scheiding van goederen", geboorteplaats: "Mechelen", geboortedatum: "1965-02-20", adres: "Kerkstraat 8" }],
        "compromis"
      ),
    });
    const w = dossierNaarParameterwaarden(d);
    // Eén partij/koppel krijgt geen volgnummer (overbodig).
    expect(w.identiteit_verkopers).not.toMatch(/^\d+\. /);
    // Naam vet gemarkeerd, eerste regel = identiteit + woonplaats.
    const eersteRegel = ontdaan(w.identiteit_verkopers).split("\n\n")[0];
    expect(w.identiteit_verkopers).toContain("PEETERS Jan Pieter");
    expect(eersteRegel).toBe("De heer PEETERS Jan Pieter, geboren te Mechelen op 20 februari 1965, ingeschreven in het rijksregister onder nummer [AAN TE VULLEN: rijksregisternummer], wonende te Kerkstraat 8.");
    // Huwelijksgegevens op een nieuwe alinea, afgesloten met de verklaring (enkelvoud, mannelijk).
    const tweedeRegel = ontdaan(w.identiteit_verkopers).split("\n\n")[1];
    expect(tweedeRegel).toContain("Gehuwd met [AAN TE VULLEN: naam_echtgenoot], te [AAN TE VULLEN: plaats_huwelijk]");
    expect(tweedeRegel).toContain("onder het stelsel van scheiding van goederen");
    expect(tweedeRegel).toMatch(/zoals hij verklaart\.$/);
  });

  it("FR: Monsieur/Madame (vet) + née/inscrite/domiciliée naar het gekende geslacht + état civil en bref", () => {
    const d = maakDossier({
      partijen: maakVeld(
        [{ naam: "janssens", voornaam: "Anna", rol: "koper", geslacht: "vrouw", burgerlijkeStaat: "ongehuwd", geboorteplaats: "Leuven", geboortedatum: "1990-01-01", rijksregisternummer: "90010112345", adres: "Veldweg 22" }],
        "compromis"
      ),
    });
    const w = dossierNaarParameterwaarden(d);
    // Bij een gekend geslacht lost de keten de Franse tweevormen op ("née"
    // i.p.v. "né(e)" — werf "voorbeeld volgt echte workflow", 2026-07-11);
    // enkel bij onbekend geslacht blijft de "(e)"-vorm staan (zie test hierna).
    expect(ontdaan(w.identite_acquereurs)).toBe(
      "Madame JANSSENS Anna, née à Leuven le 1 janvier 1990, inscrite au registre national sous le numéro 90010112345, non mariée et n'ayant pas fait de déclaration de cohabitation légale, domiciliée à Veldweg 22."
    );
    expect(w.identite_acquereurs).toContain("JANSSENS Anna");
  });

  it("FR: bij ONBEKEND geslacht blijven de né(e)-tweevormen staan (nooit gokken)", () => {
    const d = maakDossier({
      partijen: maakVeld(
        [{ naam: "janssens", voornaam: "Anna", rol: "koper", burgerlijkeStaat: "ongehuwd", geboorteplaats: "Leuven", geboortedatum: "1990-01-01", rijksregisternummer: "90010112345", adres: "Veldweg 22" }],
        "compromis"
      ),
    });
    const w = dossierNaarParameterwaarden(d);
    expect(w.identite_acquereurs).toContain("né(e) à Leuven");
  });

  it("een gehuwd koppel dat SAMEN als partij optreedt komt op één gemeenschappelijke regel, zonder volgnummer, beide namen vet, verklaring in het meervoud", () => {
    const d = maakDossier({
      partijen: maakVeld(
        [
          { naam: "PEETERS", voornaam: "Jan", rol: "verkoper", geslacht: "man", burgerlijkeStaat: "gehuwd", echtgenoot: "MAES Lotte", huwelijksplaats: "Leuven", huwelijksdatum: "1990-06-01", huwelijksstelsel: "scheiding van goederen", geboorteplaats: "Mechelen", geboortedatum: "1965-02-20", adres: "Kerkstraat 8, 3080 Tervuren" },
          { naam: "MAES", voornaam: "Lotte", rol: "verkoper", geslacht: "vrouw", burgerlijkeStaat: "gehuwd", echtgenoot: "PEETERS Jan", huwelijksplaats: "Leuven", huwelijksdatum: "1990-06-01", huwelijksstelsel: "scheiding van goederen", geboorteplaats: "Leuven", geboortedatum: "1967-03-03", adres: "Kerkstraat 8, 3080 Tervuren" },
        ],
        "compromis"
      ),
    });
    const w = dossierNaarParameterwaarden(d).identiteit_verkopers;
    expect(w).not.toMatch(/^\d+\. /); // één koppel = geen overbodig volgnummer
    expect(w).toContain("PEETERS Jan"); // beide namen vet, want beiden zijn partij
    expect(w).toContain("MAES Lotte");
    expect(ontdaan(w)).toContain("zijn echtgenote, Mevrouw MAES Lotte");
    expect(ontdaan(w)).toContain("samenwonend te Kerkstraat 8, 3080 Tervuren"); // gedeeld adres, eenmaal
    expect(ontdaan(w)).toMatch(/zoals zij verklaren\.$/); // verklaring in het meervoud
  });

  it("een wettelijk-samenwonend koppel (geen combinatievariant) staat als twee afzonderlijke, genummerde regels — elk netjes afgewerkt, niet aaneengeplakt", () => {
    const d = maakDossier({
      partijen: maakVeld(
        [
          { naam: "janssens", voornaam: "Anna", rol: "koper", geslacht: "vrouw", burgerlijkeStaat: "wettelijk-samenwonend", echtgenoot: "Koen JANSSENS", adres: "Veldweg 22" },
          { naam: "janssens", voornaam: "Koen", rol: "koper", geslacht: "man", burgerlijkeStaat: "wettelijk-samenwonend", echtgenoot: "Anna JANSSENS", adres: "Veldweg 22" },
        ],
        "compromis"
      ),
    });
    const w = ontdaan(dossierNaarParameterwaarden(d).identiteit_kopers);
    expect(w.split("\n\n")).toHaveLength(4); // elke partij: identiteit + samenwoonalinea, telkens gescheiden
    expect(w).toContain("1. Mevrouw JANSSENS Anna");
    expect(w).toContain("2. De heer JANSSENS Koen");
    expect(w).toContain("Wettelijk samenwonend met Koen JANSSENS");
    expect(w).toContain("Wettelijk samenwonend met Anna JANSSENS");
  });

  it("twee niet-gekoppelde partijen: elk een eigen nummer, elk op een eigen, gescheiden alinea (niet aaneengeplakt)", () => {
    const d = maakDossier({
      partijen: maakVeld(
        [
          { naam: "a", voornaam: "X", rol: "verkoper", geslacht: "man", burgerlijkeStaat: "ongehuwd" },
          { naam: "b", voornaam: "Y", rol: "verkoper", geslacht: "vrouw", burgerlijkeStaat: "ongehuwd" },
        ],
        "compromis"
      ),
    });
    const w = ontdaan(dossierNaarParameterwaarden(d).identiteit_verkopers);
    // Elke partij op haar eigen regel, gescheiden door een lege regel (nieuwe
    // alinea) — nooit na elkaar geplakt op dezelfde regel.
    expect(w.split("\n\n")).toHaveLength(2);
    expect(w).toContain("1. De heer A X");
    expect(w).toContain("2. Mevrouw B Y");
  });

  it("onbekende burgerlijke staat: keuzeblok met alle natuurlijke-persoon-hypotheses (nooit blind gokken)", () => {
    const d = maakDossier({
      partijen: maakVeld([{ naam: "smets", voornaam: "Eva", rol: "koper", geslacht: "vrouw" }], "compromis"),
    });
    const w = dossierNaarParameterwaarden(d).identiteit_kopers;
    expect(w).toContain("[KIES DE TOEPASSELIJKE HYPOTHESE EN SCHRAP DE OVERIGE:]");
    expect(w).toContain("▸ HYPOTHESE — Natuurlijke persoon — ongehuwd");
    expect(w).toContain("▸ HYPOTHESE — Natuurlijke persoon — gehuwd");
    // De rechtspersoon-/notaris-vaststellingshypotheses horen hier niet thuis.
    expect(w).not.toContain("rechtspersoon");
    expect(w).not.toContain("notaris-identificatie");
  });

  it("meerdere opeenvolgende wijzigingen van het huwelijksstelsel worden chronologisch genummerd vermeld (bv. uit een CRH-opzoeking), zonder het oorspronkelijke contract weg te laten", () => {
    const d = maakDossier({
      partijen: maakVeld(
        [
          {
            naam: "peeters", voornaam: "Jan", rol: "verkoper", geslacht: "man", burgerlijkeStaat: "gehuwd",
            echtgenoot: "Anna Maes", huwelijksplaats: "Woluwe-Saint-Lambert", huwelijksdatum: "1985-04-27", huwelijksstelsel: "scheiding van goederen",
            huwelijkscontractNotaris: "Alfons Boone", huwelijkscontractPlaats: "Turnhout", huwelijkscontractDatum: "1985-04-19",
            wijzigingenStelsel: [
              { notaris: "Filip Segers", plaats: "Weelde", datum: "2011-03-31", omschrijving: "met behoud van het stelsel" },
              {
                notaris: "Wim Vanberghen",
                plaats: "Oud-Turnhout",
                datum: "2021-06-03",
                omschrijving: "met toevoeging van een intern gemeenschappelijk vermogen, zonder wijziging van het hoofdstelsel",
              },
            ],
          },
        ],
        "compromis"
      ),
    });
    const w = ontdaan(dossierNaarParameterwaarden(d).identiteit_verkopers);
    // Het oorspronkelijke huwelijkscontract (1985) blijft staan, naast beide latere wijzigingen.
    expect(w).toContain("Alfons Boone");
    expect(w).toContain("19 april 1985");
    expect(w).toContain("een eerste keer gewijzigd");
    expect(w).toContain("Filip Segers");
    expect(w).toContain("Weelde");
    expect(w).toContain("31 maart 2011");
    expect(w).toContain("vervolgens een tweede keer gewijzigd");
    expect(w).toContain("Wim Vanberghen");
    expect(w).toContain("Oud-Turnhout");
    expect(w).toContain("3 juni 2021");
    expect(w).toMatch(/en sindsdien niet meer gewijzigd/);
    expect(w).not.toContain("[AAN TE VULLEN: notaris_wijziging_stelsel]");
    expect(w).not.toContain("[KIES:");
  });

  it("FR: meerdere opeenvolgende wijzigingen van het huwelijksstelsel worden chronologisch genummerd vermeld", () => {
    const d = maakDossier({
      partijen: maakVeld(
        [
          {
            naam: "peeters", voornaam: "Jan", rol: "verkoper", geslacht: "man", burgerlijkeStaat: "gehuwd",
            echtgenoot: "Anna Maes", huwelijksplaats: "Woluwe-Saint-Lambert", huwelijksdatum: "1985-04-27", huwelijksstelsel: "séparation de biens",
            huwelijkscontractNotaris: "Alfons Boone", huwelijkscontractPlaats: "Turnhout", huwelijkscontractDatum: "1985-04-19",
            wijzigingenStelsel: [
              { notaris: "Filip Segers", plaats: "Weelde", datum: "2011-03-31", omschrijving: "avec maintien du régime" },
              {
                notaris: "Wim Vanberghen",
                plaats: "Oud-Turnhout",
                datum: "2021-06-03",
                omschrijving: "avec adjonction d'un patrimoine commun interne, sans modification du régime principal",
              },
            ],
          },
        ],
        "compromis"
      ),
    });
    const w = ontdaan(dossierNaarParameterwaarden(d).identite_vendeurs);
    expect(w).toContain("modifié une première fois");
    expect(w).toContain("avec maintien du régime");
    expect(w).toContain("Filip Segers");
    expect(w).toContain("puis modifié une seconde fois");
    expect(w).toContain("avec adjonction d'un patrimoine commun interne");
    expect(w).toContain("Wim Vanberghen");
    expect(w).toMatch(/et non modifié depuis lors/);
    expect(w).not.toContain("[AAN TE VULLEN: notaris_wijziging_stelsel]");
    expect(w).not.toContain("[CHOISIR:");
  });
});
