// ── Dossier → akteType-detectie ──────────────────────────────────────────────
// Pure beslissingslaag: leidt uit de gestructureerde dossiergegevens af welk
// soort ontwerpdocument (akteType) het kantoor moet opstellen. Dit is de eerste
// stap in het autonoom opstellen: vandaag kiest de notaris het model nog
// handmatig in de UI; deze functie stelt die keuze voor op basis van het
// dossiertype en de gekende signalen (compromisdatum, aard van het geschonken
// goed, …).
//
// Het akteType dat hier wordt teruggegeven sluit aan op het `akteType`-veld van
// de modeldocumenten (data/modeldocumenten/modellen/*), zodat de uitkomst
// rechtstreeks naar een model kan worden gematcht.
//
// Kernprincipe (AGENTS.md): nooit doen-alsof-zeker. Wanneer het dossier de
// keuze niet eenduidig vastlegt, geeft de functie `zekerheid: "onduidelijk"`
// met alternatieven en een `reden`, zodat de notaris die onzekerheid in de
// werkdocument-flow expliciet voorgelegd krijgt in plaats van een blinde keuze.

import type { Dossier } from "./types";
import type { AkteTypeNaam } from "@/data/modeldocumenten/akte-types";

/**
 * Detectiegegevens voor één sub-pad (`verkoopRegime` !== "gewoon"): de twee
 * regime-specifieke akteTypes en de motiveringszinnen voor elke tak van
 * `bepaalAkteType`. Nieuw sub-pad toevoegen = één regel in `VERKOOP_REGIMES`
 * hieronder — de kruising met `verkoopdocument`/`compromisdatum` hoeft niet
 * herschreven te worden.
 */
interface VerkoopRegimeInfo {
  compromisType: AkteTypeNaam;
  akteType: AkteTypeNaam;
  /** Reden bij een expliciete keuze voor "compromis". */
  redenCompromisExpliciet: string;
  /** Reden bij een expliciete keuze voor "verkoopakte". */
  redenAkteExpliciet: string;
  /** Reden wanneer een compromisdatum al gekend is (impliciete akte-keuze). */
  redenAkteViaCompromis: string;
  /** Reden wanneer geen enkele keuze gemaakt is (onduidelijk, compromis als suggestie). */
  redenOnduidelijk: string;
}

const VERKOOP_REGIMES: Partial<Record<NonNullable<Dossier["verkoopRegime"]>, VerkoopRegimeInfo>> = {
  "wet-breyne": {
    compromisType: "verkoopovereenkomst (compromis) - wet breyne",
    akteType: "verkoopakte - wet breyne",
    redenCompromisExpliciet:
      "Dossier 'compromis' onder de wet Breyne (verkoop van een te bouwen of in aanbouw zijnde woning, wet van 9 juli 1971): het kantoor stelt de onderhandse Breyne-overeenkomst op, met de wettelijk verplichte vermeldingen (prijs/betalingsschema gekoppeld aan de bouwvoortgang, waarborgregeling, plannen en lastenboek als bijlage, wettelijke bedenktijd).",
    redenAkteExpliciet:
      "Dossier 'verkoopakte' onder de wet Breyne: het kantoor stelt de authentieke akte op volgens de wet van 9 juli 1971 (o.m. de opleveringsregeling in twee fasen en de voltooiings-/financiële waarborg).",
    redenAkteViaCompromis:
      "Er is al een Breyne-overeenkomst (compromis); het kantoor stelt de authentieke akte op volgens de wet van 9 juli 1971.",
    redenOnduidelijk:
      "Geen compromisdatum gekend en geen documentkeuze gemaakt onder de wet Breyne: het kantoor stelt vermoedelijk eerst de Breyne-overeenkomst op, maar dit moet bevestigd worden.",
  },
  lijfrente: {
    compromisType: "verkoopovereenkomst (compromis) - lijfrente",
    akteType: "verkoopakte - lijfrente",
    redenCompromisExpliciet:
      "Dossier 'compromis' voor een verkoop tegen lijfrente: het kantoor stelt de onderhandse lijfrente-overeenkomst op (bouquet/rente, genotsrecht van de verkoper, aleatoir karakter — art. 1968 e.v. oud BW), zonder een vaste prijs zoals bij een gewone verkoop.",
    redenAkteExpliciet:
      "Dossier 'verkoopakte' voor een verkoop tegen lijfrente: het kantoor stelt de authentieke akte op met de rente-/bouquetregeling, het genotsrecht van de verkoper en de fiscale grondslag (kanselement, art. 2.9.2.0.1 VCF).",
    redenAkteViaCompromis:
      "Er is al een lijfrente-overeenkomst (compromis); het kantoor stelt de authentieke akte op met dezelfde rente-/bouquetregeling.",
    redenOnduidelijk:
      "Geen compromisdatum gekend en geen documentkeuze gemaakt voor deze verkoop tegen lijfrente: het kantoor stelt vermoedelijk eerst de onderhandse overeenkomst op, maar dit moet bevestigd worden.",
  },
};

/**
 * Voorgesteld akteType voor een dossier, met de mate van zekerheid en een
 * korte motivering. `alternatieven` bevat andere plausibele akteTypes wanneer
 * het dossier de keuze niet eenduidig vastlegt; `reden` is bedoeld om in de
 * onzekerhedenlijst van het werkdocument te tonen. De namen komen uit het
 * centrale register (data/modeldocumenten/akte-types.ts): een typo in een
 * detectie-uitkomst is daardoor een compile-fout in plaats van een
 * stilzwijgend niet-gevonden model.
 */
export interface AkteTypeKeuze {
  /** Best passende akteType; leeg ("") wanneer geen enkel akteType plausibel is. */
  akteType: AkteTypeNaam | "";
  zekerheid: "zeker" | "onduidelijk";
  /** Andere plausibele akteTypes, hoogste waarschijnlijkheid eerst. */
  alternatieven?: AkteTypeNaam[];
  /** Korte motivering, voor de onzekerhedenlijst van het werkdocument. */
  reden: string;
}

/**
 * Leidt uit het dossier af welk ontwerpdocument het kantoor moet opstellen.
 *
 * - Verkoop: bestaat er al een compromis (compromisdatum gekend), dan stelt het
 *   kantoor de authentieke verkoopakte op (zeker). Is er nog geen compromis,
 *   dan is het onduidelijk of het kantoor eerst het compromis dan wel meteen de
 *   akte opstelt — beide worden voorgesteld.
 * - Schenking: schenkingsakte (zeker als enige courante uitkomst).
 * - Nalatenschap: meerdere mogelijke documenten (aangifte van nalatenschap,
 *   akte van erfopvolging, …); de functie wijst geen enkel akteType blind aan
 *   en markeert de keuze als onduidelijk.
 */
export function bepaalAkteType(dossier: Dossier): AkteTypeKeuze {
  switch (dossier.dossiertype) {
    case "verkoop-met-krediet":
    case "verkoop-zonder-krediet": {
      // Een sub-pad (wet Breyne, lijfrente, …) is GEEN derde verkoopdocument
      // en GEEN apart dossiertype: het is een orthogonaal kenmerk (net als
      // fiscaalRegime) dat, net als een gewone verkoop, zowel een compromis-
      // als een aktefase kent — vandaar de kruising met `verkoopdocument`
      // hieronder in plaats van een eigen tak in de switch. `regime` is
      // `undefined` voor "gewoon"/ontbrekend `verkoopRegime`.
      const regime = dossier.verkoopRegime ? VERKOOP_REGIMES[dossier.verkoopRegime] : undefined;

      // Expliciete keuze van het op te stellen document heeft voorrang.
      if (dossier.verkoopdocument === "compromis") {
        return regime
          ? { akteType: regime.compromisType, zekerheid: "zeker", reden: regime.redenCompromisExpliciet }
          : {
              akteType: "verkoopovereenkomst (compromis) - heldere taal",
              zekerheid: "zeker",
              alternatieven: ["verkoopovereenkomst (compromis)"],
              reden:
                "Dossier 'compromis': het kantoor stelt standaard het compromis in heldere taal op (voordien is enkel een bod/aankoopbelofte getekend). Het klassieke compromis blijft beschikbaar als alternatief.",
            };
      }
      if (dossier.verkoopdocument === "verkoopakte") {
        return regime
          ? { akteType: regime.akteType, zekerheid: "zeker", reden: regime.redenAkteExpliciet }
          : {
              akteType: "verkoopakte",
              zekerheid: "zeker",
              reden:
                "Dossier 'verkoopakte': het kantoor stelt de authentieke verkoopakte op (meestal binnen de vier maanden na de ondertekening van het compromis).",
            };
      }
      // Terugval wanneer het document niet expliciet gekozen is: leid af uit de
      // aanwezigheid van een compromisdatum.
      const heeftCompromis = Boolean(dossier.compromisdatum?.waarde);
      if (heeftCompromis) {
        return regime
          ? { akteType: regime.akteType, zekerheid: "zeker", reden: regime.redenAkteViaCompromis }
          : {
              akteType: "verkoopakte",
              zekerheid: "zeker",
              reden:
                "Er is al een onderhandse verkoopovereenkomst (compromis); het kantoor stelt de authentieke verkoopakte op.",
            };
      }
      return regime
        ? {
            akteType: regime.compromisType,
            zekerheid: "onduidelijk",
            alternatieven: [regime.akteType],
            reden: regime.redenOnduidelijk,
          }
        : {
            akteType: "verkoopovereenkomst (compromis) - heldere taal",
            zekerheid: "onduidelijk",
            alternatieven: ["verkoopovereenkomst (compromis)", "verkoopakte"],
            reden:
              "Geen compromisdatum gekend en geen documentkeuze gemaakt: het kantoor stelt vermoedelijk eerst het compromis (standaard in heldere taal) op, maar dit moet bevestigd worden.",
          };
    }

    case "schenking": {
      const goedType = dossier.goedTypeBelasting?.waarde;
      if (goedType === "roerend") {
        return {
          akteType: "schenkingsakte-roerend-goed",
          zekerheid: "zeker",
          reden: "Schenkingsdossier van een roerend goed: het kantoor stelt de schenkingsakte (roerend goed) op.",
        };
      }
      if (goedType === "onroerend") {
        return {
          akteType: "schenkingsakte",
          zekerheid: "zeker",
          reden: "Schenkingsdossier van een onroerend goed: het kantoor stelt de schenkingsakte op.",
        };
      }
      return {
        akteType: "schenkingsakte",
        zekerheid: "onduidelijk",
        alternatieven: ["schenkingsakte-roerend-goed"],
        reden:
          "Schenkingsdossier zonder gekende aard van het geschonken goed (roerend/onroerend): het kantoor stelt vermoedelijk de schenkingsakte (onroerend) op, maar dit moet bevestigd worden.",
      };
    }

    case "nalatenschap":
      // De aangifte van nalatenschap is het onherleidbare kerndocument van elk
      // nalatenschapsdossier: ze moet voor de erfbelasting worden ingediend
      // binnen de wettelijke termijn. Het kantoor stelt ze daarom standaard op;
      // de akte/het attest van erfopvolging (om de tegoeden te deblokkeren) is
      // een bijkomend, apart document — geen alternatief voor hetzelfde resultaat.
      return {
        akteType: "aangifte-nalatenschap",
        zekerheid: "zeker",
        alternatieven: ["akte-erfopvolging"],
        reden:
          "Nalatenschapsdossier: het kantoor stelt de aangifte van nalatenschap op (verplicht voor de erfbelasting, in te dienen binnen de wettelijke termijn). Een akte/attest van erfopvolging wordt desgevallend bijkomend opgemaakt om de tegoeden te deblokkeren.",
      };

    case "aanpassing-statuten-vennootschap":
      return {
        akteType: "aanpassing-statuten-besloten-vennootschap",
        zekerheid: "zeker",
        reden: "Vennootschapsdossier voor een statutenwijziging: het kantoor stelt de aanpassing van de statuten op.",
      };

    case "keuzetestament":
      return {
        akteType: "keuzetestament",
        zekerheid: "zeker",
        reden: "Testamentdossier (keuzetestament): het kantoor stelt het keuzetestament op.",
      };

    case "testament-gezinswoning":
      return {
        akteType: "testament-gezinswoning-partner-restlegaat-kinderen",
        zekerheid: "zeker",
        reden:
          "Testamentdossier (gezinswoning aan partner met restlegaat aan de kinderen): het kantoor stelt dat testament op.",
      };

    default: {
      // Exhaustiviteitscontrole: faalt de compilatie hier, dan is er een
      // dossiertype bijgekomen zonder mapping in deze functie. (Het dossier
      // zelf is hier `never` — de union dekt alle types — dus het onbekende
      // type is enkel via een cast op runtime-data leesbaar.)
      const _onbekend: never = dossier;
      return {
        akteType: "",
        zekerheid: "onduidelijk",
        reden: `Onbekend dossiertype (${String((_onbekend as { dossiertype?: string }).dossiertype)}): geen akteType afgeleid.`,
      };
    }
  }
}
