/**
 * Shared health probe for Windows install, update, and service registration.
 */
const fs = require("fs");
const http = require("http");
const path = require("path");

const DEFAULT_DATA_DIR = path.join(
  process.env.ProgramData || process.env.SIRAYA_DATA_DIR || "C:\\ProgramData",
  "Siraya",
  "Printer",
);

const AGENT_PORT = 5000;

function readReadyPort(dataDir) {
  try {
    const raw = fs.readFileSync(path.join(dataDir, "agent-ready.json"), "utf8");
    const parsed = JSON.parse(raw);
    const port = parseInt(String(parsed.port || ""), 10);
    return port === AGENT_PORT ? AGENT_PORT : null;
  } catch {
    return null;
  }
}

function readEnvPort(dataDir) {
  try {
    const envFile = path.join(dataDir, ".env");
    if (!fs.existsSync(envFile)) return null;
    for (const line of fs.readFileSync(envFile, "utf8").split(/\r?\n/)) {
      const m = line.match(/^\s*PORT=(\d+)\s*$/);
      if (m) {
        const port = parseInt(m[1], 10);
        return port === AGENT_PORT ? AGENT_PORT : null;
      }
    }
  } catch {
    /* ignore */
  }
  return null;
}

function readSettingsPort(dataDir) {
  try {
    const settingsFile = path.join(dataDir, "settings.json");
    if (!fs.existsSync(settingsFile)) return null;
    const parsed = JSON.parse(fs.readFileSync(settingsFile, "utf8"));
    const port = parseInt(String(parsed.port || ""), 10);
    return port === AGENT_PORT ? AGENT_PORT : null;
  } catch {
    return null;
  }
}

function getHealthCheckPorts(dataDir = DEFAULT_DATA_DIR) {
  const seen = new Set();
  const ports = [];
  const add = (p) => {
    const n = parseInt(String(p), 10);
    if (n !== AGENT_PORT || seen.has(n)) return;
    seen.add(n);
    ports.push(n);
  };

  add(readReadyPort(dataDir));
  add(readSettingsPort(dataDir));
  add(readEnvPort(dataDir));
  add(AGENT_PORT);
  return ports;
}

function probeHealthOnce(host, port, timeoutMs = 3000) {
  return new Promise((resolve) => {
    const req = http.get(
      `http://${host}:${port}/health`,
      { timeout: timeoutMs },
      (res) => {
        res.resume();
        resolve(res.statusCode === 200 ? port : null);
      },
    );
    req.on("error", () => resolve(null));
    req.on("timeout", () => {
      req.destroy();
      resolve(null);
    });
  });
}

function sleep(ms) {
  return new Promise((r) => setTimeout(r, ms));
}

async function waitForHealth(opts = {}) {
  const dataDir = opts.dataDir || DEFAULT_DATA_DIR;
  const host = opts.host || "127.0.0.1";
  const timeoutSec = opts.timeoutSec || 90;
  const intervalMs = opts.intervalMs || 2000;
  const deadline = Date.now() + timeoutSec * 1000;
  const ports = opts.port != null ? [opts.port] : getHealthCheckPorts(dataDir);

  while (Date.now() < deadline) {
    for (const port of ports) {
      const ok = await probeHealthOnce(host, port, opts.timeoutMs || 3000);
      if (ok) return ok;
    }
    await sleep(intervalMs);
  }
  return null;
}

module.exports = {
  DEFAULT_DATA_DIR,
  AGENT_PORT,
  getHealthCheckPorts,
  probeHealthOnce,
  waitForHealth,
  readReadyPort,
};
