import { describe, it, expect } from "vitest";
import { seedModellen, seedOnderdelen } from "./index";
import { auditBibliotheek, telPerCode, type AuditCode } from "./bibliotheek-audit";

// ── Dé kwaliteitspoort van de bibliotheek ────────────────────────────────────
// Eén test bewaakt alle mapping-/kwaliteitscontroles van de auditmotor
// (bibliotheek-audit.ts), zodat een nieuw model of een nieuwe clausule
// automatisch dezelfde lat haalt als de bestaande bibliotheek:
//
//  - FOUTEN zijn nooit toegelaten (0, hard): dode declaraties, ontbrekende
//    rollen-mapping, onbestaande structuurverwijzingen, generatie-restfouten.
//  - WAARSCHUWINGEN zijn geplafonneerd per code (ratchet: enkel verlagen).
//    Lost een commit structureel waarschuwingen op, verlaag dan het plafond
//    mee in dezelfde commit; verhoog het nooit om een nieuwe melding te
//    doen zwijgen — los de melding op.
//
// Nieuwe controle in de auditmotor? Voeg hier één plafondregel toe.
// (Vervangt de vroegere losse tests rollen-dekking en parameter-declaraties.)

/** Plafonds per waarschuwingscode (stand 2026-07-11, na de parameterharmonisatie) — enkel verlagen. */
const WAARSCHUWING_PLAFONDS: Record<Exclude<AuditCode, "rol-mapping-ontbreekt" | "ontbrekend-onderdeel" | "generatie-restfout" | "dode-declaratie" | "alias-parameternaam">, number> = {
  "te-vertalen-markering": 1, // ht-premies-wallonie: authentieke NL-tekst nog aan te leveren
  "onvertaalde-clausule": 1, // het heldere-taal-compromis
  "tegenhanger-ontbreekt": 0, // elk model bestaat in NL én FR — houden zo
  "parameter-nergens-gedeclareerd": 0, // 186 vóór de harmonisatie van 2026-07-11; laatste 74 aangevuld op 2026-07-12 — houden op 0
  // FR-clausules waarvan de parameternamen (nog) afwijken van de NL-spiegel —
  // de werklijst van de parameterharmonisatie: hernoem naar de gedeelde namen
  // (zie parameter-register.ts) en verlaag dit plafond mee in dezelfde commit.
  "parameter-taalpariteit": 31,
  "duplicaat-tekst": 0, // geen identieke clausuleteksten — houden zo
};

describe("bibliotheek-audit", () => {
  const bevindingen = auditBibliotheek(seedModellen, seedOnderdelen);
  const perCode = telPerCode(bevindingen);

  it("geen fouten in de seed-bibliotheek", () => {
    const fouten = bevindingen
      .filter((b) => b.ernst === "fout")
      .map((b) => `${b.onderwerp}: [${b.code}] ${b.omschrijving}`);
    expect(fouten).toEqual([]);
  });

  it.each(Object.entries(WAARSCHUWING_PLAFONDS))(
    "waarschuwingen %s blijven onder het plafond (%i)",
    (code, plafond) => {
      const aantal = perCode.get(code as AuditCode) ?? 0;
      expect(
        aantal,
        `code "${code}": ${aantal} > plafond ${plafond}. Los de nieuwe meldingen op (zie auditBibliotheek) ` +
          `in plaats van het plafond te verhogen; daalt de teller structureel, verlaag het plafond mee.`
      ).toBeLessThanOrEqual(plafond);
    }
  );

  it("elke waarschuwingscode heeft een plafond (nieuwe controle = nieuwe plafondregel)", () => {
    const zonderPlafond = [...perCode.keys()].filter(
      (code) => bevindingen.some((b) => b.code === code && b.ernst === "waarschuwing") && !(code in WAARSCHUWING_PLAFONDS)
    );
    expect(zonderPlafond).toEqual([]);
  });
});
