// ── Schema-bewaking van de conventie-nazicht-kennisbank ──────────────────────
// Zelfde geest als de schema-guard op de modeldocumenten-bibliotheek: elk
// controlepunt moet volledig en consistent zijn, zodat de analyse-engine en
// de Word-render nooit op halve data lopen. Uitbreiden van de kennisbank mag
// nooit stilzwijgend een categorie/doel-combinatie introduceren die de engine
// niet aankan.

import { describe, expect, it } from "vitest";
import { KENNISBANK_CONTROLEPUNTEN, relevanteControlepunten, akteTypesMetKennisbank } from "./kennisbank";
import { NAZICHT_CATEGORIE_VOLGORDE, nazichtCategorieLabels } from "./types";
import { isGekendAkteType } from "@/data/modeldocumenten/akte-types";

describe("kennisbank conventie-nazicht — schema", () => {
  it("heeft unieke, niet-lege ids", () => {
    const ids = KENNISBANK_CONTROLEPUNTEN.map((p) => p.id);
    expect(new Set(ids).size).toBe(ids.length);
    expect(ids.every((id) => id.trim().length > 0)).toBe(true);
  });

  it("heeft voor elk punt een titel, uitleg en minstens één niet-lege signaalgroep", () => {
    for (const punt of KENNISBANK_CONTROLEPUNTEN) {
      expect(punt.titel.trim(), punt.id).not.toBe("");
      expect(punt.uitleg.trim(), punt.id).not.toBe("");
      expect(punt.signalen.length, punt.id).toBeGreaterThan(0);
      for (const groep of punt.signalen) {
        expect(groep.length, punt.id).toBeGreaterThan(0);
        expect(groep.every((t) => t.trim().length > 0), punt.id).toBe(true);
      }
    }
  });

  it("verwijst enkel naar geregistreerde akteTypes", () => {
    for (const punt of KENNISBANK_CONTROLEPUNTEN) {
      if (punt.akteTypes === "alle") continue;
      for (const type of punt.akteTypes) {
        expect(isGekendAkteType(type), `${punt.id} → ${type}`).toBe(true);
      }
    }
  });

  it("houdt categorie en doel consistent (engine-contract)", () => {
    for (const punt of KENNISBANK_CONTROLEPUNTEN) {
      // essentieel/belangrijk = aanwezigheidseis; te-vermijden = verbodseis.
      if (punt.categorie === "essentieel" || punt.categorie === "belangrijk") {
        expect(punt.doel, punt.id).toBe("vereist");
      }
      if (punt.categorie === "te-vermijden") {
        expect(punt.doel, punt.id).toBe("verdacht");
      }
      // vereist → er moet een in te voegen clausule zijn.
      if (punt.doel === "vereist") {
        expect(punt.voorstel?.trim(), punt.id).toBeTruthy();
        expect(punt.vervanging, punt.id).toBeUndefined();
      } else {
        expect(punt.voorstel, punt.id).toBeUndefined();
      }
    }
  });

  it("kent voor elke categorie een label en volgorde-plaats", () => {
    for (const punt of KENNISBANK_CONTROLEPUNTEN) {
      expect(nazichtCategorieLabels[punt.categorie]).toBeTruthy();
      expect(NAZICHT_CATEGORIE_VOLGORDE).toContain(punt.categorie);
    }
  });
});

describe("kennisbank conventie-nazicht — dekking", () => {
  it("dekt het compromis met alle vier de categorieën", () => {
    const punten = relevanteControlepunten("verkoopovereenkomst (compromis)");
    expect(punten.length).toBeGreaterThanOrEqual(15);
    for (const categorie of NAZICHT_CATEGORIE_VOLGORDE) {
      expect(
        punten.some((p) => p.categorie === categorie),
        `compromis mist categorie ${categorie}`
      ).toBe(true);
    }
  });

  it("dekt de andere geseede rechtshandelingen met een minimum aan punten", () => {
    expect(relevanteControlepunten("verkoopakte").length).toBeGreaterThanOrEqual(10);
    expect(relevanteControlepunten("onderhandse volmacht").length).toBeGreaterThanOrEqual(4);
    expect(relevanteControlepunten("schenkingsakte-roerend-goed").length).toBeGreaterThanOrEqual(4);
  });

  it("geeft voor een onbekend akteType enkel de algemene punten terug", () => {
    const punten = relevanteControlepunten("volstrekt-onbekend-type");
    expect(punten.length).toBeGreaterThanOrEqual(2);
    expect(punten.every((p) => p.akteTypes === "alle")).toBe(true);
  });

  it("somt de gedekte akteTypes op (voor de UI-keuzelijst)", () => {
    const types = akteTypesMetKennisbank();
    expect(types).toContain("verkoopovereenkomst (compromis)");
    expect(types).toContain("onderhandse volmacht");
    expect(types).toContain("schenkingsakte-roerend-goed");
  });
});
