const path = require("path");
const fs = require("fs");
const { getSirayaDataRoot } = require("./lib/paths");
const { upsertEnvVars } = require("./lib/env-file");
const envPath =
  process.env.DOTENV_CONFIG_PATH ||
  path.join(getSirayaDataRoot(), ".env");
if (fs.existsSync(envPath)) {
  require("dotenv").config({ path: envPath });
} else {
  require("dotenv").config();
}

const { initSettings, loadSettings, syncEnvFromSettings } = require("./lib/settings-store");
const { initializeTemplates } = require("./lib/template-engine-v2");
const { findAvailablePort } = require("./lib/port-utils");
const { startWatchdog } = require("./lib/watchdog");

initSettings();
initializeTemplates({
  BUSINESS_NAME: process.env.BUSINESS_NAME,
  BUSINESS_PHONE: process.env.BUSINESS_PHONE,
  BUSINESS_WEBSITE: process.env.BUSINESS_WEBSITE,
  BUSINESS_TAGLINE: process.env.BUSINESS_TAGLINE,
  BUSINESS_ADDRESS: process.env.BUSINESS_ADDRESS,
});

const express = require("express");
const cors = require("cors");
const { exec } = require("child_process");
const { printerManager } = require("./printer");
const { initQueue } = require("./lib/print-queue");
const { createPrintRouter } = require("./lib/print-routes");
const { createTemplateRouter } = require("./lib/template-routes");
const { createTemplateV2Router } = require("./lib/template-engine-v2/routes");
const { createSettingsRouter } = require("./lib/settings-routes");
const { createBrandingRouter } = require("./lib/branding-routes");
const { getLogsDir, ensureDir } = require("./lib/paths");
const { createLogger } = require("./lib/logger");
const { createPrintRateLimiter } = require("./lib/rate-limit");

const SERVICE_VERSION =
  process.env.SERVICE_VERSION ||
  (() => {
    try {
      return require("./package.json").version;
    } catch {
      return "unknown";
    }
  })();
const startTime = Date.now();
const logger = createLogger();

process.on("uncaughtException", (err) => {
  logger.error(`uncaughtException: ${err?.stack || err}`);
  setTimeout(() => process.exit(1), 500);
});
process.on("unhandledRejection", (reason) => {
  logger.error(`unhandledRejection: ${reason?.stack || reason}`);
});

const settings = loadSettings();
const HOST = process.env.HOST || settings.host || "127.0.0.1";
const envPortRaw = process.env.PORT?.trim();
const envPort = envPortRaw ? parseInt(envPortRaw, 10) : null;
let PORT =
  Number.isFinite(envPort) && envPort > 0
    ? envPort
    : parseInt(String(settings.port || 5000), 10);

/** Keep settings.json aligned with PORT in .env (fixes stuck 5001 after port conflict). */
if (Number.isFinite(envPort) && envPort > 0 && envPort !== settings.port) {
  try {
    const { updateSettings } = require("./lib/settings-store");
    updateSettings({ port: envPort });
  } catch (e) {
    logger.warn(`Could not sync settings port: ${e.message}`);
  }
}

const corsOrigins = (process.env.CORS_ORIGINS || settings.corsOrigins?.join(",") || "http://127.0.0.1:*,http://localhost:*")
  .split(",")
  .map((s) => s.trim())
  .filter(Boolean);

initQueue({
  printFn: async (job) => {
    await printerManager.printReceipt(job.payload || {}, {
      receiptKind: job.receiptKind,
      templateId: job.templateId,
    });
  },
});

startWatchdog({
  logger,
  onStall: () => {
    logger.error("[watchdog] queue pump stalled — exiting for SCM restart");
    setTimeout(() => process.exit(1), 2000);
  },
});

const app = express();
const printRateLimiter = createPrintRateLimiter();

app.use(
  cors({
    origin(origin, callback) {
      if (!origin) return callback(null, true);
      const ok = corsOrigins.some((pattern) => {
        if (pattern.includes("*")) {
          const re = new RegExp(
            `^${pattern.replace(/\./g, "\\.").replace(/\*/g, ".*")}$`,
          );
          return re.test(origin);
        }
        return origin === pattern;
      });
      callback(null, ok);
    },
  }),
);
app.use(express.json({ limit: "2mb" }));
app.use(printRateLimiter);

app.get("/designer", (req, res) => {
  res.sendFile(path.join(__dirname, "public", "designer.html"));
});

app.use(express.static(path.join(__dirname, "public")));

const printerHealth = () => {
  const st = printerManager.getStatus();
  let cupsQueue = null;
  if (process.platform === "linux") {
    try {
      const {
        resolveLinuxCupsQueueName,
        getCupsQueueStatus,
      } = require("./lib/linux-cups");
      const queue = resolveLinuxCupsQueueName(st.printer || {});
      if (queue) cupsQueue = getCupsQueueStatus(queue);
    } catch {
      /* optional */
    }
  }
  return {
    printerConnected: st.connected,
    printer: st.printer,
    printerMode: st.printerMode,
    cupsQueue,
  };
};

app.use(
  createPrintRouter({
    serviceVersion: SERVICE_VERSION,
    startTime,
    getPrinterHealth: printerHealth,
  }),
);

app.use(
  createSettingsRouter({
    serviceVersion: SERVICE_VERSION,
    startTime,
    getPrinterHealth: printerHealth,
  }),
);

app.use(
  createTemplateRouter({
    businessConfig: printerManager.config,
  }),
);

app.use(
  createTemplateV2Router({
    businessConfig: printerManager.config,
  }),
);

app.use(createBrandingRouter());

function renderControlPanelHtml() {
  const isWindows = process.platform === "win32";
  const noPrintersMsg = isWindows
    ? "No thermal printer found. Plug in USB, install the driver in Windows Settings → Printers & scanners, then click Rescan. Or enter the exact Windows printer name below."
    : "No printers found. Connect USB printer or add via CUPS.";
  return `<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>Siraya Printer Setup</title>
  <style>
    :root {
      --bg: #0f1419; --card: #1e293b; --border: #334155;
      --text: #e2e8f0; --muted: #94a3b8; --accent: #38bdf8;
      --ok: #4ade80; --warn: #fbbf24; --err: #f87171;
    }
    * { box-sizing: border-box; }
    body {
      font-family: system-ui, -apple-system, sans-serif;
      margin: 0; background: var(--bg); color: var(--text);
      min-height: 100vh; line-height: 1.45;
    }
    .container {
      max-width: 760px; margin: 0 auto;
      padding: clamp(16px, 4vw, 32px) clamp(12px, 3vw, 20px);
    }
    .header {
      background: linear-gradient(135deg, #0c4a6e, #1e293b);
      padding: clamp(16px, 4vw, 24px);
      border-radius: 12px; margin-bottom: 16px;
      border: 1px solid var(--border);
    }
    .header h1 {
      margin: 0 0 6px;
      font-size: clamp(1.15rem, 4vw, 1.4rem);
      color: var(--accent);
    }
    .header p { margin: 0; color: var(--muted); font-size: 0.9rem; }
    .card {
      background: var(--card); border: 1px solid var(--border);
      border-radius: 12px; padding: clamp(14px, 3vw, 18px);
      margin: 12px 0;
    }
    .card.ok { border-left: 4px solid var(--ok); }
    .card.warn { border-left: 4px solid var(--warn); }
    .card.err { border-left: 4px solid var(--err); }
    .card h3 { margin: 0 0 12px; font-size: 1rem; }
    .links {
      display: flex; flex-wrap: wrap; gap: 8px 16px;
      margin: 12px 0 16px;
    }
    .links a { color: var(--accent); text-decoration: none; font-size: 0.95rem; }
    .links a:hover { text-decoration: underline; }
    input[type="text"] {
      width: 100%; padding: 10px 12px; border-radius: 8px;
      border: 1px solid var(--border); background: #0f172a; color: var(--text);
      font-size: 0.95rem; margin: 6px 0 10px;
    }
    label {
      display: block; font-size: 0.85rem; color: var(--muted);
      margin-bottom: 8px;
    }
    select {
      width: 100%; padding: 12px; border-radius: 8px;
      border: 1px solid var(--border); background: #1a2332; color: var(--text);
      margin-bottom: 10px; font-size: 1rem;
    }
    .btn-row {
      display: flex; flex-wrap: wrap; gap: 8px;
      margin-top: 14px;
    }
    .btn {
      padding: 11px 16px; border: 1px solid var(--border); border-radius: 8px;
      cursor: pointer; font-weight: 600; font-size: 0.95rem;
      background: #1a2332; color: var(--text);
      flex: 1 1 140px; min-height: 44px;
    }
    .btn:disabled { opacity: 0.55; cursor: not-allowed; }
    .btn-primary { background: var(--accent); color: #0f1419; border-color: transparent; }
    .btn-success { background: rgba(74,222,128,0.15); color: var(--ok); border-color: rgba(74,222,128,0.35); }
    .btn-warn { background: rgba(251,191,36,0.12); color: var(--warn); border-color: rgba(251,191,36,0.35); }
    .empty { color: var(--muted); text-align: center; padding: 24px 12px; }
    .hidden { display: none !important; }
    #printerCount { font-size: 0.85rem; color: var(--muted); margin-top: 4px; }
    #actionStatus {
      margin-top: 12px; padding: 10px 12px; border-radius: 8px;
      font-size: 0.9rem; border: 1px solid var(--border);
      background: rgba(15,20,25,0.45);
    }
    #actionStatus.ok { color: var(--ok); border-color: rgba(74,222,128,0.35); }
    #actionStatus.err { color: var(--err); border-color: rgba(248,113,113,0.35); }
    #actionStatus.warn { color: var(--warn); border-color: rgba(251,191,36,0.35); }
    .status-grid {
      display: grid; gap: 8px;
      grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
      font-size: 0.9rem;
    }
    .status-grid strong { color: var(--muted); font-weight: 600; display: block; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.03em; }
    .hint {
      margin-top: 10px; padding: 10px 12px; border-radius: 8px;
      background: rgba(251,191,36,0.08); border: 1px solid rgba(251,191,36,0.25);
      color: var(--warn); font-size: 0.88rem;
    }
    @media (max-width: 520px) {
      .btn { flex: 1 1 100%; }
      .status-grid { grid-template-columns: 1fr; }
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="header">
      <h1>Siraya Printer Service v${SERVICE_VERSION}</h1>
      <p>Quick setup for this register. Use Receipt designer for layout and branding.</p>
    </div>
    <div id="status" class="card">Loading…</div>
    <div class="links">
      <a href="/designer">Receipt designer</a>
      <a href="/settings">Settings JSON</a>
    </div>
    <div class="card">
      <h3>Printer</h3>
      <label for="spoolerSelect">Select thermal printer</label>
      <select id="spoolerSelect"></select>
      <div id="printerCount"></div>
      <div id="noPrinters" class="empty hidden">${noPrintersMsg}</div>
      <div id="manualPrinterWin" class="${isWindows ? "" : "hidden"}">
        <label for="manualSpoolerName">Windows printer queue name</label>
        <input type="text" id="manualSpoolerName" placeholder="Exact name from Settings → Printers (e.g. BC-95AC)" />
        <button class="btn btn-primary" id="btnManualSave" onclick="saveManualSpooler()">Use this printer</button>
      </div>
      <div id="cupsHint" class="hint hidden">CUPS queue looks stuck. Tap <strong>Clear queue</strong>, then test print again.</div>
      <div class="btn-row">
        <button class="btn btn-primary" id="btnSave" onclick="saveSpooler()">Save default</button>
        <button class="btn btn-success" id="btnTest" onclick="testPrint()">Test print</button>
        <button class="btn" id="btnRescan" onclick="rescan()">Rescan</button>
        <button class="btn btn-warn" id="btnClearQueue" onclick="clearQueue()">Clear queue</button>
      </div>
      <div id="actionStatus" class="hidden"></div>
    </div>
  </div>
  <script src="/print-job-poll.js"></script>
  <script>
    let printers = [];

    function setAction(msg, kind) {
      const el = document.getElementById('actionStatus');
      if (!msg) {
        el.className = 'hidden';
        el.textContent = '';
        return;
      }
      el.className = kind || '';
      el.textContent = msg;
    }

    function setBusy(id, busy, label) {
      const btn = document.getElementById(id);
      if (!btn) return;
      btn.disabled = busy;
      if (label) btn.textContent = label;
      else if (id === 'btnTest') btn.textContent = 'Test print';
      else if (id === 'btnSave') btn.textContent = 'Save default';
      else if (id === 'btnRescan') btn.textContent = 'Rescan';
      else if (id === 'btnClearQueue') btn.textContent = 'Clear queue';
    }

    function printerLabel(p, i) {
      let label = p.name + ' (' + p.type + ')';
      if (p.type === 'CUPS') label += ' — recommended';
      return label;
    }

    async function loadStatus() {
      const res = await fetch('/status');
      const data = await res.json();
      const connected = data.printerConnected;
      const el = document.getElementById('status');
      const cups = data.cupsQueue;
      const stuck = cups && cups.stuck;
      el.className = 'card ' + (stuck ? 'warn' : connected ? 'ok' : 'warn');
      el.innerHTML =
        '<div class="status-grid">' +
        '<div><strong>Printer</strong>' + (data.printer?.name || 'Not set') + '</div>' +
        '<div><strong>Type</strong>' + (data.printer?.type || '—') + '</div>' +
        '<div><strong>Service queue</strong>' + (data.queueDepth ?? 0) + ' job(s)</div>' +
        '<div><strong>CUPS</strong>' + (cups ? cups.queue + ' · ' + cups.pendingJobs + ' pending' : '—') + '</div>' +
        '</div>';
      document.getElementById('cupsHint').classList.toggle('hidden', !stuck);
      await loadPrinters(data.printer?.name);
    }

    async function loadPrinters(selectedName) {
      const pr = await fetch('/printers');
      printers = await pr.json();
      const sel = document.getElementById('spoolerSelect');
      const empty = document.getElementById('noPrinters');
      sel.innerHTML = '';
      document.getElementById('printerCount').textContent = printers.length + ' printer(s) detected';
      if (!printers.length) {
        empty.classList.remove('hidden');
        sel.classList.add('hidden');
        return;
      }
      empty.classList.add('hidden');
      sel.classList.remove('hidden');
      const rank = (p) => (p.type === 'CUPS' ? 0 : p.type === 'Spooler' ? 1 : p.type === 'USB' ? 3 : 2);
      const indexed = printers.map((p, i) => ({ p, i }));
      indexed.sort((a, b) => rank(a.p) - rank(b.p) || a.i - b.i);
      let selectedValue = String(indexed[0].i);
      indexed.forEach(({ p, i }) => {
        const opt = document.createElement('option');
        opt.value = i;
        opt.textContent = printerLabel(p, i);
        sel.appendChild(opt);
        if (selectedName && p.name === selectedName) selectedValue = String(i);
        else if (!selectedName && p.type === 'CUPS') selectedValue = String(i);
      });
      sel.value = selectedValue;
    }

    async function saveManualSpooler() {
      const name = document.getElementById('manualSpoolerName').value.trim();
      if (!name) {
        setAction('Enter the printer name exactly as shown in Windows Settings.', 'err');
        return;
      }
      setBusy('btnManualSave', true, 'Saving…');
      setAction('Saving printer…', 'warn');
      try {
        const res = await fetch('/select-printer', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ spoolerName: name })
        });
        const j = await res.json();
        if (!j.success) throw new Error('Could not save printer');
        setAction('Printer saved: ' + name, 'ok');
        await loadStatus();
      } catch (e) {
        setAction(e.message || 'Save failed', 'err');
      } finally {
        setBusy('btnManualSave', false);
      }
    }

    async function saveSpooler() {
      setBusy('btnSave', true, 'Saving…');
      setAction('Saving printer…', 'warn');
      try {
        await fetch('/select-printer', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ index: parseInt(document.getElementById('spoolerSelect').value, 10) })
        });
        setAction('Default printer saved.', 'ok');
        await loadStatus();
      } catch (e) {
        setAction(e.message || 'Save failed', 'err');
      } finally {
        setBusy('btnSave', false);
      }
    }

    async function rescan() {
      setBusy('btnRescan', true, 'Scanning…');
      setAction('Scanning for printers…', 'warn');
      try {
        await fetch('/rescan', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: '{}' });
        setAction('Scan complete.', 'ok');
        await loadStatus();
      } catch (e) {
        setAction(e.message || 'Rescan failed', 'err');
      } finally {
        setBusy('btnRescan', false);
      }
    }

    async function clearQueue() {
      setBusy('btnClearQueue', true, 'Clearing…');
      setAction('Clearing CUPS queue…', 'warn');
      try {
        const res = await fetch('/printers/clear-queue', { method: 'POST' });
        const j = await res.json();
        if (!j.ok) throw new Error(j.error || 'Could not clear queue');
        setAction('Cleared queue: ' + (j.queue || 'done') + '. Try test print.', 'ok');
        await loadStatus();
      } catch (e) {
        setAction(e.message || 'Clear queue failed', 'err');
      } finally {
        setBusy('btnClearQueue', false);
      }
    }

    async function testPrint() {
      setBusy('btnTest', true, 'Printing…');
      setAction('Sending test print…', 'warn');
      try {
        const res = await fetch('/print', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            orderNumber: 'TEST-' + Date.now(),
            orderType: 'dine-in',
            items: [{ name: 'Chicken Broast', quantity: 1, price: 450, total: 450 }],
            subtotal: 450,
            tax: 45,
            total: 495,
            paymentMethod: 'Cash',
          })
        });
        const j = await res.json();
        if (!res.ok || j.success === false) {
          setAction(j.error || 'Print request failed', 'err');
          return;
        }
        const id = j.printJobId;
        if (!id || typeof pollPrintJob !== 'function') {
          setAction('Queued: ' + (j.state || 'ok'), 'ok');
          return;
        }
        setAction('Waiting for printer…', 'warn');
        const out = await pollPrintJob(id, {
          onUpdate(job) { setAction('Printing… ' + job.state, 'warn'); }
        });
        await loadStatus();
        const st = await fetch('/status').then((r) => r.json());
        if (out.ok && st.cupsQueue?.stuck) {
          setAction('Sent to printer but CUPS queue is stuck — tap Clear queue, then test again.', 'err');
          return;
        }
        setAction(
          out.ok ? 'Receipt printed successfully.' : ('Print failed: ' + (out.job.lastError || 'check printer power and queue')),
          out.ok ? 'ok' : 'err'
        );
      } catch (e) {
        setAction(e.message || 'Print failed', 'err');
      } finally {
        setBusy('btnTest', false);
      }
    }

    loadStatus().catch((e) => setAction(e.message, 'err'));
  </script>
</body>
</html>`;
}

app.get("/", (req, res) => {
  res.send(renderControlPanelHtml());
});

app.get("/printers", (req, res) => {
  res.json(printerManager.detector.detectedPrinters);
});

app.post("/printers/clear-queue", (req, res) => {
  if (process.platform !== "linux") {
    return res.json({ ok: false, error: "LINUX_ONLY" });
  }
  try {
    const {
      resolveLinuxCupsQueueName,
      clearCupsQueue,
    } = require("./lib/linux-cups");
    const queue = resolveLinuxCupsQueueName(printerManager.currentPrinter || {});
    if (!queue) return res.json({ ok: false, error: "NO_CUPS_QUEUE" });
    const out = clearCupsQueue(queue);
    res.json({ ...out, queue });
  } catch (e) {
    res.status(500).json({ ok: false, error: String(e.message || e) });
  }
});

app.post("/select-printer", (req, res) => {
  const { index, spoolerName } = req.body || {};
  if (typeof spoolerName === "string" && spoolerName.trim()) {
    const name = spoolerName.trim();
    process.env.PRINTER_SPOOLER_NAME = name;
    printerManager.currentPrinter = {
      type: "Spooler",
      name,
      devicePath: name,
      spoolerName: name,
      autoDetected: true,
      platform: process.platform,
      driver: "Windows-Spooler-RAW",
    };
    printerManager.detector.selectedPrinter = printerManager.currentPrinter;
    printerManager.detector.saveConfig();
    printerManager.setupPrintMethods();
    try {
      upsertEnvVars({
        PRINTER_SPOOLER_NAME: name,
        PRINTER_MODE: "spooler",
      });
    } catch (e) {
      console.warn("Could not persist printer to .env:", e.message);
    }
    return res.json({ success: true });
  }
  const success = printerManager.selectPrinter(index);
  if (success && printerManager.currentPrinter?.type === "Spooler") {
    const name = printerManager.currentPrinter.name;
    process.env.PRINTER_SPOOLER_NAME = name;
    try {
      upsertEnvVars({
        PRINTER_SPOOLER_NAME: name,
        PRINTER_MODE: "spooler",
      });
    } catch (e) {
      console.warn("Could not persist printer to .env:", e.message);
    }
  }
  res.json({ success });
});

app.post("/rescan", async (req, res) => {
  const printers = await printerManager.rescanPrinters();
  res.json({ success: true, printers });
});

app.get("/logs", (req, res) => {
  const logDir = getLogsDir();
  let logContent = "";
  try {
    ensureDir(logDir);
    for (const file of fs.readdirSync(logDir)) {
      if (file.endsWith(".log")) {
        logContent += `=== ${file} ===\n`;
        logContent += fs.readFileSync(path.join(logDir, file), "utf8");
        logContent += "\n\n";
      }
    }
  } catch {
    logContent = "No logs available";
  }
  res.set("Content-Type", "text/plain");
  res.send(logContent);
});

app.get("/support/export", (req, res) => {
  const { getPrintDataDir } = require("./lib/print-queue");
  const { getPublicSettings } = require("./lib/settings-store");
  const pub = getPublicSettings();
  const lines = [
    `version=${SERVICE_VERSION}`,
    `printer=${printerManager.currentPrinter?.name || "none"}`,
    `mode=${printerManager.printerMode}`,
    `queueDir=${getPrintDataDir()}`,
    `logsDir=${getLogsDir()}`,
    `serviceUrl=${pub.serviceUrl}`,
    `uptimeSec=${Math.floor((Date.now() - startTime) / 1000)}`,
  ];
  res.set("Content-Type", "text/plain");
  res.send(lines.join("\n"));
});

app.post("/restart", (req, res) => {
  if (process.platform === "win32") {
    exec(
      "net stop SirayaPrinterService & net start SirayaPrinterService",
      { windowsHide: true },
      () => {},
    );
    return res.json({ success: true, message: "Windows service restart initiated" });
  }
  if (process.platform === "linux") {
    exec("systemctl restart siraya-printer.service", () => {});
    return res.json({ success: true, message: "Linux service restart initiated" });
  }
  res.json({ success: true, message: "Restart not automated on this platform" });
});

app.use((req, res) => {
  if (res.headersSent) return;
  res.status(404).json({ error: "NOT_FOUND" });
});

async function startServer() {
  syncEnvFromSettings(loadSettings());
  const host = process.env.HOST || HOST;
  const fixedPort = Number.isFinite(envPort) && envPort > 0 ? envPort : null;
  let port = fixedPort || parseInt(String(PORT), 10);
  const lockPort5000 =
    port === 5000 ||
    fixedPort === 5000 ||
    process.env.SIRAYA_INNO_INSTALL === "1";

  try {
    const net = require("net");
    const available = await new Promise((resolve) => {
      const server = net.createServer();
      server.once("error", () => resolve(false));
      server.once("listening", () => {
        server.close(() => resolve(true));
      });
      server.listen(port, host);
    });
    if (!available) {
      if (lockPort5000) {
        logger.error(
          `Port ${port} is in use. Siraya printer agent requires port 5000 — stop the other process and retry.`,
        );
        process.exit(1);
      }
      const startPort = fixedPort || port;
      port = await findAvailablePort(host, startPort);
      if (fixedPort && port !== fixedPort) {
        logger.warn(
          `Port ${fixedPort} unavailable (common on Windows) — listening on ${port} instead`,
        );
      } else {
        logger.warn(`Port ${startPort} busy — using ${port}`);
      }
      const { updateSettings } = require("./lib/settings-store");
      updateSettings({ port });
    } else if (lockPort5000 && port === 5000) {
      const { updateSettings } = require("./lib/settings-store");
      const current = loadSettings();
      if (current.port !== 5000) {
        updateSettings({ port: 5000 });
      }
    }
  } catch (e) {
    logger.error("Port resolution failed:", e.message);
    if (lockPort5000) {
      process.exit(1);
    }
  }

  app.listen(port, host, () => {
    logger.info(
      `Siraya printer service listening on http://${host}:${port} v${SERVICE_VERSION}`,
    );
    try {
      const readyFile = path.join(getSirayaDataRoot(), "agent-ready.json");
      fs.writeFileSync(
        readyFile,
        JSON.stringify(
          {
            port,
            pid: process.pid,
            startedAt: new Date().toISOString(),
            version: SERVICE_VERSION,
          },
          null,
          2,
        ),
        "utf8",
      );
    } catch (e) {
      logger.warn(`Could not write agent-ready.json: ${e.message}`);
    }
    setTimeout(() => {
      printerManager.detector.detectAllPrinters().then(() => {
        logger.info(
          `Detected ${printerManager.detector.detectedPrinters.length} printer(s)`,
        );
      });
    }, 2000);
  });
}

void startServer();
