// ── Tijdelijke opslag voor gegenereerde .docx-bestanden ──────────────────────
// Sommige chatomgevingen (o.a. Copilot Studio) kunnen een base64-gecodeerd
// bestand niet omzetten naar een downloadbare bijlage in de chat. Daarom
// bewaart deze cache het gegenereerde bestand kortstondig onder een
// ongokbaar token, zodat de agent in plaats daarvan gewoon een downloadlink
// (/api/bestanden/{token}) kan delen met de gebruiker. Bevat nooit
// persoonsgegevens: de invoer is per conventie al geanonimiseerd (zie
// AGENTS.md).
//
// Op een serverless platform (bv. Vercel) draait elke aanroep mogelijk in een
// andere instantie/container: een zuiver in-memory Map zou de link dan vaak
// al na enkele seconden "verlopen" laten lijken, ruim vóór de eigenlijke
// TTL. Daarom valt deze cache terug op Supabase (zelfde service-client en
// "geen configuratie? blijf lokaal werken"-conventie als lib/supabase/server
// en lib/api/jsonb-sync-route) wanneer die beschikbaar is, en enkel op een
// in-memory Map als noodoplossing zonder Supabase (bv. lokale dev).
//
// Vereiste tabel (SQL, eenmalig in de Supabase SQL Editor):
//
//   create table gegenereerde_bestanden (
//     token        text primary key,
//     bestandsnaam text not null,
//     mime_type    text not null,
//     data_base64  text not null,
//     verloopt_om  timestamptz not null
//   );

import { maakServiceClient } from "@/lib/supabase/server";
import { naAntwoord } from "@/lib/naAntwoord";

// 24 uur: de notaris moet het werkdocument ook later op de dag (of de ochtend
// nadien) nog kunnen openen zonder het opnieuw te laten genereren.
const TTL_MS = 24 * 60 * 60 * 1000;
const TABEL = "gegenereerde_bestanden";

export interface CachedBestand {
  buffer: Buffer;
  mimeType: string;
  bestandsnaam: string;
}

interface InMemoryBestand extends CachedBestand {
  verlooptOm: number;
}

const geheugenCache = new Map<string, InMemoryBestand>();

function ruimGeheugenCacheOp() {
  const nu = Date.now();
  for (const [token, item] of geheugenCache) {
    if (item.verlooptOm < nu) geheugenCache.delete(token);
  }
}

export async function bewaarBestand(buffer: Buffer, mimeType: string, bestandsnaam: string): Promise<string> {
  const token = crypto.randomUUID();
  const sb = maakServiceClient();

  if (sb) {
    // Opportunistische opruiming: verlopen bestanden verwijderen zodat de
    // tabel niet blijft aangroeien (geen aparte cron nodig). Via naAntwoord()
    // — NA het antwoord — zodat deze niet-kritische opruiming de generatie/
    // het downloadUrl nooit vertraagt (zie leverWordBestand voor dezelfde
    // reden bij de notaris-notificatie).
    naAntwoord(() => sb.from(TABEL).delete().lt("verloopt_om", new Date().toISOString()));
    const verlooptOm = new Date(Date.now() + TTL_MS).toISOString();
    const { error } = await sb.from(TABEL).insert({
      token,
      bestandsnaam,
      mime_type: mimeType,
      data_base64: buffer.toString("base64"),
      verloopt_om: verlooptOm,
    });
    if (!error) return token;
    // Bij een opslagfout (bv. tabel ontbreekt nog) toch een werkende link
    // teruggeven via de in-memory fallback, in plaats van de hele
    // bestandsgeneratie te laten falen.
  }

  ruimGeheugenCacheOp();
  geheugenCache.set(token, { buffer, mimeType, bestandsnaam, verlooptOm: Date.now() + TTL_MS });
  return token;
}

export async function haalBestand(token: string): Promise<CachedBestand | undefined> {
  const sb = maakServiceClient();
  if (sb) {
    const { data } = await sb
      .from(TABEL)
      .select("bestandsnaam, mime_type, data_base64, verloopt_om")
      .eq("token", token)
      .maybeSingle();
    if (data) {
      if (new Date(data.verloopt_om).getTime() < Date.now()) {
        await sb.from(TABEL).delete().eq("token", token);
        return undefined;
      }
      return {
        buffer: Buffer.from(data.data_base64, "base64"),
        mimeType: data.mime_type,
        bestandsnaam: data.bestandsnaam,
      };
    }
  }

  const item = geheugenCache.get(token);
  if (!item) return undefined;
  if (item.verlooptOm < Date.now()) {
    geheugenCache.delete(token);
    return undefined;
  }
  return item;
}
