// ── Punt 48 · Checklistgewicht ↔ zekerheids-/escalatiemodel (AUT-O1) ──────────
// Tot nu toe was een akte-checklist (data/kennisbank-checklists.ts) zuiver
// INFORMATIEF: ze somt de te controleren punten op, maar had geen greep op de
// autonomie-besturing. Deze module koppelt het CHECKLISTGEWICHT aan de
// zekerheidsgronden (autonomie.ts), naar het model van `perceptieGronden`
// (perceptie.ts): een onopgelost of afwijkend punt wordt een NEGATIEVE grond,
// zodat het genereren van een ontwerpdocument met zo'n punt niet stilzwijgend
// het gewone "werkdocument"-label draagt, maar naar de notaris escaleert.
//
// ── De dragende ontwerpkeuze (de afruil, expliciet) ─────────────────────────
// De roadmap-werf vraagt een afweging tussen TE STRENG (elk cruciaal punt hard
// blokkerend → niets genereert nog autonoom) en TE LOS (blijft louter een
// suggestie). De gekozen middenweg:
//
//   1. ENKEL CRUCIALE PUNTEN POORTEN DE AUTONOMIE. Punten met gewicht
//      "belangrijk"/"nuttig"/"overbodig" blijven zuiver informatief en voeden
//      de zekerheid NIET — anders zou elke checklist de generatie blokkeren.
//      (Een cruciaal punt is per definitie "moet aanwezig én correct zijn;
//      fout of ontbrekend = ingrijpen" — kennisbank-checklists.ts.)
//   2. GRADUEEL, zoals perceptieGronden: een cruciaal punt dat
//      - "afwijkend" is → BLOKKERENDE negatieve grond (harde tegenstelling,
//        analoog aan een tegenstrijdig bronveld) → meteen "onzeker";
//      - "open" (nog niet opgelost) is → niet-blokkerende negatieve grond
//        (ondergraaft trapsgewijs, analoog aan een "onzeker" waargenomen veld);
//      - "ok" is → positieve grond.
//   3. NIEUWE, LAAGONAFHANKELIJKE GROND. De check zit NIET in de perceptielaag
//      (die gaat over bronextractie) en wordt NIET in autonomie.ts ingebrand
//      (dat blijft de generieke motor): het is een aparte pure functie die
//      `Zekerheidsgrond[]` levert, combineerbaar met `perceptieGronden`, en via
//      het bestaande `bepaalZekerheid` het niveau bepaalt. Zo blijft de afruil
//      op één plek zichtbaar en aanpasbaar.
//
// Puur en deterministisch: geen I/O, geen tijd. De uitkomst per punt
// ("ok"/"afwijkend"/"open") komt van de aanroeper (de dossierspecifieke
// checklist-voortgang, punt 45); ontbreekt een uitkomst, dan geldt "open".

import type { AkteChecklist, ChecklistPunt } from "@/data/kennisbank-checklists";
import { bepaalZekerheid, type Zekerheid, type Zekerheidsgrond } from "./autonomie";

/** De dossierspecifieke uitkomst van één checklistpunt (punt 45-voortgang). */
export type PuntUitkomst =
  | "ok" // aanwezig én correct
  | "afwijkend" // aanwezig maar fout/strijdig — moet ingrijpen
  | "open"; // nog niet gecontroleerd/opgelost

/** Uitkomst per punt-id; een ontbrekende sleutel telt als "open". */
export type ChecklistUitkomsten = Readonly<Record<string, PuntUitkomst>>;

/** Het generatie-etiket dat uit de checklist volgt. */
export type GeneratieLabel = "werkdocument" | "voorleggen-aan-notaris";

/** De beoordeling van een generatie tegen de akte-checklist. */
export interface ChecklistBeoordeling {
  /** Moet de generatie naar de notaris i.p.v. als vrij werkdocument door te gaan? */
  escaleert: boolean;
  label: GeneratieLabel;
  /** De cruciale punten die (nog) niet "ok" zijn — de reden van de escalatie. */
  onopgelosteCruciaal: ChecklistPunt[];
  /** De afgeleide zekerheid, met haar gronden (klaar voor de audit-trail). */
  zekerheid: Zekerheid;
  reden: string;
}

/** De uitkomst van één punt, met "open" als veilige standaard. */
function uitkomstVan(punt: ChecklistPunt, uitkomsten: ChecklistUitkomsten): PuntUitkomst {
  return uitkomsten[punt.id] ?? "open";
}

/**
 * Zet de CRUCIALE checklistpunten om in zekerheidsgronden (analoog aan
 * `perceptieGronden`). Niet-cruciale punten leveren geen grond: zij poorten de
 * autonomie niet. Een afwijkend cruciaal punt is een blokkerende negatieve
 * grond, een open cruciaal punt een niet-blokkerende, een ok'd punt een
 * positieve.
 */
export function checklistGronden(
  checklist: AkteChecklist,
  uitkomsten: ChecklistUitkomsten
): Zekerheidsgrond[] {
  const gronden: Zekerheidsgrond[] = [];
  for (const punt of checklist.punten) {
    if (punt.gewicht !== "cruciaal") continue;
    const uitkomst = uitkomstVan(punt, uitkomsten);
    if (uitkomst === "afwijkend") {
      gronden.push({ omschrijving: `Cruciaal punt afwijkend: ${punt.omschrijving}`, positief: false, blokkerend: true });
    } else if (uitkomst === "open") {
      gronden.push({ omschrijving: `Cruciaal punt nog niet opgelost: ${punt.omschrijving}`, positief: false });
    } else {
      gronden.push({ omschrijving: `Cruciaal punt in orde: ${punt.omschrijving}`, positief: true });
    }
  }
  return gronden;
}

/**
 * Beoordeelt of een generatie tegen deze checklist als vrij werkdocument mag
 * doorgaan, of naar de notaris escaleert. Regel: ELK cruciaal punt dat niet
 * "ok" is (afwijkend óf open) doet de generatie escaleren — de niet-cruciale
 * punten blijven informatief. De zekerheid (met gronden) reist mee voor de
 * verantwoording/audit-trail.
 */
export function beoordeelGeneratieChecklist(
  checklist: AkteChecklist,
  uitkomsten: ChecklistUitkomsten
): ChecklistBeoordeling {
  const gronden = checklistGronden(checklist, uitkomsten);
  const zekerheid = bepaalZekerheid(gronden);
  const onopgelosteCruciaal = checklist.punten.filter(
    (p) => p.gewicht === "cruciaal" && uitkomstVan(p, uitkomsten) !== "ok"
  );
  const escaleert = onopgelosteCruciaal.length > 0;
  const label: GeneratieLabel = escaleert ? "voorleggen-aan-notaris" : "werkdocument";
  const reden = escaleert
    ? `${onopgelosteCruciaal.length} cruciaal punt${onopgelosteCruciaal.length === 1 ? "" : "en"} nog niet in orde — voorleggen aan de notaris.`
    : "Alle cruciale punten in orde — vrij werkdocument.";
  return { escaleert, label, onopgelosteCruciaal, zekerheid, reden };
}

/**
 * Combineert de checklistgronden met andere zekerheidsgronden (bv. uit
 * `perceptieGronden` of `grondenUitOnzekerheden`) tot één afgeleide zekerheid.
 * Handig wanneer een tier-3-handeling zowel de bronperceptie als de checklist
 * moet meewegen: de gronden zijn per constructie homogene `Zekerheidsgrond`s.
 */
export function gecombineerdeZekerheid(...grondenlijsten: Zekerheidsgrond[][]): Zekerheid {
  return bepaalZekerheid(grondenlijsten.flat());
}
