const path = require("path");
const fs = require("fs");
const os = require("os");
const { execFile } = require("child_process");
const { app } = require("electron");

const SERVICE_NAME = "SirayaPrinterService";
const LINUX_SERVICE_NAME = "siraya-printer";

function getServiceBundleRoot() {
  if (app.isPackaged) {
    const bundled = path.join(process.resourcesPath, "service-bundle");
    if (fs.existsSync(bundled)) return bundled;
  }
  return path.resolve(__dirname, "..", "..", "dist", "release");
}

function getIconPath() {
  const p = path.join(__dirname, "..", "renderer", "icon.png");
  return fs.existsSync(p) ? p : undefined;
}

function execPs(script, opts = {}) {
  return new Promise((resolve, reject) => {
    execFile(
      "powershell.exe",
      ["-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", script],
      { windowsHide: true, ...opts },
      (err, stdout, stderr) => {
        if (err) reject(new Error(stderr || err.message));
        else resolve(stdout);
      },
    );
  });
}

function runElevatedScript(scriptPath, args = []) {
  return new Promise((resolve, reject) => {
    const argList = args.map((a) => `'${String(a).replace(/'/g, "''")}'`).join(", ");
    const ps = `
$p = Start-Process powershell -Verb RunAs -Wait -PassThru -ArgumentList '-NoProfile','-ExecutionPolicy','Bypass','-File','${scriptPath.replace(/'/g, "''")}'${argList ? `,${argList}` : ""}
exit $p.ExitCode
`;
    execPs(ps).then(resolve).catch(reject);
  });
}

function runElevatedBash(scriptPath, args = []) {
  return new Promise((resolve, reject) => {
    execFile(
      "pkexec",
      ["bash", scriptPath, ...args],
      { env: process.env },
      (err, stdout, stderr) => {
        if (err) {
          reject(new Error(stderr?.toString() || err.message || String(err)));
        } else {
          resolve(stdout?.toString() || "");
        }
      },
    );
  });
}

async function isLinuxServiceActive() {
  if (process.platform !== "linux") return false;
  return new Promise((resolve) => {
    execFile(
      "systemctl",
      ["is-active", "--quiet", LINUX_SERVICE_NAME],
      (err) => resolve(!err),
    );
  });
}

async function waitForHealth(url, timeoutSec = 90) {
  const deadline = Date.now() + timeoutSec * 1000;
  while (Date.now() < deadline) {
    try {
      const res = await fetch(url);
      if (res.ok) return true;
    } catch {
      /* retry */
    }
    await new Promise((r) => setTimeout(r, 2000));
  }
  return false;
}

async function runWindowsFirstRunSetup({ bundleRoot, onProgress }) {
  const log = (msg) => {
    if (onProgress) onProgress(msg);
  };

  log("Checking Windows version…");
  const osCheck = await execPs(
    "[int](Get-CimInstance Win32_OperatingSystem).BuildNumber -ge 10240",
  );
  if (!String(osCheck).trim().startsWith("True")) {
    return { ok: false, error: "Windows 10 or newer required" };
  }

  const root = bundleRoot || getServiceBundleRoot();
  const installScript = path.join(root, "install-from-folder.ps1");

  if (!fs.existsSync(installScript)) {
    return {
      ok: false,
      error: `Install script not found at ${installScript}. Run npm run build:release first.`,
    };
  }

  log("Installing print service (UAC prompt may appear)…");
  await runElevatedScript(installScript, [root]);

  log("Waiting for print agent…");
  const healthy = await waitForHealth("http://127.0.0.1:5000/health");
  if (!healthy) {
    return { ok: false, error: "Service did not respond on port 5000" };
  }

  log("Setup complete");
  return { ok: true, serviceUrl: "http://127.0.0.1:5000" };
}

async function runLinuxFirstRunSetup({ bundleRoot, onProgress }) {
  const log = (msg) => {
    if (onProgress) onProgress(msg);
  };

  if (await isLinuxServiceActive()) {
    log("Print service already running");
    return { ok: true, serviceUrl: "http://127.0.0.1:5000" };
  }

  const root = bundleRoot || getServiceBundleRoot();
  let installScript = path.join(root, "install-from-folder.sh");
  if (!fs.existsSync(installScript)) {
    installScript = path.join(
      path.dirname(process.execPath),
      "install-from-folder.sh",
    );
  }
  if (!fs.existsSync(installScript)) {
    return {
      ok: false,
      error: `Install script not found. Run ./Install.sh from the agent-linux folder first.`,
    };
  }

  log("Installing print service (admin prompt may appear)…");
  await runElevatedBash(installScript, [root]);

  log("Waiting for print agent…");
  const healthy = await waitForHealth("http://127.0.0.1:5000/health");
  if (!healthy) {
    return {
      ok: false,
      error: "Service did not respond on port 5000 — try: sudo ./Install.sh",
    };
  }

  log("Setup complete");
  return { ok: true, serviceUrl: "http://127.0.0.1:5000" };
}

async function runFirstRunSetup({ bundleRoot, onProgress }) {
  try {
    if (process.platform === "win32") {
      return runWindowsFirstRunSetup({ bundleRoot, onProgress });
    }
    if (process.platform === "linux") {
      return runLinuxFirstRunSetup({ bundleRoot, onProgress });
    }
    return { ok: false, error: `Unsupported platform: ${process.platform}` };
  } catch (e) {
    return { ok: false, error: e.message || String(e) };
  }
}

module.exports = {
  runFirstRunSetup,
  getServiceBundleRoot,
  getIconPath,
  SERVICE_NAME,
  LINUX_SERVICE_NAME,
};
