import { existsSync } from "node:fs";
import { readFile, stat } from "node:fs/promises";
import { extname, join, relative, resolve, sep } from "node:path";
import { isSafeRequestPath } from "@wrnexus/core";
import type { Mode } from "@wrnexus/core";

const CONTENT_TYPES: Record<string, string> = {
  ".avif": "image/avif",
  ".css": "text/css; charset=utf-8",
  ".gif": "image/gif",
  ".html": "text/html; charset=utf-8",
  ".ico": "image/x-icon",
  ".jpeg": "image/jpeg",
  ".jpg": "image/jpeg",
  ".js": "text/javascript; charset=utf-8",
  ".json": "application/json; charset=utf-8",
  ".mjs": "text/javascript; charset=utf-8",
  ".pdf": "application/pdf",
  ".png": "image/png",
  ".svg": "image/svg+xml",
  ".txt": "text/plain; charset=utf-8",
  ".wasm": "application/wasm",
  ".webp": "image/webp",
  ".woff": "font/woff",
  ".woff2": "font/woff2",
  ".xml": "application/xml; charset=utf-8",
};

const IMMUTABLE_CACHE = "public, max-age=31536000, immutable";
const REVALIDATE_CACHE = "public, max-age=0, must-revalidate";

function cachePolicy(filePath: string, mode: Mode): string {
  if (mode !== "production") return "no-cache";
  const name = filePath.split(/[\\/]/).pop() ?? "";
  if (/\.html?$/i.test(name)) return REVALIDATE_CACHE;
  // Font URLs are content assets with expensive transfer costs and are almost
  // always renamed when changed. Cache them like fingerprinted build assets.
  if (/\.(?:woff2?|ttf|otf|eot)$/i.test(name)) return IMMUTABLE_CACHE;
  return /(?:^|[.-])[a-f0-9]{8,}(?:[.-]|$)/i.test(name) ? IMMUTABLE_CACHE : "public, max-age=3600";
}

/** Cache the public-dir existence check so it isn't a sync stat on every request. */
const publicDirExistsCache = new Map<string, boolean>();
const productionPublicFileCache = new Map<
  string,
  { body: Uint8Array; contentType: string; cacheControl: string }
>();
const PRODUCTION_PUBLIC_FILE_CACHE_MAX = 256;
function publicDirExists(dir: string): boolean {
  let exists = publicDirExistsCache.get(dir);
  if (exists === undefined) {
    exists = existsSync(dir);
    publicDirExistsCache.set(dir, exists);
  }
  return exists;
}

const DEFAULT_FAVICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
  <rect width="64" height="64" rx="14" fill="#0f172a"/>
  <path d="M15 18h8l5 22 7-22h7l7 22 5-22h8L53 50h-8l-7-21-7 21h-8L15 18z" fill="#6c8cff"/>
</svg>`;

export async function servePublicAsset(
  publicDir: string | undefined,
  pathname: string,
  mode: Mode,
): Promise<Response | null> {
  if (pathname === "/" || pathname.startsWith("/__wrnexus/")) return null;
  if (!isSafeRequestPath(pathname)) return null;

  const fallback = pathname === "/favicon.ico" ? defaultFaviconResponse(mode) : null;
  if (!publicDir || !publicDirExists(publicDir)) return fallback;

  const rel = safePublicRelativePath(pathname);
  if (!rel) return fallback;

  const base = resolve(publicDir);
  let filePath = resolve(base, rel);
  if (!isInside(base, filePath)) return fallback;

  if (mode === "production") {
    const cached = productionPublicFileCache.get(filePath);
    if (cached) {
      productionPublicFileCache.delete(filePath);
      productionPublicFileCache.set(filePath, cached);
      return new Response(cached.body.slice(), {
        headers: {
          "content-type": cached.contentType,
          "cache-control": cached.cacheControl,
          "x-content-type-options": "nosniff",
        },
      });
    }
  }

  try {
    const info = await stat(filePath);
    if (info.isDirectory()) {
      filePath = resolve(filePath, "index.html");
      if (!isInside(base, filePath)) return null;
    }

    const fileInfo = await stat(filePath);
    if (!fileInfo.isFile()) return null;

    const body = await readFile(filePath);
    const contentType =
      CONTENT_TYPES[extname(filePath).toLowerCase()] ?? "application/octet-stream";
    const cacheControl = cachePolicy(filePath, mode);
    if (mode === "production") {
      productionPublicFileCache.set(filePath, {
        body: new Uint8Array(body),
        contentType,
        cacheControl,
      });
      if (productionPublicFileCache.size > PRODUCTION_PUBLIC_FILE_CACHE_MAX) {
        const oldest = productionPublicFileCache.keys().next().value;
        if (oldest) productionPublicFileCache.delete(oldest);
      }
    }
    return new Response(body, {
      headers: {
        "content-type": contentType,
        "cache-control": cacheControl,
        "x-content-type-options": "nosniff",
      },
    });
  } catch {
    return fallback;
  }
}

function defaultFaviconResponse(mode: Mode): Response {
  return new Response(DEFAULT_FAVICON, {
    headers: {
      "content-type": "image/svg+xml; charset=utf-8",
      "cache-control": mode === "production" ? "public, max-age=86400" : "no-cache",
      "x-content-type-options": "nosniff",
    },
  });
}

function safePublicRelativePath(pathname: string): string | null {
  let decoded: string;
  try {
    decoded = decodeURIComponent(pathname);
  } catch {
    return null;
  }

  const segments = decoded.split("/").filter(Boolean);
  if (segments.some((segment) => segment.startsWith(".") || segment.includes("\\"))) {
    return null;
  }

  return segments.length ? join(...segments) : null;
}

function isInside(base: string, target: string): boolean {
  const rel = relative(base, target);
  return rel === "" || (!!rel && !rel.startsWith("..") && !rel.includes(`..${sep}`));
}
