import { spawnSync } from "node:child_process";
import { chmodSync, existsSync, mkdirSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
import path from "node:path";

const bootRepo = requiredEnv("HWLAB_BOOT_REPO");
const bootCommit = requiredEnv("HWLAB_BOOT_COMMIT");
const bootSh = requiredEnv("HWLAB_BOOT_SH");
const bootRef = requiredEnv("HWLAB_BOOT_REF");
const checkoutDir = process.env.HWLAB_BOOT_CHECKOUT_DIR || "/workspace/hwlab-boot/repo";
const runtimeNodeModules = process.env.HWLAB_RUNTIME_NODE_MODULES || "/opt/hwlab-env/node_modules";

if (!/^[a-f0-9]{40}$/u.test(bootCommit)) fail("HWLAB_BOOT_COMMIT must be a full 40-char SHA");
if (path.isAbsolute(bootSh) || bootSh.split("/").includes("..")) fail("HWLAB_BOOT_SH must be repo-relative");
if (
  !/^[A-Za-z0-9._/-]+$/u.test(bootRef) ||
  bootRef.startsWith("-") ||
  bootRef.includes("..")
) fail("HWLAB_BOOT_REF must be a safe branch or ref name");

const readUrl = process.env.HWLAB_BOOT_READ_URL || mirrorReadUrl(bootRepo);
process.env.HWLAB_BUN_COMMAND ||= process.execPath;
mkdirSync(path.dirname(checkoutDir), { recursive: true });
rmSync(checkoutDir, { recursive: true, force: true });
run("git", ["clone", "--no-checkout", "--single-branch", "--branch", bootRef, readUrl, checkoutDir], "/");
run("git", ["checkout", "--detach", bootCommit], checkoutDir);
linkNodeModules();
ensureRuntimeDependencies();
installHwpodAliases();

const scriptPath = path.join(checkoutDir, bootSh);
if (!existsSync(scriptPath)) fail(`boot script not found: ${bootSh}`);
run("sh", [scriptPath], checkoutDir, { replace: true });

function requiredEnv(name: string): string {
  const value = process.env[name];
  if (!value) fail(`${name} is required`);
  return value;
}

function mirrorReadUrl(repo: string): string {
  if (/github\.com[:/]pikasTech\/HWLAB(?:\.git)?$/u.test(repo)) {
    return "http://git-mirror-http.devops-infra.svc.cluster.local/pikasTech/HWLAB.git";
  }
  fail("no mirror resolver for HWLAB_BOOT_REPO; refusing direct runtime GitHub fallback");
}

function linkNodeModules(): void {
  const target = path.join(checkoutDir, "node_modules");
  if (existsSync(target) || !existsSync(runtimeNodeModules)) return;
  symlinkSync(runtimeNodeModules, target, "dir");
}

function ensureRuntimeDependencies(): void {
  const packageJson = path.join(checkoutDir, "package.json");
  if (!existsSync(packageJson)) return;
  if (canResolvePackage("yaml")) {
    process.stdout.write(`${JSON.stringify({ event: "hwlab-env-reuse-dependencies", status: "cached", package: "yaml" })}\n`);
    return;
  }

  const npmCommand = process.env.HWLAB_NPM_COMMAND || "npm";
  process.stdout.write(`${JSON.stringify({ event: "hwlab-env-reuse-dependencies", status: "installing", package: "yaml", manager: npmCommand })}\n`);
  run(npmCommand, ["install", "--omit=dev", "--include=optional", "--ignore-scripts", "--prefer-offline"], checkoutDir);
  if (!canResolvePackage("yaml")) fail("runtime dependency install completed but package yaml is still unavailable");
  process.stdout.write(`${JSON.stringify({ event: "hwlab-env-reuse-dependencies", status: "installed", package: "yaml", manager: npmCommand })}\n`);
}

function canResolvePackage(packageName: string): boolean {
  const result = spawnSync(process.execPath, ["-e", `require.resolve(${JSON.stringify(packageName)})`], {
    cwd: checkoutDir,
    env: process.env,
    stdio: "ignore"
  });
  return !result.error && !result.signal && result.status === 0;
}

function installHwpodAliases(): void {
  installHwpodAlias("hwpod", "tools/hwpod-cli.ts");
  installHwpodAlias("hwpod-ctl", "tools/hwpod-ctl.ts");
  installHwpodAlias("hwpod-compiler", "tools/hwpod-compiler-cli.ts");
}

function installHwpodAlias(commandName: string, relativeCli: string): void {
  const wrapper = path.join("/usr/local/bin", commandName);
  const runner = path.join(checkoutDir, "scripts", "run-bun.mjs");
  const cli = path.join(checkoutDir, ...relativeCli.split("/"));
  writeFileSync(wrapper, `#!/usr/bin/env sh\nexec node ${shellArg(runner)} ${shellArg(cli)} "$@"\n`, { encoding: "utf8" });
  chmodSync(wrapper, 0o755);
}

function run(command: string, args: string[], cwd: string, options: { replace?: boolean } = {}): void {
  const result = spawnSync(command, args, {
    cwd,
    env: process.env,
    stdio: "inherit"
  });
  if (result.error) fail(`${command} failed to start: ${result.error.message}`);
  if (result.signal) process.kill(process.pid, result.signal);
  const code = result.status ?? 0;
  if (options.replace) process.exit(code);
  if (code !== 0) process.exit(code);
}

function fail(message: string): never {
  process.stderr.write(`${JSON.stringify({ status: "failed", error: "hwlab_env_reuse_launcher_failed", message })}\n`);
  process.exit(1);
}

function shellArg(value: string): string {
  return `'${value.replace(/'/gu, `'"'"'`)}'`;
}
