// ── Kantooraanpassingen op de kennisbank van het conventie-nazicht ───────────
// De seed-kennisbank (kennisbank.ts) is statische, AI-opgestelde data. Het
// kantoor kan elk punt in de UI valideren, bewerken, schrappen of eigen punten
// toevoegen; die aanpassingen worden per punt bewaard (IndexedDB + Supabase-
// sync, zelfde patroon als de modeldocumenten) en hier — puur en testbaar —
// over de seed heen gelegd.
//
// Eén record per punt-id: een bewerking/validatie draagt de volledige
// puntinhoud (`punt`), een schrapping enkel de vlag (`geschrapt`). Herstellen
// naar de seed = het record verwijderen.

import type { Controlepunt, NazichtCategorie, NazichtDoel } from "./types";
import { isGekendAkteType } from "@/data/modeldocumenten/akte-types";

/** Kantooraanpassing bovenop de seed-kennisbank (opslag-eenheid, jsonb-sync). */
export interface KennisbankAanpassing {
  /** Punt-id: het seed-id bij validatie/bewerking/schrapping, een eigen id bij een nieuw punt. */
  id: string;
  /** Volledige puntinhoud (override van de seed, of een nieuw kantooreigen punt). */
  punt?: Controlepunt;
  /** Punt uitgeschakeld: telt niet meer mee in het nazicht (seed blijft herstelbaar). */
  geschrapt?: boolean;
  /** Laatste wijziging (ISO-tijdstip), voor weergave en conflictbeslechting. */
  aangepast: string;
}

/**
 * Legt de kantooraanpassingen over de seed-kennisbank: overrides vervangen
 * het seed-punt op dezelfde plaats, geschrapte punten vallen weg en nieuwe
 * kantoorpunten komen achteraan. Dit is de éne effectieve kennisbank die
 * analyse én UI gebruiken.
 */
export function stelKennisbankSamen(
  seed: readonly Controlepunt[],
  aanpassingen: readonly KennisbankAanpassing[]
): Controlepunt[] {
  const perId = new Map(aanpassingen.map((a) => [a.id, a]));
  const effectief: Controlepunt[] = [];

  for (const punt of seed) {
    const aanpassing = perId.get(punt.id);
    if (!aanpassing) {
      effectief.push(punt);
      continue;
    }
    perId.delete(punt.id);
    if (aanpassing.geschrapt) continue;
    effectief.push(aanpassing.punt ?? punt);
  }

  // Wat overblijft zijn kantooreigen punten (geen seed-tegenhanger).
  for (const aanpassing of perId.values()) {
    if (!aanpassing.geschrapt && aanpassing.punt) effectief.push(aanpassing.punt);
  }
  return effectief;
}

/** Is dit punt door de notaris gevalideerd? (ontbrekende stand = nog te valideren). */
export function isGevalideerd(punt: Controlepunt): boolean {
  return punt.validatie?.status === "gevalideerd";
}

const CATEGORIEEN: readonly NazichtCategorie[] = ["essentieel", "belangrijk", "beter", "te-vermijden"];
const DOELEN: readonly NazichtDoel[] = ["vereist", "verdacht"];

/**
 * Valideert een (bewerkt of nieuw) controlepunt en geeft de gebreken in
 * mensentaal terug — leeg = geldig. Zelfde regels als de schema-test op de
 * seed, zodat de UI-editor geen punt kan opslaan dat de engine niet aankan.
 */
export function valideerControlepunt(punt: Controlepunt): string[] {
  const fouten: string[] = [];
  if (!punt.id.trim()) fouten.push("Het punt heeft een id nodig.");
  if (!punt.titel.trim()) fouten.push("Titel is verplicht.");
  if (!punt.uitleg.trim()) fouten.push("Uitleg/motivering is verplicht.");
  if (!CATEGORIEEN.includes(punt.categorie)) fouten.push("Ongeldige categorie.");
  if (!DOELEN.includes(punt.doel)) fouten.push("Ongeldig doel.");
  if ((punt.categorie === "essentieel" || punt.categorie === "belangrijk") && punt.doel !== "vereist") {
    fouten.push("Essentieel/belangrijk veronderstelt een aanwezigheidseis (doel 'vereist').");
  }
  if (punt.categorie === "te-vermijden" && punt.doel !== "verdacht") {
    fouten.push("'Te vermijden' veronderstelt een verbodseis (doel 'verdacht').");
  }
  if (punt.signalen.length === 0 || punt.signalen.some((g) => g.length === 0 || g.some((t) => !t.trim()))) {
    fouten.push("Minstens één signaalgroep met niet-lege trefwoorden is vereist.");
  }
  if (punt.doel === "vereist") {
    if (!punt.voorstel?.trim()) fouten.push("Een aanwezigheidseis heeft een in te voegen clausuletekst (voorstel) nodig.");
    if (punt.vervanging) fouten.push("Een aanwezigheidseis gebruikt geen vervangtekst.");
  } else if (punt.voorstel) {
    fouten.push("Een verbodseis gebruikt geen voorstel (wel eventueel een vervangtekst).");
  }
  if (punt.akteTypes !== "alle") {
    if (punt.akteTypes.length === 0) fouten.push("Kies minstens één rechtshandeling (of 'alle').");
    for (const type of punt.akteTypes) {
      if (!isGekendAkteType(type)) fouten.push(`Onbekend akteType: ${type}.`);
    }
  }
  return fouten;
}

// ── Signalen ↔ tekst (voor de UI-editor) ─────────────────────────────────────
// Formaat: één signaalgroep per regel (OF), trefwoorden binnen een regel
// gescheiden door " + " (EN). Voorbeeld:
//   opschortende voorwaarde + lening
//   opschortende voorwaarde + krediet

export function signalenNaarTekst(signalen: readonly (readonly string[])[]): string {
  return signalen.map((groep) => groep.join(" + ")).join("\n");
}

export function tekstNaarSignalen(tekst: string): string[][] {
  return tekst
    .split("\n")
    .map((regel) =>
      regel
        .split("+")
        .map((t) => t.trim())
        .filter((t) => t.length > 0)
    )
    .filter((groep) => groep.length > 0);
}
