#!/usr/bin/env node

const { spawn, spawnSync } = require("node:child_process");

const windowsUserInfoCompat =
  process.platform === "win32"
    ? ["--import", "data:text/javascript,process.geteuid=()=>1"]
    : [];
const inheritedNodeOptions = String(process.env.NODE_OPTIONS ?? "").trim();
const childNodeOptions =
  process.platform === "win32"
    ? [
        inheritedNodeOptions,
        "--import=data:text/javascript,process.geteuid=()=>1",
      ]
        .filter(Boolean)
        .join(" ")
    : inheritedNodeOptions;
const parentPid = process.ppid;
const child = spawn(
  process.execPath,
  [
    ...windowsUserInfoCompat,
    "--import",
    "tsx",
    "--test",
    ...process.argv.slice(2),
  ],
  {
    cwd: process.cwd(),
    env: childNodeOptions
      ? { ...process.env, NODE_OPTIONS: childNodeOptions }
      : process.env,
    stdio: "inherit",
    windowsHide: true,
  },
);

let settled = false;
let parentWatch;
let maxRunTimer;

function stopChildTree() {
  if (!child.pid) return;
  if (process.platform === "win32") {
    const stopped = spawnSync(
      "taskkill",
      ["/PID", String(child.pid), "/T", "/F"],
      { stdio: "ignore", windowsHide: true },
    );
    if (!stopped.error && stopped.status === 0) return;
  }
  try {
    child.kill("SIGTERM");
  } catch {
    // The child may already have exited between the liveness check and kill.
  }
}

function finish(exitCode, stopTree = false) {
  if (settled) return;
  settled = true;
  if (parentWatch) clearInterval(parentWatch);
  if (maxRunTimer) clearTimeout(maxRunTimer);
  if (stopTree) stopChildTree();
  process.exit(exitCode);
}

child.once("error", (error) => {
  process.stderr.write(`${error.message}\n`);
  finish(1, true);
});
child.once("exit", (code) => finish(code ?? 1));

const shutdownSignals = [
  ["SIGINT", 130],
  ["SIGTERM", 143],
  ["SIGHUP", 129],
];
if (process.platform === "win32") shutdownSignals.push(["SIGBREAK", 131]);
for (const [signal, exitCode] of shutdownSignals) {
  process.on(signal, () => finish(exitCode, true));
}

parentWatch = setInterval(() => {
  if (!parentPid || parentPid === process.pid) return;
  try {
    process.kill(parentPid, 0);
  } catch (error) {
    if (error?.code !== "ESRCH") return;
    process.stderr.write("test runner parent exited; stopping child process tree\n");
    finish(1, true);
  }
}, 1000);
parentWatch.unref();

const configuredMaxRunMs = Number(process.env.CODEFLOW_TEST_MAX_MS ?? 0);
if (Number.isFinite(configuredMaxRunMs) && configuredMaxRunMs > 0) {
  maxRunTimer = setTimeout(() => {
    process.stderr.write(
      `test runner exceeded CODEFLOW_TEST_MAX_MS=${configuredMaxRunMs}; stopping child process tree\n`,
    );
    finish(124, true);
  }, configuredMaxRunMs);
  maxRunTimer.unref();
}
