import { readFile, stat } from "node:fs/promises";
import { join } from "node:path";
import { NextResponse } from "next/server";

/**
 * Serve uploaded media files from /app/public/uploads at runtime.
 *
 * Next.js standalone build only includes files known at build time under
 * `public/`, so user uploads written to a mounted volume aren't picked up
 * by the static handler. This route reads them straight off disk.
 *
 * Cached aggressively because filenames already include a random hash.
 */
export const runtime = "nodejs";
export const dynamic = "force-dynamic";

const UPLOAD_DIR = process.env.MEDIA_UPLOAD_DIR ?? "public/uploads";

const MIME_BY_EXT: Record<string, string> = {
  jpg: "image/jpeg",
  jpeg: "image/jpeg",
  png: "image/png",
  webp: "image/webp",
  avif: "image/avif",
  gif: "image/gif",
  svg: "image/svg+xml",
  pdf: "application/pdf",
};

function safePath(parts: string[]): string | null {
  // Reject any segment containing path-traversal characters.
  for (const p of parts) {
    if (!p || p === "." || p === ".." || p.includes("\\") || p.includes("/")) return null;
  }
  return parts.join("/");
}

export async function GET(
  _req: Request,
  { params }: { params: Promise<{ path: string[] }> },
) {
  const { path } = await params;
  const rel = safePath(path);
  if (!rel) return new NextResponse("Bad path", { status: 400 });

  const abs = join(process.cwd(), UPLOAD_DIR, rel);
  try {
    const st = await stat(abs);
    if (!st.isFile()) return new NextResponse("Not found", { status: 404 });
    const buf = await readFile(abs);
    const ext = rel.split(".").pop()?.toLowerCase() ?? "";
    const mime = MIME_BY_EXT[ext] ?? "application/octet-stream";
    return new NextResponse(new Uint8Array(buf), {
      status: 200,
      headers: {
        "content-type": mime,
        "cache-control": "public, max-age=31536000, immutable",
        "content-length": String(buf.length),
      },
    });
  } catch {
    return new NextResponse("Not found", { status: 404 });
  }
}
