import { describe, it, expect } from "vitest";
import {
  akteMeta,
  BAREMA,
  berekenAkteKostenOverzicht,
  getAktekosten,
  kiesBarema,
  type AkteType,
  type SchenkingsWijze,
} from "./ereloon";

// ── Uitbreidingscontract van de afrekeningslaag ──────────────────────────────
// Een nieuw AkteType toevoegen vergt wijzigingen op meerdere plaatsen
// (AkteType-union, akteMeta, kiesBarema, getAktekosten, getRetributies,
// getIndividualiseerbareKosten, getLeveringskosten). De union en
// `Record<AkteType, …>` dwingen akteMeta af via de compiler, maar de
// berekenfuncties niet allemaal (getAktekosten is een if-cascade met een
// impliciete default-tak). Deze test sluit dat gat: voor élk AkteType —
// actief of niet — moet de volledige keten een coherent resultaat geven,
// zodat een half-geïntegreerd akteType nooit stilzwijgend een lege of
// onzinnige afrekening oplevert.

const ALLE_AKTETYPEN = Object.keys(akteMeta) as AkteType[];
const SCHENKINGSWIJZEN: SchenkingsWijze[] = ["voorschot", "buiten_deel"];

describe.each(ALLE_AKTETYPEN)("afrekeningscontract — %s", (akteType) => {
  it("kiesBarema geeft in elke configuratie een bestaande baremacode", () => {
    for (const eigenWoning of [false, true]) {
      for (const schenkingsWijze of SCHENKINGSWIJZEN) {
        const code = kiesBarema(akteType, { eigenWoning, schenkingsWijze });
        expect(
          BAREMA[code],
          `barema "${code}" (${akteType}, eigenWoning=${eigenWoning}, ` +
            `${schenkingsWijze}) bestaat niet in BAREMA`
        ).toBeDefined();
      }
    }
  });

  it("getAktekosten geeft een positief forfait, ook als verbonden akte", () => {
    for (const verbonden of [false, true]) {
      const kost = getAktekosten(akteType, verbonden);
      expect(kost.bedrag).toBeGreaterThan(0);
      expect(kost.label.trim()).not.toBe("");
      expect(kost.opmerking.trim()).not.toBe("");
    }
  });

  it("berekenAkteKostenOverzicht geeft een coherent totaaloverzicht", () => {
    const overzicht = berekenAkteKostenOverzicht(akteType, 350_000, "Vlaanderen");
    expect(overzicht).not.toBeNull();
    expect(overzicht!.honorarium).toBeGreaterThan(0);
    expect(overzicht!.aktekost).toBeGreaterThan(0);
    // Subtotaal = som van de delen; totaal = subtotaal + btw + vrijgesteld.
    const som =
      overzicht!.honorarium +
      overzicht!.aktekost +
      overzicht!.indBedrag +
      overzicht!.levBedrag;
    expect(overzicht!.subtotaalExclBtw).toBeCloseTo(som, 6);
    expect(overzicht!.totaal).toBeCloseTo(
      overzicht!.subtotaalExclBtw + overzicht!.btw + overzicht!.vrijgesteldBedrag,
      6
    );
    // Geen afrekening zonder grondslag.
    expect(berekenAkteKostenOverzicht(akteType, 0, "Vlaanderen")).toBeNull();
  });
});
