import { readFile, stat } from "node:fs/promises";
import { extname, join, normalize, resolve } from "node:path";
import type { Page } from "@playwright/test";

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

function safeDistPath(distDir: string, pathname: string) {
  const decoded = decodeURIComponent(pathname);
  const relative = decoded.replace(/^\/+/, "");
  const safe = normalize(relative).replace(/^(\.\.(?:[\\/]|$))+/, "");
  return join(distDir, safe);
}

async function resolveStaticFile(distDir: string, pathname: string) {
  const indexPath = join(distDir, "index.html");
  let filePath = safeDistPath(
    distDir,
    pathname === "/" ? "/index.html" : pathname,
  );

  try {
    const fileStat = await stat(filePath);
    if (fileStat.isDirectory()) {
      filePath = join(filePath, "index.html");
    }
  } catch {
    filePath = indexPath;
  }

  try {
    return {
      body: await readFile(filePath),
      contentType:
        contentTypes[extname(filePath).toLowerCase()] ??
        "application/octet-stream",
    };
  } catch {
    return null;
  }
}

export async function installAdminFrontStaticRoutes(
  page: Page,
  options: {
    distDir?: string;
    origin?: string;
  } = {},
) {
  const origin = options.origin ?? "http://adminfront.test";
  const distDir = resolve(
    options.distDir ??
      process.env.ADMINFRONT_DIST_DIR ??
      "/tmp/baron-sso-adminfront-dist",
  );

  await page.route(`${origin}/**`, async (route) => {
    const url = new URL(route.request().url());
    if (url.pathname === "/api" || url.pathname.startsWith("/api/")) {
      await route.fallback();
      return;
    }

    const file = await resolveStaticFile(distDir, url.pathname);
    if (!file) {
      await route.fulfill({
        status: 500,
        contentType: "application/json; charset=utf-8",
        body: JSON.stringify({ error: "adminfront_dist_not_found" }),
      });
      return;
    }

    await route.fulfill({
      status: 200,
      contentType: file.contentType,
      body: file.body,
    });
  });
}
