#!/usr/bin/env node
/* eslint-disable */
/**
 * preinstall — runs BEFORE npm replaces files on disk. Gracefully stops
 * the running Omnius daemon so the install window doesn't strand it with
 * a half-replaced binary that crashes on next relaunch.
 *
 * The postinstall hook restarts the daemon after install completes with
 * the new code in place.
 *
 * Opt-out: OMNIUS_SKIP_DAEMON_INSTALL=1 (matches postinstall semantics).
 */

"use strict";

if (process.env.OMNIUS_SKIP_DAEMON_INSTALL === "1") {
  process.exit(0);
}

var os = require("os");
var path = require("path");
var fs = require("fs");
var cp = require("child_process");

var IS_WIN = os.platform() === "win32";
var IS_LINUX = os.platform() === "linux";
var IS_MAC = os.platform() === "darwin";
var HOME = os.homedir();
var SERVICE_LABEL = "omnius-daemon";
var LAUNCHD_LABEL = "ai.omnius.daemon";
var WIN_TASK_NAME = "OmniusDaemon";
var BANNER = [
  "",
  "░░      ░░░  ░░░░  ░░   ░░░  ░░        ░░  ░░░░  ░░░      ░░",
  "▒  ▒▒▒▒  ▒▒   ▒▒   ▒▒    ▒▒  ▒▒▒▒▒  ▒▒▒▒▒  ▒▒▒▒  ▒▒  ▒▒▒▒▒▒▒",
  "▓  ▓▓▓▓  ▓▓        ▓▓  ▓  ▓  ▓▓▓▓▓  ▓▓▓▓▓  ▓▓▓▓  ▓▓▓      ▓▓",
  "█  ████  ██  █  █  ██  ██    █████  █████  ████  ████████  █",
  "██      ███  ████  ██  ███   ██        ███      ████      ██",
  ""
].join("\n");

function quietInstall() {
  var level = String(process.env.npm_config_loglevel || "").toLowerCase();
  return process.env.OMNIUS_QUIET_INSTALL === "1" || level === "silent";
}

function runQuiet(cmd) {
  try { cp.execSync(cmd, { stdio: "pipe", timeout: 8000 }); return true; } catch (e) { return false; }
}

function log(msg) { process.stdout.write("  [preinstall] " + msg + "\n"); }
function progress(step, total, msg) {
  if (quietInstall()) return;
  var width = 18;
  var filled = Math.max(0, Math.min(width, Math.round((step / total) * width)));
  process.stdout.write("  [" + "#".repeat(filled) + ".".repeat(width - filled) + "] " + step + "/" + total + " " + msg + "\n");
}

if (!quietInstall()) process.stdout.write(BANNER + "\n");

function stopServiceManager() {
  // Stop via the registered service manager if one exists. This is
  // graceful (sends SIGTERM, waits for exit) AND prevents the manager
  // from auto-restarting the daemon mid-install.
  try {
    if (IS_LINUX) {
      // Pause + stop. Don't disable — we want it to come back after
      // postinstall re-enables/restarts it.
      runQuiet("systemctl --user stop " + SERVICE_LABEL + ".service");
    } else if (IS_MAC) {
      var plist = path.join(HOME, "Library", "LaunchAgents", LAUNCHD_LABEL + ".plist");
      if (fs.existsSync(plist)) runQuiet("launchctl unload " + plist);
    } else if (IS_WIN) {
      runQuiet('schtasks /End /TN "' + WIN_TASK_NAME + '"');
    }
  } catch (e) { /* best-effort */ }
}

function killPidFile(pidFile) {
  try {
    if (!fs.existsSync(pidFile)) return false;
    var n = parseInt(fs.readFileSync(pidFile, "utf8").trim(), 10);
    if (!n || n <= 0) return false;
    try { process.kill(n, "SIGTERM"); log("SIGTERM " + pidFile + " (pid " + n + ")"); return true; }
    catch (e) { /* dead */ }
  } catch (e) {}
  return false;
}

progress(1, 3, "Preparing Omnius service handoff");
stopServiceManager();
killPidFile(path.join(HOME, ".omnius", "daemon.pid"));
progress(2, 3, "Stopped old daemon handles");

// Final: lsof-based sweep for any process still holding 11435.
try {
  var port = parseInt(process.env.OMNIUS_PORT || "11435", 10);
  var out = "";
  try {
    out = cp.execSync("lsof -ti :" + port + " 2>/dev/null || true", {
      encoding: "utf8", timeout: 3000,
    }).trim();
  } catch (e) {}
  if (out) {
    out.split(/\s+/).forEach(function (s) {
      var n = parseInt(s, 10);
      if (Number.isFinite(n) && n > 0 && n !== process.pid) {
        try { process.kill(n, "SIGTERM"); log("SIGTERM port-holder pid " + n); } catch (e) {}
      }
    });
  }
} catch (e) {}

// 1.5s grace so SIGTERM handlers can flush state.
progress(3, 3, "Install handoff ready");
setTimeout(function () { process.exit(0); }, 1500);
