#!/usr/bin/env node

const { spawn, exec, execSync } = require("child_process");
const path = require("path");
const fs = require("fs");
const os = require("os");

const pkg = require("./package.json");

// ─── Configuration ────────────────────────────────────────────────────
const DEFAULT_PORT = 20123;
const DEFAULT_HOST = "0.0.0.0";

let port = DEFAULT_PORT;
let host = DEFAULT_HOST;
let noBrowser = false;
let showLog = false;
let trayMode = false;

// Parse arguments
const args = process.argv.slice(2);
for (let i = 0; i < args.length; i++) {
  if (args[i] === "--port" || args[i] === "-p") {
    port = parseInt(args[i + 1], 10) || DEFAULT_PORT;
    i++;
  } else if (args[i] === "--host" || args[i] === "-H") {
    host = args[i + 1] || DEFAULT_HOST;
    i++;
  } else if (args[i] === "--no-browser" || args[i] === "-n") {
    noBrowser = true;
  } else if (args[i] === "--log" || args[i] === "-l") {
    showLog = true;
  } else if (args[i] === "--tray" || args[i] === "-t") {
    trayMode = true;
  } else if (args[i] === "--help" || args[i] === "-h") {
    console.log(`
Usage: ${pkg.name} [options]

Options:
  -p, --port <port>   Port to run the server (default: ${DEFAULT_PORT})
  -H, --host <host>   Host to bind (default: ${DEFAULT_HOST})
  -n, --no-browser    Don't open browser automatically
  -l, --log           Show server logs (default: hidden)
  -t, --tray          Run in background (no interactive menu)
  -h, --help          Show this help message
  -v, --version       Show version
`);
    process.exit(0);
  } else if (args[i] === "--version" || args[i] === "-v") {
    console.log(pkg.version);
    process.exit(0);
  }
}

// ─── Standalone server path ───────────────────────────────────────────
const standaloneDir = path.join(__dirname, "app");
const serverPath = path.join(standaloneDir, "server.js");

if (!fs.existsSync(serverPath)) {
  console.error("Error: Standalone build not found at cli/app/server.js");
  console.error("Run 'npm run build:cli' first.");
  process.exit(1);
}

// ─── Helpers ──────────────────────────────────────────────────────────

function openBrowser(url) {
  const cmd = process.platform === "darwin" ? "open"
    : process.platform === "win32" ? "start"
    : "xdg-open";
  exec(`${cmd} "${url}"`, { windowsHide: true }, (err) => {
    if (err) console.log(`Open browser manually: ${url}`);
  });
}

function killProcessOnPort(port) {
  return new Promise((resolve) => {
    try {
      if (process.platform === "win32") {
        const output = execSync(`netstat -ano | findstr :${port}`, {
          encoding: "utf8", shell: true, windowsHide: true, timeout: 5000
        }).trim();
        const lines = output.split("\n").filter(l => l.includes("LISTENING"));
        if (lines.length > 0) {
          const pid = lines[0].trim().split(/\s+/).pop();
          execSync(`taskkill /F /PID ${pid} 2>nul`, { stdio: "ignore", shell: true, windowsHide: true });
        }
      } else {
        const pidOutput = execSync(`lsof -ti:${port}`, { encoding: "utf8", stdio: ["pipe", "pipe", "ignore"] }).trim();
        if (pidOutput) execSync(`kill -9 ${pidOutput.split("\n")[0]} 2>/dev/null`, { stdio: "ignore" });
      }
    } catch {}
    setTimeout(resolve, 500);
  });
}

// ─── Start Server ─────────────────────────────────────────────────────

function startServer() {
  const displayHost = host === DEFAULT_HOST ? "localhost" : host;
  const url = `http://${displayHost}:${port}/dashboard`;

  const server = spawn(process.execPath, ["--max-old-space-size=4096", serverPath], {
    cwd: standaloneDir,
    stdio: showLog ? "inherit" : "ignore",
    env: { ...process.env, PORT: String(port), HOSTNAME: host }
  });

  server.on("error", (err) => {
    console.error("Failed to start server:", err.message);
    process.exit(1);
  });

  server.on("close", (code) => {
    if (code && code !== 0) {
      console.error(`Server exited with code ${code}`);
    }
    process.exit(code || 0);
  });

  // Cleanup on exit
  const cleanup = () => {
    try { server.kill(); } catch {}
  };
  process.on("SIGINT", () => { cleanup(); process.exit(0); });
  process.on("SIGTERM", () => { cleanup(); process.exit(0); });
  process.on("SIGHUP", () => { cleanup(); process.exit(0); });

  return { server, url };
}

// ─── Main ─────────────────────────────────────────────────────────────

async function main() {
  await killProcessOnPort(port);

  const { server, url } = startServer();

  // Tray mode: no interactive menu
  if (trayMode) {
    console.log(`\n  ${pkg.name} v${pkg.version}`);
    console.log(`  Server: ${url}`);
    console.log(`\n  Running in background (PID: ${server.pid})\n`);
    return;
  }

  // Wait for server to be ready
  const { selectMenu, pause } = require("./src/cli/utils/input");
  const { clearScreen } = require("./src/cli/utils/display");

  // Wait a bit for server startup
  await new Promise(r => setTimeout(r, 3000));

  // If --no-browser, just show info and wait
  if (noBrowser) {
    console.log(`\n  ${pkg.name} v${pkg.version}`);
    console.log(`  Server: ${url}`);
    console.log(`\n  Press Ctrl+C to stop.\n`);
    return;
  }

  // Interactive menu loop
  while (true) {
    const displayHost = host === DEFAULT_HOST ? "localhost" : host;
    const serverUrl = `http://${displayHost}:${port}`;

    const choice = await selectMenu(
      `${pkg.name} (v${pkg.version})`,
      [
        { label: "Web UI (Open in Browser)", icon: "\ud83c\udf10" },
        { label: "Hide to Background", icon: "\ud83d\udd14" },
        { label: "Exit", icon: "\ud83d\udeaa" },
      ],
      0,
      `\ud83d\ude80 Server: ${serverUrl}`
    );

    if (choice === 0) {
      openBrowser(url);
      await pause("\nPress Enter to go back to menu...");
    } else if (choice === 1) {
      clearScreen();
      console.log(`\n  \ud83d\udd14 ${pkg.name} is running in background`);
      console.log(`  Server: ${serverUrl}`);
      console.log(`  PID: ${server.pid}`);
      console.log(`\n  Press Ctrl+C to stop.\n`);
      // Keep process alive, remove stdin listeners
      process.stdin.removeAllListeners("keypress");
      if (process.stdin.isTTY) try { process.stdin.setRawMode(false); } catch {}
      return;
    } else {
      // Exit
      console.log("\nExiting...");
      server.kill();
      setTimeout(() => process.exit(0), 100);
      return;
    }
  }
}

main().catch((err) => {
  console.error("Fatal:", err.message);
  process.exit(1);
});
