import fs from "node:fs/promises";
import http from "node:http";
import path from "node:path";
import { fileURLToPath } from "node:url";

const sandboxRoot = path.dirname(fileURLToPath(import.meta.url));
const allowedFiles = new Set(["app.js", "logic.mjs", "styles.css"]);
const mimeTypes = { ".js": "text/javascript; charset=utf-8", ".mjs": "text/javascript; charset=utf-8", ".css": "text/css; charset=utf-8" };

function safeScriptJson(value) {
  return JSON.stringify(value).replaceAll("<", "\\u003c");
}

async function renderedIndex() {
  const [template, rules, cases] = await Promise.all([
    fs.readFile(path.join(sandboxRoot, "index.html"), "utf8"),
    fs.readFile(path.join(sandboxRoot, "rules.json"), "utf8").then(JSON.parse),
    fs.readFile(path.join(sandboxRoot, "test-cases.json"), "utf8").then(JSON.parse),
  ]);
  return template
    .replace("__PAYROLL_RULES__", safeScriptJson(rules))
    .replace("__PAYROLL_TEST_CASES__", safeScriptJson(cases));
}

export function createPayrollServer() {
  return http.createServer(async (request, response) => {
    try {
      const pathname = new URL(request.url, "http://127.0.0.1").pathname;
      if (pathname === "/" || pathname === "/index.html") {
        response.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store" });
        response.end(await renderedIndex());
        return;
      }

      const requestedFile = pathname.slice(1);
      if (!allowedFiles.has(requestedFile)) {
        response.writeHead(404, { "content-type": "text/plain; charset=utf-8" });
        response.end("Not found");
        return;
      }
      response.writeHead(200, { "content-type": mimeTypes[path.extname(requestedFile)], "cache-control": "no-store" });
      response.end(await fs.readFile(path.join(sandboxRoot, requestedFile)));
    } catch (error) {
      response.writeHead(500, { "content-type": "text/plain; charset=utf-8" });
      response.end(`Local server error: ${error.message}`);
    }
  });
}

if (process.argv[1] === fileURLToPath(import.meta.url)) {
  const port = Number(process.env.PAYROLL_SANDBOX_PORT ?? 4177);
  createPayrollServer().listen(port, "127.0.0.1", () => {
    console.log(`Payroll Sandbox: http://127.0.0.1:${port}`);
  });
}
