/**
 * Cache für CMS-API-Responses (nur serverseitig, Node fs/crypto).
 * Wird ausschließlich per dynamic import aus cms.ts geladen – nie von Layout/Middleware,
 * damit es nicht ins Client-Bundle gelangt. Flag/State: cms-cache-state.ts.
 */

import { createHash } from "node:crypto";
import { readFile, writeFile, mkdir } from "node:fs/promises";
import { existsSync } from "node:fs";
import { setCmsFromCacheUsed } from "./cms-cache-state";

const CACHE_DIR = `${process.cwd()}/.cache/cms`;

function cacheKeyFromUrl(url: string): string {
  return createHash("sha256").update(url).digest("hex");
}

async function ensureCacheDir(): Promise<void> {
  if (!existsSync(CACHE_DIR)) {
    await mkdir(CACHE_DIR, { recursive: true });
  }
}

interface CachedResponse {
  status: number;
  body: string;
}

async function getCached(key: string): Promise<CachedResponse | null> {
  try {
    const path = `${CACHE_DIR}/${key}.json`;
    if (!existsSync(path)) return null;
    const raw = await readFile(path, "utf-8");
    const data = JSON.parse(raw) as CachedResponse;
    return data?.body != null ? data : null;
  } catch {
    return null;
  }
}

async function setCached(key: string, data: CachedResponse): Promise<void> {
  try {
    await ensureCacheDir();
    const path = `${CACHE_DIR}/${key}.json`;
    await writeFile(path, JSON.stringify(data), "utf-8");
  } catch {
    // Cache schreiben optional
  }
}

/**
 * Fetch mit Cache: bei Erfolg wird die Response in .cache/cms gespeichert (überschreibt vorhanden).
 * Bei Fehler wird versucht, aus dem Cache zu lesen; wenn gefunden, wird usedCacheThisRequest gesetzt.
 */
export async function cachedFetch(url: string): Promise<Response> {
  const key = cacheKeyFromUrl(url);

  try {
    const res = await fetch(url);
    const body = await res.text();
    await setCached(key, { status: res.status, body });
    return new Response(body, {
      status: res.status,
      headers: res.headers,
    });
  } catch {
    const cached = await getCached(key);
    if (cached) {
      setCmsFromCacheUsed();
      return new Response(cached.body, {
        status: cached.status,
        headers: { "Content-Type": "application/json" },
      });
    }
    throw new Error(`CMS nicht erreichbar (${url}) und kein Cache für diese Anfrage.`);
  }
}
