import { describe, it, expect } from "vitest";
import JSZip from "jszip";
import { POST } from "./route";
import { haalBestand } from "@/lib/word/bestandenCache";

const PNG_1X1 =
  "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=";

const MODEL_ID = "verkoopovereenkomst-compromis";
const BRIEF_ID = "verkoop-koper-eerste-contact-nl";

function maakRequest(body: Record<string, unknown>): Request {
  return new Request("http://localhost/api/dossier/word", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(body),
  });
}

describe("POST /api/dossier/word", () => {
  it("bundelt ontwerp, modelmail en aktekosten in één .docx-bestand", async () => {
    const res = await POST(
      maakRequest({
        modeldocumentId: MODEL_ID,
        modeldocumentParametersJson: JSON.stringify({ prijs_letters: "DRIEHONDERDDUIZEND", prijs_cijfers: "300000" }),
        modelbrievenJson: JSON.stringify([{ id: BRIEF_ID, parameters: {} }]),
        akteType: "verkoop",
        bedrag: "300000",
        gewest: "Vlaanderen",
      })
    );
    expect(res.status).toBe(200);
    const json = await res.json();
    expect(json.bestandsnaam).toContain("(nai)");
    expect(json.bestandsnaam.endsWith(".docx")).toBe(true);
    expect(json.mimeType).toBe(
      "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
    );
    // De base64-drempel is bewust laag (zie MAX_BASE64_BYTES in route.ts): een
    // chatgeoriënteerde orchestrator (bv. Copilot Studio) kan zelfs bij een
    // geslaagde tool-aanroep alsnog vastlopen op een te grote payload in zijn
    // eigen antwoord-synthese. Dit gebundelde .docx is realistisch dus meestal
    // groter dan de drempel; haal de buffer in dat geval via downloadUrl.
    const token = json.downloadUrl.split("/").pop();
    const buffer = json.base64 ? Buffer.from(json.base64, "base64") : (await haalBestand(token))!.buffer;
    expect(buffer.subarray(0, 2).toString("latin1")).toBe("PK");
    expect(json.disclaimer).toMatch(/[Ww]erkdocument/);
  });

  it("400 bij ontbrekende modeldocumentId", async () => {
    const res = await POST(maakRequest({ modelbrievenJson: "[]" }));
    expect(res.status).toBe(400);
  });

  it("400 bij onbekend modeldocument-id", async () => {
    const res = await POST(maakRequest({ modeldocumentId: "bestaat-niet", modelbrievenJson: "[]" }));
    expect(res.status).toBe(400);
  });

  it("400 bij onbekende modelbrief-id", async () => {
    const res = await POST(
      maakRequest({ modeldocumentId: MODEL_ID, modelbrievenJson: JSON.stringify([{ id: "bestaat-niet" }]) })
    );
    expect(res.status).toBe(400);
  });

  it("werkt ook zonder modelmails en zonder afrekening (enkel het ontwerp)", async () => {
    const res = await POST(
      maakRequest({ modeldocumentId: MODEL_ID, modelbrievenJson: "[]" })
    );
    expect(res.status).toBe(200);
  });

  it("neemt 'notities' en een bijgevoegde afbeelding effectief op in het .docx", async () => {
    const res = await POST(
      maakRequest({
        modeldocumentId: MODEL_ID,
        modelbrievenJson: "[]",
        notities: "De koper wenst een snelle overdracht, ten laatste eind volgende maand.",
        afbeeldingenJson: JSON.stringify([
          { bestandsnaam: "stedenbouw-p1.png", base64: PNG_1X1, bijschrift: "Stedenbouwkundige inlichtingen, p. 1" },
        ]),
      })
    );
    expect(res.status).toBe(200);
    const json = await res.json();
    const token = json.downloadUrl.split("/").pop();
    const buffer = json.base64 ? Buffer.from(json.base64, "base64") : (await haalBestand(token))!.buffer;
    const zip = await JSZip.loadAsync(buffer);
    const documentXml = await zip.file("word/document.xml")!.async("string");
    expect(documentXml).toContain("snelle overdracht");
    expect(documentXml).toContain("Stedenbouwkundige inlichtingen, p. 1");
    // De afbeelding zelf moet effectief als media-bestand in het .docx zitten.
    const mediaBestanden = Object.keys(zip.files).filter((naam) => naam.startsWith("word/media/"));
    expect(mediaBestanden.length).toBeGreaterThan(0);
  });
});
