import { describe, it, expect } from "vitest";
import { bepaalVolgendeStap, bepaalTermijnen } from "./levenscyclus-motor";
import { maakVeld, type Dossier, type DossierStatus } from "./types";

// ── AUT-S3 · Levenscyclus-motor ──────────────────────────────────────────────

const VANDAAG = "2026-03-01";

// Testbouwer aan de runtime-grens: de discriminated union van Dossier maakt een
// Partial-parameter onwerkbaar over dossiertypes heen (prijs/hypothecaireLasten
// bestaan enkel op sommige leden); een losse overschrijf + cast is hier bewust.
function maakDossier(overschrijf: Record<string, unknown> = {}): Dossier {
  return {
    id: "d1",
    dossiertype: "verkoop-zonder-krediet",
    status: "compromis-ontvangen" as DossierStatus,
    partijen: maakVeld([{ naam: "Janssens", rol: "verkoper" }], "compromis"),
    goed: maakVeld({ adres: "Kerkstraat 1" }, "eigendomstitel"),
    ontbrekendeStukken: [],
    tegenstrijdigheden: [],
    aangemaakt: "2026-01-01T00:00:00.000Z",
    aangepast: "2026-01-01T00:00:00.000Z",
    ...overschrijf,
  } as unknown as Dossier;
}

/** Zet de vier verplichte verkoopstukken aanwezig zodat het dossier "volledig" is. */
function metAlleStukken(over: Record<string, unknown> = {}): Dossier {
  return maakDossier({
    hypothecaireLasten: maakVeld([{ schuldeiser: "KBC", bedrag: 1000, moetGeroyeerdWorden: true }], "hypotheekattest"),
    goed: maakVeld({ adres: "Kerkstraat 1", kadastraleGegevens: "sectie B nr 88" }, "eigendomstitel"),
    attesten: { stedenbouw: { datum: "2026-02-01" }, bodem: { datum: "2026-02-02" } },
    ...over,
  });
}

const prijsConflict = maakVeld(300000, "compromis");
prijsConflict.alternatieven = [{ waarde: 320000, bron: "eigendomstitel" }];

describe("bepaalVolgendeStap — fase-poort en rijpheid", () => {
  it("intake met partijen+goed en geen conflict is klaar om autonoom naar compliance te gaan", () => {
    const r = bepaalVolgendeStap(maakDossier({ dossiertype: "schenking" }), VANDAAG);
    expect(r.huidigeFase).toBe("intake");
    expect(r.aanbevolenFase).toBe("compliance");
    expect(r.klaarVoorOvergang).toBe(true);
    expect(r.vereistNotaris).toBe(false);
    expect(r.ambtelijk).toBe(false);
  });

  it("een kritieke tegenstrijdigheid blokkeert de overgang", () => {
    const r = bepaalVolgendeStap(maakDossier({ dossiertype: "schenking", prijs: prijsConflict }), VANDAAG);
    expect(r.klaarVoorOvergang).toBe(false);
    expect(r.blokkades.some((b) => b.includes("Tegenstrijdig"))).toBe(true);
  });

  it("opzoekingen is pas klaar voor ontwerp als alle stukken binnen zijn", () => {
    const onvolledig = bepaalVolgendeStap(maakDossier({ status: "opzoekingen-lopend" }), VANDAAG);
    expect(onvolledig.huidigeFase).toBe("opzoekingen");
    expect(onvolledig.aanbevolenFase).toBe("ontwerp");
    expect(onvolledig.klaarVoorOvergang).toBe(false);
    expect(onvolledig.blokkades.some((b) => b.includes("Ontbrekend stuk"))).toBe(true);

    const volledig = bepaalVolgendeStap(metAlleStukken({ status: "opzoekingen-lopend" }), VANDAAG);
    expect(volledig.klaarVoorOvergang).toBe(true);
    expect(volledig.blokkades).toEqual([]);
  });

  it("nazicht-validatie vereist de notaris (geen autonome overgang)", () => {
    const r = bepaalVolgendeStap(maakDossier({ status: "ontwerp-verstuurd" }), VANDAAG);
    expect(r.huidigeFase).toBe("nazicht-validatie");
    expect(r.vereistNotaris).toBe(true);
    expect(r.ambtelijk).toBe(false);
    expect(r.klaarVoorOvergang).toBe(false);
    expect(r.actie).toContain("validatie");
  });

  it("het verlijden is ambtelijk — nooit autonoom, overdragen aan de notaris", () => {
    const r = bepaalVolgendeStap(maakDossier({ status: "klaar-voor-akte" }), VANDAAG);
    expect(r.huidigeFase).toBe("ondertekening");
    expect(r.aanbevolenFase).toBe("formaliteiten");
    expect(r.ambtelijk).toBe(true);
    expect(r.vereistNotaris).toBe(true);
    expect(r.klaarVoorOvergang).toBe(false);
    expect(r.actie).toContain("verlijden");
  });

  it("formaliteiten mogen autonoom door de poort zodra er geen kritiek is", () => {
    const r = bepaalVolgendeStap(metAlleStukken({ status: "verleden" }), VANDAAG);
    expect(r.huidigeFase).toBe("formaliteiten");
    expect(r.aanbevolenFase).toBe("financiele-afhandeling");
    expect(r.klaarVoorOvergang).toBe(true);
  });
});

describe("bepaalTermijnen", () => {
  it("leidt de vier-maandentermijn af uit de compromisdatum en beoordeelt ze", () => {
    const t = bepaalTermijnen(maakDossier({ compromisdatum: maakVeld("2026-01-15", "compromis") }), VANDAAG);
    expect(t).toHaveLength(1);
    expect(t[0].vervaldatum).toBe("2026-05-15");
    expect(t[0].status).toBe("ok");
  });

  it("markeert een verstreken termijn", () => {
    const t = bepaalTermijnen(maakDossier({ compromisdatum: maakVeld("2025-09-15", "compromis") }), VANDAAG);
    expect(t[0].status).toBe("verstreken");
  });

  it("geeft geen termijn zonder compromisdatum", () => {
    expect(bepaalTermijnen(maakDossier(), VANDAAG)).toEqual([]);
  });
});
