import { describe, it, expect } from "vitest";
import { structuurAnkerUitOntwerp, structuurAnkerParagrafen, KORTE_COPILOT_PROMPT } from "./aiAgentInstructies";
import { WERKDOSSIER_AGENT_PROMPT, WERKBLAD_KORTE_PROMPT } from "@/data/ai-prompts";
import { vindOverdrachtsgrensSchendingen } from "./overdrachtsgrensLint";

describe("structuurAnkerUitOntwerp", () => {
  it("haalt de doorlopend genummerde hoofdstukken uit het gegenereerde ontwerp, in volgorde", () => {
    const ontwerp = [
      "VERKOOPOVEREENKOMST",
      "## 1. DÉSIGNATION DU VENDEUR ET DE L'ACQUÉREUR",
      "tekst …",
      "## 2. DESCRIPTION DU BIEN",
      "tekst …",
      "### Een subkop hoort hier niet bij",
      "## 19. SANCTIONS EN CAS DE NON-RESPECT DES ENGAGEMENTS",
      "tekst …",
    ].join("\n");
    expect(structuurAnkerUitOntwerp(ontwerp)).toEqual([
      { nummer: 1, titel: "DÉSIGNATION DU VENDEUR ET DE L'ACQUÉREUR" },
      { nummer: 2, titel: "DESCRIPTION DU BIEN" },
      { nummer: 19, titel: "SANCTIONS EN CAS DE NON-RESPECT DES ENGAGEMENTS" },
    ]);
  });

  it("geeft een lege lijst voor een ontwerp zonder genummerde hoofdstukken", () => {
    expect(structuurAnkerUitOntwerp("Geen enkele kop hier.")).toEqual([]);
  });
});

describe("structuurAnkerParagrafen", () => {
  it("bouwt een sectie met de titel 'Structuuranker' en één regel per hoofdstuk", () => {
    const ontwerp = "## 1. IDENTIFICATIE\ntekst\n## 2. PRIJS\ntekst";
    const paragrafen = structuurAnkerParagrafen(ontwerp, "nl");
    const platteTekst = paragrafen
      .map((p) => JSON.stringify(p))
      .join("\n");
    expect(platteTekst).toContain("Structuuranker");
    expect(platteTekst).toContain("1. IDENTIFICATIE");
    expect(platteTekst).toContain("2. PRIJS");
  });

  it("meldt duidelijk wanneer er geen genummerde hoofdstukken zijn (nooit stilzwijgend weglaten)", () => {
    const paragrafen = structuurAnkerParagrafen("Geen kop hier.", "nl");
    const platteTekst = paragrafen.map((p) => JSON.stringify(p)).join("\n");
    expect(platteTekst).toContain("Geen genummerde hoofdstukken gevonden");
  });

  it("FR: gebruikt de Franstalige titel en meldtekst", () => {
    const paragrafen = structuurAnkerParagrafen("## 1. IDENTIFICATION\ntexte", "fr");
    const platteTekst = paragrafen.map((p) => JSON.stringify(p)).join("\n");
    expect(platteTekst).toContain("Ancre de structure");
    expect(platteTekst).toContain("1. IDENTIFICATION");
  });
});

// ── w:noProof op de werkblad-/instructiepagina's (backlog punt 30) ──────────
// Deze pagina's worden vóór gebruik verwijderd; hun runs dragen noProof zodat
// Word er geen spelling op controleert (geen rode kronkellijnen op prompttekst).
describe("noProof op de instructie-runs (docx-library-pad)", () => {
  it("elke instructiebouwer levert runs met w:noProof", async () => {
    const {
      korteCopilotPromptParagrafen,
      instructieSectieParagrafen,
      ontbrekendeGegevensParagrafen,
      gebruikersNotitiesParagrafen,
      bevindingenParagrafen,
    } = await import("./aiAgentInstructies");
    const bouwers: Record<string, unknown[]> = {
      kortePrompt: korteCopilotPromptParagrafen("nl"),
      instructies: instructieSectieParagrafen(),
      ontbrekend: ontbrekendeGegevensParagrafen("tekst met [AAN TE VULLEN: prijs]", "nl"),
      notities: gebruikersNotitiesParagrafen("een notitie", "nl"),
      anker: structuurAnkerParagrafen("## 1. IDENTIFICATIE\ntekst", "nl"),
      bevindingen: bevindingenParagrafen([{ parameter: "prijs", waarde: "100" }], "nl"),
    };
    for (const [naam, paragrafen] of Object.entries(bouwers)) {
      const json = paragrafen.map((p) => JSON.stringify(p)).join("\n");
      expect(json, `bouwer '${naam}' mist w:noProof op zijn runs`).toContain('"w:noProof"');
    }
  });
});

// ── Overdrachtsgrens-lint (twee-agent gouden pad, opdracht notaris 2026-07-12)
// Spec: OVERDRACHT-TWEE-AGENTS.md. De teksten die letterlijk in elk
// gegenereerd .docx worden ingebed, mogen geen verwijzing bevatten die enkel
// agent 1 (met Notary.AI-MCP-toegang) kan invullen — agent 2 (algemeen, zonder
// die toegang) moet ze zelfstandig kunnen volgen. Een nieuwe toolverwijzing
// of sessie-/dossier-ID-aanname die per ongeluk in de prompt sluipt, faalt
// hier meteen in plaats van pas bij een productieklacht.
describe("bijgevoegdeStukkenParagrafen", () => {
  it("geeft een lege lijst zonder bevindingen (niets om uit af te leiden)", async () => {
    const { bijgevoegdeStukkenParagrafen } = await import("./aiAgentInstructies");
    expect(bijgevoegdeStukkenParagrafen(undefined, "nl")).toEqual([]);
    expect(bijgevoegdeStukkenParagrafen([], "nl")).toEqual([]);
  });

  it("herleidt de unieke, niet-lege 'bron'-vermeldingen, in volgorde van eerste voorkomen", async () => {
    const { bijgevoegdeStukkenParagrafen } = await import("./aiAgentInstructies");
    const paragrafen = bijgevoegdeStukkenParagrafen(
      [
        { parameter: "a", waarde: "1", bron: "compromis p. 1" },
        { parameter: "b", waarde: "2", bron: "EPC-attest" },
        { parameter: "c", waarde: "3", bron: "compromis p. 1" },
        { parameter: "d", waarde: "4", bron: "  " }, // lege/whitespace-bron telt niet mee
        { parameter: "e", waarde: "5" }, // geen bron
      ],
      "nl"
    );
    const tekst = JSON.stringify(paragrafen);
    expect(tekst).toContain("compromis p. 1");
    expect(tekst).toContain("EPC-attest");
    // Precies twee bullets (geen duplicaat, geen lege bron).
    expect((tekst.match(/compromis p\. 1/g) ?? []).length).toBe(1);
  });

  it("toont een expliciete leeg-melding wanneer geen enkele bevinding een bron draagt", async () => {
    const { bijgevoegdeStukkenParagrafen } = await import("./aiAgentInstructies");
    const paragrafen = bijgevoegdeStukkenParagrafen([{ parameter: "a", waarde: "1" }], "nl");
    expect(JSON.stringify(paragrafen)).toContain("Geen brondocumenten vermeld");
  });
});

describe("overdrachtsgrens-lint — ingebedde werkbladteksten blijven zelfstandig voor agent 2", () => {
  it("WERKDOSSIER_AGENT_PROMPT bevat geen agent-1-only-verwijzingen", () => {
    const schendingen = vindOverdrachtsgrensSchendingen(WERKDOSSIER_AGENT_PROMPT);
    expect(schendingen, JSON.stringify(schendingen, null, 2)).toEqual([]);
  });

  it("WERKBLAD_KORTE_PROMPT bevat geen agent-1-only-verwijzingen", () => {
    const schendingen = vindOverdrachtsgrensSchendingen(WERKBLAD_KORTE_PROMPT);
    expect(schendingen, JSON.stringify(schendingen, null, 2)).toEqual([]);
  });

  it("KORTE_COPILOT_PROMPT (NL & FR, zoals ingebed in het .docx) bevat geen agent-1-only-verwijzingen", () => {
    for (const taal of ["nl", "fr"] as const) {
      const schendingen = vindOverdrachtsgrensSchendingen(KORTE_COPILOT_PROMPT[taal]);
      expect(schendingen, `${taal}: ${JSON.stringify(schendingen, null, 2)}`).toEqual([]);
    }
  });
});
