import express from "express";
import { spawn } from "node:child_process";
import path from "node:path";
import { fileURLToPath } from "node:url";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const repoRoot = path.resolve(__dirname, "..");

const app = express();
app.use(express.static(path.join(__dirname, "public")));

function sseHeaders(res) {
  res.setHeader("Content-Type", "text/event-stream; charset=utf-8");
  res.setHeader("Cache-Control", "no-cache, no-transform");
  res.setHeader("Connection", "keep-alive");
  // Nginx proxies may buffer unless disabled; harmless in dev.
  res.setHeader("X-Accel-Buffering", "no");
}

function sseSend(res, event, data) {
  if (event) res.write(`event: ${event}\n`);
  const lines = String(data).split(/\r?\n/);
  for (const line of lines) res.write(`data: ${line}\n`);
  res.write("\n");
}

app.get("/api/run", (req, res) => {
  const prompt = String(req.query.prompt || "").trim();
  const mock = String(req.query.mock || "1") === "1";
  const configPath = String(req.query.config || "./configs/config.yaml");

  if (!prompt) {
    res.status(400).json({ error: "missing prompt" });
    return;
  }

  sseHeaders(res);
  sseSend(res, "status", "starting");

  // Unified in-container execution: Node spawns python directly.
  const py = process.env.PYTHON_BIN || "python";
  const args = [
    path.join(repoRoot, "main.py"),
    "--prompt",
    prompt,
    "--config",
    configPath,
    "--script-only",
  ];
  if (mock) args.push("--mock");

  const child = spawn(py, args, {
    cwd: repoRoot,
    env: process.env,
    stdio: ["ignore", "pipe", "pipe"],
  });

  let buf = "";
  child.stdout.setEncoding("utf8");
  child.stdout.on("data", (chunk) => {
    buf += chunk;
    const parts = buf.split(/\r?\n/);
    buf = parts.pop() || "";
    for (const line of parts) {
      if (!line) continue;
      // Forward raw lines. Frontend will parse SCENE_JSON.
      sseSend(res, "line", line);
    }
  });

  child.stderr.setEncoding("utf8");
  child.stderr.on("data", (chunk) => {
    sseSend(res, "stderr", chunk);
  });

  req.on("close", () => {
    child.kill("SIGTERM");
  });

  child.on("exit", (code) => {
    if (buf.trim()) sseSend(res, "line", buf.trim());
    sseSend(res, "done", String(code ?? 0));
    res.end();
  });
});

const port = Number(process.env.PORT || 3000);
app.listen(port, () => {
  console.log(`[server] http://127.0.0.1:${port}`);
});

