import { describe, it, expect } from "vitest";
import {
  extraheerUitBrondocumenten,
  naarIntakeWaarnemingen,
  perceptieGronden,
  type Brondocument,
  type PerceptieRegister,
  type GeextraheerdeWaarneming,
} from "./perceptie";
import { bepaalZekerheid } from "./autonomie";

// ── AUT-O3 · Perceptielaag-contract ──────────────────────────────────────────
// Bewaakt het contract bronstuk → waarneming → (bestaande merge) + de koppeling
// naar de AUT-O1-gronden. De echte extractors zijn AUT-S1; hier stubs.

const compromisDoc: Brondocument = { ref: "compromis.pdf", bronType: "compromis", tekst: "Prijs: 395.000 EUR" };
const titelDoc: Brondocument = { ref: "titel.pdf", bronType: "eigendomstitel", tekst: "…" };

const register: PerceptieRegister = {
  compromis: (doc) => [{ veldpad: "prijs", waarde: 395000, bronType: doc.bronType, brondocumentRef: doc.ref, zekerheid: "zeker" }],
  eigendomstitel: (doc) => [{ veldpad: "goed.adres", waarde: "Bosstraat 45", bronType: doc.bronType, brondocumentRef: doc.ref, zekerheid: "zeker" }],
};

describe("extraheerUitBrondocumenten", () => {
  it("laat de bijhorende extractor lopen en verzamelt de waarnemingen", () => {
    const r = extraheerUitBrondocumenten([compromisDoc, titelDoc], register);
    expect(r.waarnemingen.map((w) => w.veldpad).sort()).toEqual(["goed.adres", "prijs"]);
    expect(r.onbekendeBronnen).toEqual([]);
  });

  it("raadt nooit: een bronstuk zonder extractor belandt in onbekendeBronnen", () => {
    const bodem: Brondocument = { ref: "bodem.pdf", bronType: "bodemattest", tekst: "blanco" };
    const r = extraheerUitBrondocumenten([compromisDoc, bodem], register);
    expect(r.onbekendeBronnen).toEqual(["bodem.pdf"]);
    expect(r.waarnemingen).toHaveLength(1);
  });
});

describe("naarIntakeWaarnemingen — koppelt aan de bestaande merge", () => {
  it("mapt veldpad/bronType/ref naar het IntakeExtraWaarneming-formaat", () => {
    const r = extraheerUitBrondocumenten([compromisDoc], register);
    expect(naarIntakeWaarnemingen(r)).toEqual([
      { veld: "prijs", waarde: 395000, bron: "compromis", brondocumentId: "compromis.pdf" },
    ]);
  });
});

describe("perceptieGronden — voedt AUT-O1", () => {
  it("vereist veld met zekerheid waargenomen → positieve grond", () => {
    const r = extraheerUitBrondocumenten([compromisDoc], register);
    const gronden = perceptieGronden(r, ["prijs"]);
    expect(gronden).toEqual([{ omschrijving: 'Vereist veld "prijs" is met zekerheid waargenomen.', positief: true }]);
    expect(bepaalZekerheid(gronden).niveau).toBe("zeker");
  });

  it("ontbrekend vereist veld → blokkerende negatieve grond → onzeker", () => {
    const r = extraheerUitBrondocumenten([compromisDoc], register);
    const gronden = perceptieGronden(r, ["prijs", "goed.adres"]);
    expect(gronden.find((g) => g.omschrijving.includes("goed.adres"))).toMatchObject({ positief: false, blokkerend: true });
    expect(bepaalZekerheid(gronden).niveau).toBe("onzeker");
  });

  it("tegenstrijdige bronnen voor één veld → blokkerende negatieve grond", () => {
    const waarnemingen: GeextraheerdeWaarneming[] = [
      { veldpad: "prijs", waarde: 395000, bronType: "compromis", zekerheid: "zeker" },
      { veldpad: "prijs", waarde: 400000, bronType: "eigendomstitel", zekerheid: "zeker" },
    ];
    const gronden = perceptieGronden({ waarnemingen, onbekendeBronnen: [] }, ["prijs"]);
    expect(gronden[0]).toMatchObject({ positief: false, blokkerend: true });
  });

  it("lage-zekerheid-waarneming → niet-blokkerende negatieve grond", () => {
    const waarnemingen: GeextraheerdeWaarneming[] = [{ veldpad: "prijs", waarde: 395000, bronType: "compromis", zekerheid: "onzeker" }];
    const gronden = perceptieGronden({ waarnemingen, onbekendeBronnen: [] }, ["prijs"]);
    expect(gronden[0]).toMatchObject({ positief: false });
    expect(gronden[0].blokkerend).toBeUndefined();
  });

  it("onbekend bronstuk → blokkerende negatieve grond", () => {
    const gronden = perceptieGronden({ waarnemingen: [], onbekendeBronnen: ["x.pdf"] }, []);
    expect(gronden[0]).toMatchObject({ positief: false, blokkerend: true });
  });
});
