// ── Dossier → autonoom berekende afrekening ──────────────────────────────────
// Derde pijler van het Einddoel (na ontwerpdocument en modelmails): leidt uit
// een dossier de afrekening af — aktekosten/ereloon (data/ereloon.ts) en, waar
// van toepassing, de schenk- of erfbelasting (data/belastingen.ts). Net als de
// twee andere pijlers blijft het resultaat een werkdocument: elke waarde die
// niet met zekerheid uit het dossier kon worden afgeleid, komt in
// `onzekerheden` in plaats van stilzwijgend te worden aangenomen.
//
// Kernprincipe (AGENTS.md): nooit doen-alsof-zeker. Ontbreekt een bepalende
// invoer (bedrag, verwantschap, aard van het goed), dan berekent de functie
// dat onderdeel niet en motiveert ze waarom in `onzekerheden`.

import type { Dossier } from "./types";
import type { Gewest } from "@/lib/context/gewest";
import {
  berekenAkteKostenOverzicht,
  berekenForfaitaireAfrekening,
  berekenHeffing,
  EIGEN_WONING_MAX_KOOPSOM_VLAANDEREN,
  type AkteType,
  type AkteKostenOverzicht,
  type ForfaitaireAfrekening,
  type HeffingResultaat,
} from "@/data/ereloon";
import {
  berekenSchenking,
  berekenErfenis,
  type BelastingResultaat,
} from "@/data/belastingen";

/** Berekende belasting met aanduiding van de soort. */
export interface AfrekeningBelasting {
  soort: "schenking" | "erfenis";
  resultaat: BelastingResultaat;
}

/** Resultaat van het autonoom samenstellen van de afrekening voor een dossier. */
export interface AutonomeAfrekening {
  /** Aktekosten/ereloon-overzicht; ontbreekt wanneer er geen bedrag/akteType is. */
  aktekosten?: AkteKostenOverzicht;
  /**
   * Aktekosten van de kredietakte (hypothecaire lening) — enkel bij een
   * verkoop-met-krediet met een gekend kredietbedrag. De koper tekent dan twee
   * akten en de afrekening hoort beide te tonen.
   */
  aktekostenKrediet?: AkteKostenOverzicht;
  /**
   * Overheidsrecht op de overdracht (verkooprecht/registratiebelasting). Bij een
   * verkoop is dit veruit de grootste post en hoort het in de afrekening thuis;
   * het bedrag is afgerond op hele euro's. Ontbreekt wanneer niet van toepassing.
   */
  registratiebelasting?: HeffingResultaat;
  /** Schenk-/erfbelasting; ontbreekt wanneer niet van toepassing of niet afleidbaar. */
  belasting?: AfrekeningBelasting;
  /**
   * Afrekening voor een akte van onbepaalde waarde (testament, huwelijkscontract,
   * statutenwijziging, zorgvolmacht, volmacht, verkavelings-/basisakte …): enkel
   * de forfaitaire aktekosten en het recht op geschriften; het honorarium bepaalt
   * de notaris (zie `onzekerheden`). Sluit elkaar uit met `aktekosten`.
   */
  forfaitaireAfrekening?: ForfaitaireAfrekening;
  /** Alles wat de notaris vóór gebruik moet beoordelen of zelf moet aanvullen. */
  onzekerheden: string[];
}

/**
 * Stelt autonoom de afrekening samen uit een dossier. Pure functie zonder
 * side effects: dezelfde dossiergegevens leveren altijd dezelfde afrekening.
 * Alle bedragen blijven indicatief (BETA) en moeten door de notaris worden
 * gevalideerd.
 */
export function stelAfrekeningSamenAutonoom(dossier: Dossier, gewest: Gewest): AutonomeAfrekening {
  const onzekerheden: string[] = [];

  switch (dossier.dossiertype) {
    case "verkoop-met-krediet":
    case "verkoop-zonder-krediet": {
      // Verkoop tegen lijfrente kent geen vaste prijs (het kanselement is net
      // de essentie van de figuur, zie verkoop-lijfrente-fiscale-grondslag) —
      // een automatische berekening op basis van dossier.prijs zou hier een
      // onjuiste of misleidende grondslag suggereren. Bewust geen berekening:
      // de notaris bepaalt de fiscale grondslag (gekapitaliseerde rente +
      // bouquet, met de venale waarde als ondergrens) per dossier.
      if (dossier.verkoopRegime === "lijfrente") {
        onzekerheden.push(
          "Verkoop tegen lijfrente: geen automatische afrekening. Het ereloon en het verkooprecht/de registratiebelasting worden niet op een vaste prijs berekend maar op de overeengekomen, gekapitaliseerde waarde van de rente en het bouquet (kanselement, art. 2.9.2.0.1 VCF) — bepaal de fiscale grondslag per dossier, zie de clausule 'Fiscale grondslag — kanselement' in het ontwerp."
        );
        return { onzekerheden };
      }
      const prijs = dossier.prijs?.waarde;
      if (!prijs || prijs <= 0) {
        onzekerheden.push("Geen (positieve) verkoopprijs in het dossier: de aktekosten kunnen niet worden berekend.");
        return { onzekerheden };
      }
      // Verkooprecht: het verlaagd tarief "enige eigen woning" wordt enkel
      // toegepast wanneer het dossier dat uitdrukkelijk zegt (koperEnigeEigen-
      // Woning: true) én de wettelijke waardegrens gerespecteerd is; expliciet
      // false → algemeen tarief zonder voorbehoud; onbekend → algemeen tarief
      // mét de melding dat het verlaagd tarief mogelijk van toepassing is.
      let eigenWoning = false;
      if (dossier.koperEnigeEigenWoning === true) {
        if (gewest === "Vlaanderen" && prijs <= EIGEN_WONING_MAX_KOOPSOM_VLAANDEREN) {
          eigenWoning = true;
          onzekerheden.push(
            "Verlaagd verkooprecht (enige eigen woning) toegepast op basis van het dossier: controleer de wettelijke voorwaarden (geen andere woning, hoofdverblijf binnen 3 jaar)."
          );
        } else if (gewest === "Vlaanderen") {
          onzekerheden.push(
            `Koper koopt zijn enige eigen woning, maar de koopsom overschrijdt de waardegrens van €${EIGEN_WONING_MAX_KOOPSOM_VLAANDEREN.toLocaleString("nl-BE")} — algemeen tarief toegepast.`
          );
        } else {
          onzekerheden.push(
            "Koper koopt zijn enige eigen woning: in dit gewest loopt het gunstregime via een abattement/verlaagd tarief met eigen voorwaarden — hier is het algemeen tarief berekend, na te kijken."
          );
        }
      }
      const aktekosten =
        berekenAkteKostenOverzicht("verkoop", prijs, gewest, {
          eigenWoning,
          extraLeveringskostenIds: dossier.stedenbouwInlichtingenOntvangen?.waarde ? ["lev-stedenbouw"] : [],
        }) ?? undefined;

      // Verkooprecht/registratiebelasting — bij een verkoop de grootste post;
      // afgerond op hele euro's.
      let registratiebelasting: HeffingResultaat | undefined;
      const heffing = berekenHeffing("verkoop", prijs, gewest, { eigenWoning });
      if (heffing) {
        registratiebelasting = { ...heffing, bedrag: Math.round(heffing.bedrag) };
        if (dossier.koperEnigeEigenWoning === undefined) {
          onzekerheden.push(
            "Registratiebelasting berekend aan het algemeen tarief: indien de koper voldoet aan de voorwaarden van de enige eigen woning (verlaagd tarief), is het verschuldigde recht lager — na te kijken."
          );
        }
      }

      // Kredietakte: bij een verkoop met krediet tekent de koper ook de
      // hypothecaire lening — die kosten horen mee in het werkdossier zodra
      // het kredietbedrag gekend is.
      let aktekostenKrediet: AkteKostenOverzicht | undefined;
      if (dossier.dossiertype === "verkoop-met-krediet") {
        const kredietBedrag = dossier.kredietofferte?.waarde.bedrag;
        if (kredietBedrag && kredietBedrag > 0) {
          aktekostenKrediet = berekenAkteKostenOverzicht("hypotheek", kredietBedrag, gewest) ?? undefined;
        } else {
          onzekerheden.push(
            "Verkoop met krediet, maar geen kredietbedrag in het dossier: de kosten van de kredietakte konden niet worden berekend."
          );
        }
      }

      // Wet Breyne: het ereloon (KB 1950-barema) en het verkooprecht/de btw
      // worden — net als bij een gewone verkoop — berekend op de TOTALE prijs,
      // ongeacht de betaling in schijven per bouwfase (het betalingsritme
      // wijzigt de belastbare/erelonengrondslag niet). Enkel deze duiding
      // wordt toegevoegd, geen aparte berekeningstak: elders (kiesBarema/
      // berekenHeffing in data/ereloon.ts) een parallel akteType "verkoop-wet-
      // breyne" invoeren zou zeven schakelpunten dupliceren voor een
      // rekenkundig identieke uitkomst.
      if (dossier.verkoopRegime === "wet-breyne") {
        onzekerheden.push(
          "Wet Breyne: het ereloon en het verkooprecht/de btw hierboven zijn berekend op de totale prijs, zoals bij een gewone verkoop — het betalingsritme (voorschot max. 5% vóór de akte, saldo per bouwfase) wijzigt deze grondslag niet. Controleer afzonderlijk of de constructiewaarde aan btw onderworpen is (fiscaalRegime) in plaats van aan registratiebelasting."
        );
      }

      return { aktekosten, aktekostenKrediet, registratiebelasting, onzekerheden };
    }

    case "schenking": {
      const waarde = dossier.belastbareWaarde?.waarde;
      if (!waarde || waarde <= 0) {
        onzekerheden.push("Geen (positieve) belastbare waarde in het dossier: de schenking kan niet worden berekend.");
        return { onzekerheden };
      }
      const goedType = dossier.goedTypeBelasting?.waarde;
      const relatie = dossier.relatieBelasting?.waarde;
      if (!goedType) onzekerheden.push("Aard van het geschonken goed (roerend/onroerend) niet gekend: vereist voor de afrekening.");
      if (!relatie) onzekerheden.push("Verwantschap schenker–begiftigde niet gekend: vereist voor de schenkbelasting.");

      let belasting: AfrekeningBelasting | undefined;
      let aktekosten: AkteKostenOverzicht | undefined;
      if (goedType && relatie) {
        belasting = { soort: "schenking", resultaat: berekenSchenking(gewest, goedType, relatie, waarde) };
        const akteType: AkteType = goedType === "roerend" ? "schenking-roerend" : "schenking-onroerend";
        const aantalSchenkers = dossier.partijen.waarde.filter((p) => p.rol === "schenker").length;
        aktekosten =
          berekenAkteKostenOverzicht(akteType, waarde, gewest, {
            aantalOverdragers: aantalSchenkers > 0 ? aantalSchenkers : 1,
          }) ?? undefined;
      }
      return { aktekosten, belasting, onzekerheden };
    }

    case "nalatenschap": {
      const waarde = dossier.belastbareWaarde?.waarde;
      if (!waarde || waarde <= 0) {
        onzekerheden.push("Geen (positieve) belastbare waarde in het dossier: de erfbelasting kan niet worden berekend.");
        return { onzekerheden };
      }
      const relatie = dossier.relatieBelasting?.waarde;
      if (!relatie) {
        onzekerheden.push("Verwantschap erflater–erfgenaam niet gekend: vereist voor de erfbelasting.");
        return { onzekerheden };
      }
      const goedType = dossier.goedTypeBelasting?.waarde ?? "onroerend";
      const andereGoederen = dossier.andereGoederenWaarde?.waarde ?? 0;
      // De vrijstelling van de gezinswoning/roerend geldt enkel voor de
      // partner, niet voor afstammelingen in dezelfde belastingschijf
      // ("rechte_lijn_partner"). De partner-vrijstelling speelt enkel binnen
      // die schijf; bij andere relaties is isPartner irrelevant.
      const erfgenamen = dossier.partijen.waarde.filter((p) => p.rol === "erfgenaam");
      let isPartner = false;
      if (relatie === "rechte_lijn_partner") {
        const gekend = erfgenamen.filter((p) => p.testamentRelatie === "partner" || p.testamentRelatie === "kind");
        if (gekend.length === erfgenamen.length && erfgenamen.length > 0) {
          isPartner = erfgenamen.every((p) => p.testamentRelatie === "partner");
        } else {
          onzekerheden.push(
            "Partnerstatus van de erfgenaam (bepalend voor de vrijstelling van de gezinswoning) is niet gekend — controleer dit."
          );
        }
      }
      const resultaat = berekenErfenis(gewest, relatie, waarde, andereGoederen, goedType, isPartner);
      return { belasting: { soort: "erfenis", resultaat }, onzekerheden };
    }

    case "aanpassing-statuten-vennootschap":
    case "keuzetestament":
    case "testament-gezinswoning": {
      // Akten van onbepaalde waarde: geen waarde-grondslag, dus geen
      // proportioneel honorarium of registratierecht. De afrekening beperkt zich
      // tot de zekere, gesourcede forfaitaire aktekosten (art. 2 §2) en het
      // recht op geschriften; het honorarium bepaalt de notaris per akte.
      onzekerheden.push(
        "Akte van onbepaalde waarde: enkel de forfaitaire aktekosten en het recht op geschriften zijn automatisch berekend. Het (vaste/specifieke) honorarium volgens het tariefbesluit bepaalt de notaris per akte — hier bewust niet automatisch geraamd."
      );
      return { forfaitaireAfrekening: berekenForfaitaireAfrekening("hoofdakte"), onzekerheden };
    }

    default: {
      // Het dossier zelf is hier `never` (de union dekt alle dossiertypes).
      const _onbekend: never = dossier;
      void _onbekend;
      onzekerheden.push("Onbekend dossiertype: geen afrekening afgeleid.");
      return { onzekerheden };
    }
  }
}
