import { closeSync, mkdirSync, openSync, readFileSync } from "node:fs";
import { resolve } from "node:path";

const webRoot = process.cwd();
const repoRoot = resolve(webRoot, "../..");
const stateDir = resolve(webRoot, ".state/tasktree-native");
const databaseEnvFile = process.env.TASKTREE_NATIVE_DATABASE_ENV_FILE;
const temporalAddress = process.env.TASKTREE_TEMPORAL_ADDRESS;

if (!databaseEnvFile) throw new Error("TASKTREE_NATIVE_DATABASE_ENV_FILE is required");
if (!temporalAddress) throw new Error("TASKTREE_TEMPORAL_ADDRESS is required");

function readEnvValue(path: string, key: string): string {
  const line = readFileSync(path, "utf8")
    .split(/\r?\n/u)
    .find((candidate) => candidate.startsWith(`${key}=`));
  if (!line) throw new Error(`${key} is missing from the configured env source`);
  const raw = line.slice(key.length + 1).trim();
  if ((raw.startsWith('"') && raw.endsWith('"')) || (raw.startsWith("'") && raw.endsWith("'"))) return raw.slice(1, -1);
  return raw;
}

mkdirSync(stateDir, { recursive: true });
const logFd = openSync(resolve(stateDir, "services.log"), "a");
const databaseUrl = readEnvValue(databaseEnvFile, "DATABASE_URL");
const commonEnv = {
  ...process.env,
  TASKTREE_DATABASE_URL: databaseUrl,
  TASKTREE_TEMPORAL_ADDRESS: temporalAddress,
  TASKTREE_TEMPORAL_NAMESPACE: process.env.TASKTREE_TEMPORAL_NAMESPACE ?? "unidesk",
  TASKTREE_TEMPORAL_TASK_QUEUE: process.env.TASKTREE_TEMPORAL_TASK_QUEUE ?? "hwlab-v03-tasktree"
};
const backupWorktree = process.env.TASKTREE_BACKUP_WORKTREE;

const children = [
  Bun.spawn([process.execPath, "cmd/hwlab-tasktree-worker/main.ts"], { cwd: repoRoot, env: commonEnv, stdin: "ignore", stdout: logFd, stderr: logFd }),
  Bun.spawn([process.execPath, "cmd/hwlab-tasktree-api/main.ts"], {
    cwd: repoRoot,
    env: {
      ...commonEnv,
      ...(backupWorktree ? { TASKTREE_BACKUP_WORKTREE: `${backupWorktree}-api` } : {}),
      TASKTREE_API_HOST: "127.0.0.1",
      TASKTREE_API_PORT: "6673"
    },
    stdin: "ignore",
    stdout: logFd,
    stderr: logFd
  }),
  Bun.spawn([process.execPath, "x", "vite", "--config", "scripts/tasktree-native-vite.config.ts"], { cwd: webRoot, env: { ...process.env, HWLAB_TASKTREE_NATIVE_API_URL: "http://127.0.0.1:6673" }, stdin: "ignore", stdout: logFd, stderr: logFd })
];

process.stdout.write(`${JSON.stringify({ serviceId: "hwlab-tasktree-native", status: "started", pids: children.map((child) => child.pid), valuesPrinted: false })}\n`);

let stopping = false;
async function stop(): Promise<void> {
  if (stopping) return;
  stopping = true;
  for (const child of children) child.kill("SIGTERM");
  await Promise.allSettled(children.map((child) => child.exited));
  closeSync(logFd);
  process.exit(0);
}

process.once("SIGINT", stop);
process.once("SIGTERM", stop);
const exited = await Promise.race(children.map(async (child, index) => ({ index, code: await child.exited })));
if (!stopping) {
  process.stderr.write(`${JSON.stringify({ serviceId: "hwlab-tasktree-native", status: "child-exited", ...exited })}\n`);
  await stop();
}
