import { describe, expect, it } from "vitest";
import { seedModellen } from "./index";
import { groepeerPerRechtshandeling, koppelModelParen, onvertaaldeClausules } from "./rechtshandeling";
import { TE_VERTALEN } from "./pariteit";
import type { Modeldocument, Modelonderdeel } from "./types";

function maakModel(deel: Partial<Modeldocument> & { id: string }): Modeldocument {
  return {
    titel: deel.id,
    akteType: "verkoopakte",
    omschrijving: "",
    structuur: [],
    versie: "1.0",
    datum: "2026-07-05",
    ...deel,
  };
}

function maakOnderdeel(deel: Partial<Modelonderdeel> & { id: string }): Modelonderdeel {
  return {
    titel: deel.id,
    categorie: "vorm",
    omschrijving: "",
    tekst: "tekst",
    varianten: [],
    parameters: [],
    toepasbaarOp: [],
    versie: "1.0",
    datum: "2026-07-05",
    ...deel,
  };
}

describe("koppelModelParen", () => {
  it("koppelt FR aan zijn NL-bron en laat losse modellen als eigen paar staan", () => {
    const nl = maakModel({ id: "a" });
    const fr = maakModel({ id: "a-fr", taal: "fr", vertalingVanId: "a" });
    const alleenNl = maakModel({ id: "b" });
    const frZonderBron = maakModel({ id: "c-fr", taal: "fr", vertalingVanId: "c" });
    const paren = koppelModelParen([nl, fr, alleenNl, frZonderBron]);
    expect(paren).toEqual([
      { nl, fr },
      { nl: alleenNl, fr: undefined },
      { fr: frZonderBron },
    ]);
  });
});

describe("groepeerPerRechtshandeling", () => {
  it("groepeert per akteType van het NL-model, alfabetisch, en sorteert binnen de groep op titel", () => {
    const modellen = [
      maakModel({ id: "v2", akteType: "verkoopakte", titel: "Zebra" }),
      maakModel({ id: "s1", akteType: "schenkingsakte", titel: "Schenking" }),
      maakModel({ id: "v1", akteType: "verkoopakte", titel: "Alfa" }),
    ];
    const groepen = groepeerPerRechtshandeling(modellen);
    expect(groepen.map((g) => g.rechtshandeling)).toEqual(["schenkingsakte", "verkoopakte"]);
    expect(groepen[1].paren.map((p) => p.nl!.id)).toEqual(["v1", "v2"]);
  });
});

describe("onvertaaldeClausules", () => {
  const onderdelen = [
    maakOnderdeel({ id: "x" }),
    maakOnderdeel({ id: "x-fr", taal: "fr", vertalingVanId: "x" }),
    maakOnderdeel({ id: "y" }),
    maakOnderdeel({ id: "z-fr", taal: "fr", varianten: [{ id: "v1", hypothese: "h", tekst: `${TE_VERTALEN}\nnog te doen` }] }),
  ];

  it("markeert in een FR-model de NL-onderdelen en de [TE VERTALEN]-onderdelen, niet de vertaalde", () => {
    const fr = maakModel({
      id: "m-fr",
      taal: "fr",
      structuur: [
        { onderdeelId: "x-fr", verplicht: true }, // vertaald
        { onderdeelId: "y", verplicht: true }, // NL-onderdeel hergebruikt → groen
        { onderdeelId: "z-fr", verplicht: true }, // draagt TE VERTALEN → groen
        { onderdeelId: "bestaat-niet", verplicht: true }, // aparte fout (rood), niet groen
      ],
    });
    expect(onvertaaldeClausules(fr, onderdelen)).toEqual(["y", "z-fr"]);
  });

  it("is leeg voor een volledig vertaald model en voor een gewoon NL-model", () => {
    const fr = maakModel({ id: "m-fr", taal: "fr", structuur: [{ onderdeelId: "x-fr", verplicht: true }] });
    const nl = maakModel({ id: "m", structuur: [{ onderdeelId: "x", verplicht: true }, { onderdeelId: "y", verplicht: true }] });
    expect(onvertaaldeClausules(fr, onderdelen)).toEqual([]);
    expect(onvertaaldeClausules(nl, onderdelen)).toEqual([]);
  });
});

describe("seed-bibliotheek — NL en FR lopen gelijk (instructie notaris)", () => {
  it("élk Nederlandstalig seed-model heeft een Franstalige spiegel", () => {
    const zonderFr = koppelModelParen(seedModellen)
      .filter((p) => p.nl && !p.fr)
      .map((p) => p.nl!.id);
    expect(
      zonderFr,
      `NL-modellen zonder FR-spiegel: maak de spiegel aan (onvertaalde clausules mogen voorlopig naar het NL-onderdeel verwijzen — die tonen groen).`
    ).toEqual([]);
  });

  it("er zijn geen Franstalige seed-modellen zonder bestaande NL-bron", () => {
    const wees = koppelModelParen(seedModellen)
      .filter((p) => p.fr && !p.nl)
      .map((p) => p.fr!.id);
    expect(wees).toEqual([]);
  });

  it("elke rechtshandeling-groep bevat minstens één volledig paar", () => {
    for (const groep of groepeerPerRechtshandeling(seedModellen)) {
      expect(
        groep.paren.some((p) => p.nl && p.fr),
        `rechtshandeling "${groep.rechtshandeling}" heeft geen enkel volledig NL/FR-paar`
      ).toBe(true);
    }
  });
});
