import { resolve, extname } from 'path';
import { readFile } from 'fs/promises';
import type { IncomingMessage, ServerResponse } from 'http';

/** Supported content types by file extension. */
const CONTENT_TYPES: Record<string, string> = {
  '.html': 'text/html',
  '.css': 'text/css',
  '.js': 'application/javascript',
  '.mjs': 'application/javascript',
  '.json': 'application/json',
  '.svg': 'image/svg+xml',
  '.png': 'image/png',
  '.ico': 'image/x-icon',
  '.woff2': 'font/woff2',
};

/**
 * Serve static files from a directory.
 *
 * - Only handles GET requests
 * - Maps `/` to `/index.html`
 * - Protects against path traversal (resolved path must be within uiDir)
 * - Returns true if a file was served, false otherwise (caller should 404)
 */
export async function serveStatic(
  req: IncomingMessage,
  res: ServerResponse,
  uiDir: string,
): Promise<boolean> {
  // Only serve GET requests
  if (req.method !== 'GET') {
    return false;
  }

  // Parse the pathname from the request URL
  const urlStr = req.url ?? '/';
  let pathname: string;
  try {
    // Use URL constructor to safely parse; base doesn't matter for pathname extraction
    const parsed = new URL(urlStr, 'http://localhost');
    pathname = parsed.pathname;
  } catch {
    return false;
  }

  // Map root to index.html
  if (pathname === '/') {
    pathname = '/index.html';
  }

  // Check that the file extension is one we serve
  const ext = extname(pathname);
  const contentType = CONTENT_TYPES[ext];
  if (!contentType) {
    return false;
  }

  // Resolve the absolute path to the requested file
  // Strip leading slash to get a relative path for resolve()
  const relativePath = pathname.slice(1);
  const resolvedUiDir = resolve(uiDir);
  const filePath = resolve(resolvedUiDir, relativePath);

  // Path traversal protection: ensure the resolved path is within uiDir
  if (!filePath.startsWith(resolvedUiDir + '/') && filePath !== resolvedUiDir) {
    return false;
  }

  // Try to read and serve the file
  try {
    const content = await readFile(filePath);
    res.writeHead(200, { 'Content-Type': contentType });
    res.end(content);
    return true;
  } catch {
    // File doesn't exist or can't be read — let the caller handle it
    return false;
  }
}
