import { NextResponse, type NextRequest } from "next/server";

import { lotteryApiOrigin } from "./src/lib/lottery-api-base";
import { generateCSP, nonCspSecurityHeaders } from "./src/lib/csp-config";

type RuntimeOriginsEnvelope = {
  code?: number;
  data?: {
    iframe_allowed_origins?: unknown;
  };
};

const RUNTIME_ORIGINS_TTL_MS = 60_000;
let cachedRuntimeOrigins: string[] | null = null;
let cachedAt = 0;

async function loadRuntimeOrigins(): Promise<string[]> {
  if (cachedRuntimeOrigins !== null && Date.now() - cachedAt < RUNTIME_ORIGINS_TTL_MS) {
    return cachedRuntimeOrigins;
  }

  try {
    const url = `${lotteryApiOrigin()}/api/v1/integration/runtime-origins`;
    const response = await fetch(url, {
      headers: { Accept: "application/json" },
      cache: "no-store",
    });

    if (!response.ok) return [];

    const payload = (await response.json()) as RuntimeOriginsEnvelope;
    const origins = payload.data?.iframe_allowed_origins;

    if (!Array.isArray(origins)) return [];

    cachedRuntimeOrigins = origins.filter((origin): origin is string => typeof origin === "string");
    cachedAt = Date.now();

    return cachedRuntimeOrigins;
  } catch {
    return cachedRuntimeOrigins ?? [];
  }
}

export async function middleware(_request: NextRequest): Promise<NextResponse> {
  const response = NextResponse.next();
  const runtimeOrigins = await loadRuntimeOrigins();

  response.headers.set("Content-Security-Policy", generateCSP(runtimeOrigins));
  for (const header of nonCspSecurityHeaders) {
    response.headers.set(header.key, header.value);
  }

  return response;
}

export const config = {
  matcher: ["/((?!api|_next/static|_next/image|favicon.ico|.*\\..*).*)"],
};
