import { describe, it, expect } from "vitest";
import {
  checklistGronden,
  beoordeelGeneratieChecklist,
  gecombineerdeZekerheid,
  type ChecklistUitkomsten,
} from "./checklist-zekerheid";
import type { AkteChecklist, ChecklistPunt } from "@/data/kennisbank-checklists";

function punt(id: string, gewicht: ChecklistPunt["gewicht"]): ChecklistPunt {
  return { id, gewicht, omschrijving: `omschrijving ${id}` };
}

function checklist(punten: ChecklistPunt[]): AkteChecklist {
  return {
    id: "cl-test",
    akteType: "verkoopakte",
    titel: "Test",
    omschrijving: "",
    punten,
    versie: "1.0",
    datum: "2026-01-01",
    aangepast: "2026-01-01",
  };
}

const CHECKLIST = checklist([
  punt("c1", "cruciaal"),
  punt("c2", "cruciaal"),
  punt("b1", "belangrijk"),
  punt("n1", "nuttig"),
]);

describe("checklistGronden", () => {
  it("levert enkel gronden voor cruciale punten (niet-cruciale zijn informatief)", () => {
    const gronden = checklistGronden(CHECKLIST, { c1: "ok", c2: "ok", b1: "afwijkend", n1: "open" });
    // Alleen c1 en c2 tellen mee; b1/n1 leveren geen grond.
    expect(gronden).toHaveLength(2);
    expect(gronden.every((g) => g.positief)).toBe(true);
  });

  it("markeert een afwijkend cruciaal punt als blokkerende negatieve grond", () => {
    const gronden = checklistGronden(CHECKLIST, { c1: "afwijkend", c2: "ok" });
    const c1 = gronden.find((g) => g.omschrijving.includes("c1"))!;
    expect(c1.positief).toBe(false);
    expect(c1.blokkerend).toBe(true);
  });

  it("markeert een open cruciaal punt als niet-blokkerende negatieve grond", () => {
    const gronden = checklistGronden(CHECKLIST, { c1: "open", c2: "ok" });
    const c1 = gronden.find((g) => g.omschrijving.includes("c1"))!;
    expect(c1.positief).toBe(false);
    expect(c1.blokkerend).toBeUndefined();
  });

  it("behandelt een ontbrekende uitkomst als 'open'", () => {
    const gronden = checklistGronden(CHECKLIST, {}); // niets ingevuld
    // Twee cruciale punten, beide open → twee niet-blokkerende negatieve gronden.
    expect(gronden.filter((g) => !g.positief)).toHaveLength(2);
  });
});

describe("beoordeelGeneratieChecklist — het generatie-etiket", () => {
  it("blijft vrij werkdocument wanneer alle cruciale punten in orde zijn", () => {
    const b = beoordeelGeneratieChecklist(CHECKLIST, { c1: "ok", c2: "ok", b1: "open", n1: "afwijkend" });
    // Niet-cruciale punten b1/n1 mogen open/afwijkend zijn zonder te escaleren.
    expect(b.escaleert).toBe(false);
    expect(b.label).toBe("werkdocument");
    expect(b.onopgelosteCruciaal).toHaveLength(0);
    expect(b.zekerheid.niveau).toBe("zeker");
  });

  it("escaleert bij één open cruciaal punt", () => {
    const b = beoordeelGeneratieChecklist(CHECKLIST, { c1: "ok", c2: "open" });
    expect(b.escaleert).toBe(true);
    expect(b.label).toBe("voorleggen-aan-notaris");
    expect(b.onopgelosteCruciaal.map((p) => p.id)).toEqual(["c2"]);
    // Eén niet-blokkerende negatieve grond → "waarschijnlijk", maar toch escaleren.
    expect(b.zekerheid.niveau).toBe("waarschijnlijk");
  });

  it("valt terug op 'onzeker' bij een afwijkend cruciaal punt (blokkerend)", () => {
    const b = beoordeelGeneratieChecklist(CHECKLIST, { c1: "afwijkend", c2: "ok" });
    expect(b.escaleert).toBe(true);
    expect(b.zekerheid.niveau).toBe("onzeker");
  });

  it("escaleert bij een lege uitkomstenset (alles open)", () => {
    const b = beoordeelGeneratieChecklist(CHECKLIST, {});
    expect(b.escaleert).toBe(true);
    expect(b.onopgelosteCruciaal).toHaveLength(2);
  });
});

describe("gecombineerdeZekerheid", () => {
  it("weegt checklistgronden samen met andere gronden (bv. perceptie)", () => {
    const uitkomsten: ChecklistUitkomsten = { c1: "ok", c2: "ok" };
    const checklistG = checklistGronden(CHECKLIST, uitkomsten);
    const perceptieG = [{ omschrijving: "veld ontbreekt", positief: false, blokkerend: true }];
    const z = gecombineerdeZekerheid(checklistG, perceptieG);
    // Een blokkerende perceptiegrond haalt het geheel naar "onzeker".
    expect(z.niveau).toBe("onzeker");
    expect(z.gronden.length).toBe(checklistG.length + perceptieG.length);
  });
});
