// ── AUT-S5 · AML/KYC-flow (laag 3) ───────────────────────────────────────────
// Bouwt op het AUT-O6-risicomodel (aml.ts) de eigenlijke FLOW: per partij de
// KYC-stappenlijst (welke controles zijn nog open), de risicobeoordeling, en de
// aggregatie tot één dossierbeoordeling die de notaris de go/no-go voorlegt.
// De beslissing zelf blijft altijd bij de notaris (AUT-O6, beslissing 1) — de
// flow verzamelt, bewaakt de stappen en escaleert; ze geeft nooit zelf vrij.
//
// ── Ontwerpbeslissingen ─────────────────────────────────────────────────────
// 1. SCREENING-STATUS ≠ RESULTAAT. Het risicomodel behandelt een ontbrekende
//    optionele controle (bv. sanctielijst `undefined`) veilig als "geen hit".
//    De flow maakt het ONDERSCHEID expliciet: een nog niet uitgevoerde screening
//    is een openstaande stap (zichtbaar, af te werken), geen stilzwijgend "ok".
// 2. HARDE vs. AANDACHT-STAPPEN. Identiteit, UBO (bij rechtspersoon) en
//    sanctiescreening zijn blokkerend; PEP- en herkomst-screening zijn
//    aandachtsstappen (aanbevolen, niet-blokkerend voor de datastroom).
// 3. ALTIJD ESCALEREN. `besluit` is steevast "voorleggen-notaris" en
//    `autonoomVrijgevenMogelijk: false` — ongeacht het niveau. De flow levert
//    wel PII-vrije AUT-O1-gronden zodat een blokkerend/onaanvaardbaar AML-beeld
//    ook het autonome handelen elders in het dossier tegenhoudt.

import type { Zekerheidsgrond } from "./autonomie";
import { beoordeelAmlRisico, type AmlBeoordeling, type AmlKenmerken, type AmlRisiconiveau } from "./aml";

/** Eén stap in de KYC-controlelijst van een partij. */
export interface AmlStap {
  code: "identiteit" | "ubo" | "sanctie-screening" | "pep-screening" | "herkomst-gelden";
  omschrijving: string;
  voltooid: boolean;
  blokkerend: boolean;
}

/** De AML-beoordeling van één partij, mét de openstaande controlestappen. */
export interface PartijAmlBeoordeling {
  /** Pseudoniem/rol van de partij — GEEN persoonsgegevens. */
  partijRef: string;
  beoordeling: AmlBeoordeling;
  openstaandeStappen: AmlStap[];
}

/** De geaggregeerde AML-beoordeling van het hele dossier. */
export interface AmlDossierbeoordeling {
  perPartij: PartijAmlBeoordeling[];
  hoogsteNiveau: AmlRisiconiveau;
  /** Is er minstens één blokkerende factor of openstaande blokkerende stap? */
  blokkerend: boolean;
  /** Altijd: de go/no-go is persoonlijk aan de notaris. */
  besluit: "voorleggen-notaris";
  /** ALTIJD false (AUT-O6, beslissing 1). */
  autonoomVrijgevenMogelijk: false;
  /** PII-vrije gronden voor het AUT-O1-zekerheidsmodel. */
  gronden: Zekerheidsgrond[];
}

const NIVEAU_ORDE: Record<AmlRisiconiveau, number> = { laag: 0, midden: 1, hoog: 2, onaanvaardbaar: 3 };

/**
 * Bepaalt de KYC-stappenlijst uit de kenmerken van één partij: welke controles
 * zijn (nog niet) uitgevoerd. Een optioneel kenmerk dat `undefined` is, betekent
 * "screening nog niet gebeurd" → openstaande stap.
 */
export function bepaalOpenstaandeStappen(kenmerken: AmlKenmerken): AmlStap[] {
  const stappen: AmlStap[] = [
    { code: "identiteit", omschrijving: "Identiteit verifiëren aan de hand van een bewijsstuk.", voltooid: kenmerken.identiteitGeverifieerd, blokkerend: true },
  ];
  if (kenmerken.isRechtspersoon) {
    stappen.push({
      code: "ubo",
      omschrijving: "Uiteindelijke begunstigde (UBO) identificeren.",
      voltooid: kenmerken.uboGeidentificeerd === true,
      blokkerend: true,
    });
  }
  stappen.push(
    { code: "sanctie-screening", omschrijving: "Screenen tegen sanctie-/bevriezingslijsten.", voltooid: kenmerken.sanctielijstHit !== undefined, blokkerend: true },
    { code: "pep-screening", omschrijving: "Screenen op politiek prominent persoon (PEP).", voltooid: kenmerken.pep !== undefined, blokkerend: false },
    { code: "herkomst-gelden", omschrijving: "Herkomst van de gelden nagaan.", voltooid: kenmerken.herkomstGeldenPlausibel !== undefined, blokkerend: false }
  );
  return stappen.filter((s) => !s.voltooid);
}

/** Beoordeelt één partij: het AUT-O6-risico plus de openstaande KYC-stappen. */
export function beoordeelPartijAml(partijRef: string, kenmerken: AmlKenmerken): PartijAmlBeoordeling {
  return {
    partijRef,
    beoordeling: beoordeelAmlRisico(kenmerken),
    openstaandeStappen: bepaalOpenstaandeStappen(kenmerken),
  };
}

/**
 * Aggregeert de AML-beoordeling over alle partijen van een dossier: het hoogste
 * risiconiveau, of er iets blokkerends speelt, en de gronden voor AUT-O1. Het
 * besluit is altijd "voorleggen-notaris" — de flow geeft nooit zelf vrij.
 */
export function beoordeelDossierAml(
  partijen: readonly { ref: string; kenmerken: AmlKenmerken }[]
): AmlDossierbeoordeling {
  const perPartij = partijen.map((p) => beoordeelPartijAml(p.ref, p.kenmerken));

  const hoogsteNiveau = perPartij.reduce<AmlRisiconiveau>(
    (hoog, p) => (NIVEAU_ORDE[p.beoordeling.niveau] > NIVEAU_ORDE[hoog] ? p.beoordeling.niveau : hoog),
    "laag"
  );

  const blokkerend = perPartij.some(
    (p) => p.beoordeling.factoren.some((f) => f.blokkerend) || p.openstaandeStappen.some((s) => s.blokkerend)
  );

  return {
    perPartij,
    hoogsteNiveau,
    blokkerend,
    besluit: "voorleggen-notaris",
    autonoomVrijgevenMogelijk: false,
    gronden: bouwGronden(perPartij, hoogsteNiveau, blokkerend),
  };
}

/**
 * Vertaalt de AML-flow naar AUT-O1-gronden (PII-vrij: enkel de partijRef/rol en
 * de aard van de factor, nooit namen of waarden). Een onaanvaardbaar of
 * blokkerend beeld levert blokkerende negatieve gronden; een schoon, volledig
 * gescreend dossier één positieve grond.
 */
function bouwGronden(
  perPartij: readonly PartijAmlBeoordeling[],
  hoogsteNiveau: AmlRisiconiveau,
  blokkerend: boolean
): Zekerheidsgrond[] {
  const gronden: Zekerheidsgrond[] = [];

  for (const p of perPartij) {
    if (p.beoordeling.niveau === "onaanvaardbaar") {
      gronden.push({ omschrijving: `AML onaanvaardbaar voor partij "${p.partijRef}".`, positief: false, blokkerend: true });
    }
    for (const stap of p.openstaandeStappen) {
      if (stap.blokkerend) {
        gronden.push({ omschrijving: `AML-controle "${stap.code}" nog niet voltooid voor partij "${p.partijRef}".`, positief: false, blokkerend: true });
      }
    }
  }

  if (gronden.length === 0) {
    if (hoogsteNiveau === "hoog") {
      gronden.push({ omschrijving: "AML-risico is hoog — verscherpte waakzaamheid vereist.", positief: false });
    } else if (!blokkerend) {
      gronden.push({ omschrijving: "AML-controles uitgevoerd; geen blokkerende tekortkoming.", positief: true });
    }
  }

  return gronden;
}
