// ── API: één werkdossier-sessie raadplegen en bijwerken/regenereren ──────────
// GET: de volledige bewaarde generatie-invoer + historiek van een sessie.
// POST: aanvullende stukken aanleveren (parameters, kenmerken, facultatieve
// onderdelen, notities, brieven, …) en het .docx REGENEREREN met de
// samengevoegde invoer — zonder dat de aanroeper alles opnieuw moet opgeven.
// De regeneratie hergebruikt letterlijk de bestaande generatoren (de
// route-handlers van genereerWerkdossierAlsWord en haalModeldocumentAlsWord),
// zodat sessie-regeneratie en verse generatie nooit kunnen uiteenlopen.

import { NextResponse } from "next/server";
import { haalSessie, werkSessieBij, type WerkdossierSessie } from "@/lib/dossier/werkdossierSessies";
import { POST as genereerWerkdossier } from "@/app/api/dossier/word/route";
import { GET as genereerModeldocumentWord } from "@/app/api/modeldocumenten/[id]/word/route";

export const dynamic = "force-dynamic";
// Regenereert in-process via de word-routes — zelfde ruime uitvoeringstijd
// (zie app/api/mcp/route.ts voor de volledige toelichting).
export const maxDuration = 60;

function nietGevonden(token: string) {
  return NextResponse.json(
    { fout: `Onbekende of verlopen werkdossier-sessie "${token}" — sessies blijven 24 uur na de laatste wijziging geldig (zie lijstWerkdossierSessies).` },
    { status: 404 }
  );
}

export async function GET(_request: Request, { params }: { params: Promise<{ token: string }> }) {
  const { token } = await params;
  const sessie = await haalSessie(token);
  if (!sessie) return nietGevonden(token);
  return NextResponse.json({
    ...sessie,
    toelichting:
      "Werk bij met POST op dezelfde URL: 'parameters' (object, wordt samengevoegd met de bestaande), " +
      "'verwijderParameters' (namen), 'kenmerken' (object), 'facultatief' (kommagescheiden, vervangt), " +
      "'notities' (vervangt), 'veldenJson' (JSON-object, shallow merge voor overige velden zoals " +
      "modelbrievenJson/belastingJson) en 'wijziging' (korte omschrijving voor de historiek). " +
      "Het antwoord bevat het geregenereerde .docx (downloadUrl, 24 uur geldig).",
  });
}

/** Parameters van de sessie-invoer, ongeacht de soort (body-JSON vs. query). */
function huidigeParameters(sessie: WerkdossierSessie): Record<string, string> {
  if (sessie.soort === "werkdossier") {
    const json = sessie.invoer.modeldocumentParametersJson;
    if (typeof json === "string" && json.trim()) {
      try {
        return JSON.parse(json) as Record<string, string>;
      } catch {
        return {};
      }
    }
    return {};
  }
  const query = (sessie.invoer.query ?? {}) as Record<string, string>;
  return { ...query };
}

export async function POST(request: Request, { params }: { params: Promise<{ token: string }> }) {
  const { token } = await params;
  const sessie = await haalSessie(token);
  if (!sessie) return nietGevonden(token);

  let body: Record<string, unknown>;
  try {
    body = ((await request.json()) ?? {}) as Record<string, unknown>;
  } catch {
    return NextResponse.json({ fout: "Ongeldige JSON-body." }, { status: 400 });
  }

  const parameters = (body.parameters ?? {}) as Record<string, unknown>;
  // Zowel een JSON-array als een kommagescheiden string is toegelaten.
  const verwijderParameters = Array.isArray(body.verwijderParameters)
    ? (body.verwijderParameters as string[])
    : typeof body.verwijderParameters === "string"
      ? body.verwijderParameters.split(",").map((n) => n.trim()).filter(Boolean)
      : [];
  const kenmerken = (body.kenmerken ?? {}) as Record<string, unknown>;
  const facultatief = typeof body.facultatief === "string" ? body.facultatief : undefined;
  const notities = typeof body.notities === "string" ? body.notities : undefined;
  const wijziging = typeof body.wijziging === "string" && body.wijziging.trim() ? body.wijziging.trim() : "Bijgewerkt en geregenereerd";

  let extraVelden: Record<string, unknown> = {};
  if (typeof body.veldenJson === "string" && body.veldenJson.trim()) {
    try {
      extraVelden = JSON.parse(body.veldenJson) as Record<string, unknown>;
    } catch {
      return NextResponse.json({ fout: 'Parameter "veldenJson" is geen geldige JSON-tekst.' }, { status: 400 });
    }
  }

  // ── Invoer samenvoegen: bestaande sessie + aanvullende stukken ──────────────
  const samengevoegdeParameters = { ...huidigeParameters(sessie) };
  for (const [naam, waarde] of Object.entries(parameters)) {
    if (waarde !== undefined && waarde !== null) samengevoegdeParameters[naam] = String(waarde);
  }
  for (const naam of verwijderParameters) delete samengevoegdeParameters[naam];

  let nieuweInvoer: Record<string, unknown>;
  let regeneratie: Response;
  const origin = new URL(request.url).origin;

  if (sessie.soort === "werkdossier") {
    nieuweInvoer = {
      ...sessie.invoer,
      ...extraVelden,
      ...Object.fromEntries(Object.entries(kenmerken).filter(([, w]) => w !== undefined && w !== null)),
      modeldocumentParametersJson: JSON.stringify(samengevoegdeParameters),
      ...(facultatief !== undefined ? { modeldocumentFacultatief: facultatief } : {}),
      ...(notities !== undefined ? { notities } : {}),
    };
    regeneratie = await genereerWerkdossier(
      new Request(`${origin}/api/dossier/word`, {
        method: "POST",
        headers: { "Content-Type": "application/json", "x-notary-sessie": "overslaan" },
        body: JSON.stringify(nieuweInvoer),
      })
    );
  } else {
    // soort "modeldocument": queryparameters samenvoegen en de GET-generator
    // (incl. kantoorsjabloon-pad) opnieuw aanroepen.
    const query: Record<string, string> = { ...samengevoegdeParameters };
    for (const [naam, waarde] of Object.entries(kenmerken)) {
      if (waarde !== undefined && waarde !== null) query[naam] = String(waarde);
    }
    for (const [naam, waarde] of Object.entries(extraVelden)) {
      if (waarde !== undefined && waarde !== null) query[naam] = String(waarde);
    }
    if (facultatief !== undefined) query.facultatief = facultatief;
    if (notities !== undefined) query.notities = notities;
    const modeldocumentId = String(sessie.invoer.modeldocumentId ?? "");
    nieuweInvoer = { modeldocumentId, query };
    const zoek = new URLSearchParams(query);
    regeneratie = await genereerModeldocumentWord(
      new Request(`${origin}/api/modeldocumenten/${encodeURIComponent(modeldocumentId)}/word?${zoek.toString()}`, {
        headers: { "x-notary-sessie": "overslaan" },
      }),
      { params: Promise.resolve({ id: modeldocumentId }) }
    );
  }

  const resultaat = (await regeneratie.json()) as Record<string, unknown>;
  if (!regeneratie.ok) {
    return NextResponse.json(
      { fout: `Regeneratie mislukt: ${typeof resultaat.fout === "string" ? resultaat.fout : "onbekende fout"}` },
      { status: regeneratie.status }
    );
  }

  // De regeneratie maakte zelf een nieuwe sessie aan (elke generatie doet dat);
  // voor de continuïteit van DEZE sessie werken we haar bij met de nieuwe
  // levering en invoer — het oude token blijft dus hét aanspreekpunt.
  const bijgewerkt = await werkSessieBij(
    sessie,
    nieuweInvoer,
    { bestandsnaam: String(resultaat.bestandsnaam), downloadUrl: String(resultaat.downloadUrl) },
    wijziging
  );

  return NextResponse.json({
    ...resultaat,
    dossierToken: bijgewerkt.token,
    dossierVerlooptOm: bijgewerkt.verlooptOm,
    historiek: bijgewerkt.historiek,
    toegepasteWijziging: wijziging,
  });
}
