import { describe, it, expect } from "vitest";
import { orkestreer, samenvatOrkestratie } from "./orkestratie";
import { maakVeld, type Dossier, type DossierStatus } from "./types";

const VANDAAG = "2026-03-01";

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;
}

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,
  });
}

describe("orkestreer — autonome doorloop tot een haltpunt", () => {
  it("loopt vanaf intake autonoom door tot de compliance-poort (notaris)", () => {
    // Intake is een data-poort en rijp (partijen + goed aanwezig); de volgende
    // fase compliance heeft een notaris-poort → daar stopt de doorloop.
    const plan = orkestreer(maakDossier(), VANDAAG);
    expect(plan.startFase).toBe("intake");
    expect(plan.autonomeStappen.map((s) => `${s.vanFase}→${s.naarFase}`)).toEqual(["intake→compliance"]);
    expect(plan.haltFase).toBe("compliance");
    expect(plan.haltReden).toBe("notaris-vereist");
    expect(plan.vereistNotaris).toBe(true);
    expect(plan.volledigAutonoom).toBe(false);
  });

  it("blokkeert wanneer een verplichte data-fase nog niet rijp is", () => {
    // Zet het dossier in de opzoekingen-fase met ontbrekende stukken: die fase
    // eist een volledig rapport en blokkeert dus.
    const plan = orkestreer(maakDossier({ status: "opzoekingen-lopend" as DossierStatus }), VANDAAG);
    expect(plan.haltFase).toBe("opzoekingen");
    expect(plan.haltReden).toBe("geblokkeerd");
    expect(plan.autonomeStappen).toEqual([]);
    expect(plan.blokkades.length).toBeGreaterThan(0);
  });

  it("gaat vanaf een rijpe opzoekingen-fase autonoom door tot nazicht-validatie (notaris)", () => {
    const plan = orkestreer(metAlleStukken({ status: "opzoekingen-lopend" as DossierStatus }), VANDAAG);
    // opzoekingen → ontwerp (beide data-poort), dan halt bij nazicht-validatie.
    expect(plan.autonomeStappen.map((s) => s.naarFase)).toEqual(["ontwerp", "nazicht-validatie"]);
    expect(plan.haltFase).toBe("nazicht-validatie");
    expect(plan.haltReden).toBe("notaris-vereist");
  });

  it("stopt aan de ambtelijke voorbehoudgrens (het verlijden)", () => {
    const plan = orkestreer(maakDossier(), VANDAAG, { startFase: "ondertekening" });
    expect(plan.haltFase).toBe("ondertekening");
    expect(plan.haltReden).toBe("ambtelijk");
    expect(plan.vereistNotaris).toBe(true);
  });

  it("meldt de eindfase", () => {
    const plan = orkestreer(maakDossier(), VANDAAG, { startFase: "afgesloten" });
    expect(plan.haltReden).toBe("eindfase");
    expect(plan.autonomeStappen).toEqual([]);
  });
});

describe("orkestreer — idempotentie en hervatting", () => {
  it("levert hetzelfde plan op bij dezelfde invoer", () => {
    const a = orkestreer(metAlleStukken(), VANDAAG);
    const b = orkestreer(metAlleStukken(), VANDAAG);
    expect(a).toEqual(b);
  });

  it("hervat vanaf een reeds bereikte fase zonder de eerdere stappen te herhalen", () => {
    const volledig = orkestreer(metAlleStukken(), VANDAAG);
    // Hervat vanaf het haltpunt van de vorige doorloop.
    const hervat = orkestreer(metAlleStukken(), VANDAAG, { startFase: volledig.haltFase });
    expect(hervat.startFase).toBe(volledig.haltFase);
    // De eerder autonoom doorlopen intake-stap zit niet meer in het hervatte plan.
    expect(hervat.autonomeStappen.some((s) => s.vanFase === "intake")).toBe(false);
  });
});

describe("samenvatOrkestratie", () => {
  it("vat het plan in één regel samen", () => {
    const plan = orkestreer(maakDossier(), VANDAAG);
    expect(samenvatOrkestratie(plan)).toContain("intake");
    expect(samenvatOrkestratie(plan)).toContain("wacht op de notaris");
  });
});
