#!/usr/bin/env node
/**
 * system-info.mjs — OmniRoute System Information Reporter (#280)
 *
 * Collects system/environment info for bug reports.
 * Usage: node scripts/system-info.mjs [--output system-info.txt]
 *
 * Output includes:
 *   - Node.js version
 *   - OmniRoute version
 *   - OS info
 *   - Relevant system packages (if apt available)
 *   - Agent CLI tools (qoder, gemini, claude, codex, antigravity, droid, etc.)
 *   - Docker / PM2 status
 */

import { execSync } from "child_process";
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
import { join, dirname } from "path";
import { fileURLToPath } from "url";
import os from "os";

const __dirname = dirname(fileURLToPath(import.meta.url));
const ROOT = join(__dirname, "..");

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

function run(cmd, fallback = "N/A") {
  try {
    return execSync(cmd, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
  } catch {
    return fallback;
  }
}

function toolVersion(cmd, args = "--version") {
  const version = run(`${cmd} ${args}`, null);
  if (version === null) return "not installed";
  // Trim to first line, remove prefixes like "v", "Version: "
  return version
    .split("\n")[0]
    .replace(/^(version\s*:?\s*|v)/i, "")
    .trim();
}

function section(title) {
  const line = "─".repeat(60);
  return `\n${line}\n  ${title}\n${line}\n`;
}

// ── Collect Info ──────────────────────────────────────────────────────────

const lines = [];

lines.push("OmniRoute System Information Report");
lines.push(`Generated: ${new Date().toISOString()}`);

// ── Node.js & Runtime ────────────────────────────────────────────────────

lines.push(section("Node.js & Runtime"));
lines.push(`Node.js:    ${process.version}`);
lines.push(`npm:        v${run("npm --version")}`);
lines.push(`Platform:   ${process.platform} (${process.arch})`);
lines.push(`OS:         ${os.type()} ${os.release()} (${os.arch()})`);
lines.push(`Hostname:   ${os.hostname()}`);
lines.push(`CPUs:       ${os.cpus().length}x ${os.cpus()[0]?.model || "unknown"}`);
lines.push(`Total RAM:  ${Math.round(os.totalmem() / 1024 / 1024)} MB`);
lines.push(`Free RAM:   ${Math.round(os.freemem() / 1024 / 1024)} MB`);

// ── OmniRoute Version ────────────────────────────────────────────────────

lines.push(section("OmniRoute"));
try {
  const pkg = JSON.parse(readFileSync(join(ROOT, "package.json"), "utf-8"));
  lines.push(`Version:    ${pkg.version}`);
  lines.push(`Name:       ${pkg.name}`);
} catch {
  lines.push("Version:    unable to read package.json");
}

const installedGlobal = run("npm list -g omniroute --depth=0 2>/dev/null | grep omniroute");
lines.push(`Global npm: ${installedGlobal || "not installed globally"}`);

const pm2Status = run("pm2 list 2>/dev/null | grep omniroute | awk '{print $4, $10, $12}'");
lines.push(`PM2 status: ${pm2Status || "not running via PM2"}`);

// ── Agent CLI Tools ──────────────────────────────────────────────────────

lines.push(section("Agent CLI Tools"));

const cliTools = [
  { name: "qoder-cli", cmd: "qoder", args: "--version" },
  { name: "gemini-cli", cmd: "gemini", args: "--version" },
  { name: "claude-code", cmd: "claude", args: "--version" },
  { name: "openai-codex", cmd: "codex", args: "--version" },
  { name: "antigravity", cmd: "antigravity", args: "--version" },
  { name: "droid", cmd: "droid", args: "--version" },
  { name: "openclaw", cmd: "openclaw", args: "--version" },
  { name: "kilo", cmd: "kilo", args: "--version" },
  { name: "cursor", cmd: "cursor", args: "--version" },
  { name: "aider", cmd: "aider", args: "--version" },
];

for (const { name, cmd, args } of cliTools) {
  const v = toolVersion(cmd, args);
  lines.push(`${name.padEnd(20)} ${v}`);
}

// ── Docker ───────────────────────────────────────────────────────────────

lines.push(section("Docker"));
lines.push(`Docker:     ${run("docker --version", "not installed")}`);

const dockerContainers = run(
  "docker ps --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}' 2>/dev/null",
  "N/A"
);
lines.push(`Containers:\n${dockerContainers}`);

// ── System Packages ──────────────────────────────────────────────────────

lines.push(section("System Packages (relevant)"));

const relevantPkgs = ["build-essential", "libssl-dev", "openssl", "libsqlite3-dev", "python3"];
for (const pkg of relevantPkgs) {
  const ver = run(`dpkg -l ${pkg} 2>/dev/null | grep '^ii' | awk '{print $3}'`, "not found");
  lines.push(`${pkg.padEnd(24)} ${ver}`);
}

// ── Environment Variables (safe subset) ─────────────────────────────────

lines.push(section("Environment Variables (non-sensitive)"));

const safeEnvKeys = [
  "NODE_ENV",
  "PORT",
  "DATA_DIR",
  "DB_BACKUPS_DIR",
  "LOG_LEVEL",
  "NEXT_PUBLIC_APP_URL",
  "ROUTER_API_KEY_HINT",
];

for (const key of safeEnvKeys) {
  const val = process.env[key];
  if (val !== undefined) {
    // Mask if looks like a secret
    const masked = val.length > 8 ? val.substring(0, 4) + "****" : "****";
    lines.push(`${key.padEnd(28)} ${masked}`);
  }
}

// ── Output ───────────────────────────────────────────────────────────────

const report = lines.join("\n") + "\n";

// Write to file
const outArg = process.argv.find((a) => a.startsWith("--output="));
const outFile = outArg
  ? outArg.replace("--output=", "")
  : process.argv[process.argv.indexOf("--output") + 1] || "system-info.txt";

const outPath = join(ROOT, outFile);

mkdirSync(dirname(outPath), { recursive: true });
writeFileSync(outPath, report);
console.log(report);
console.log(`\n✅ Report saved to: ${outPath}`);
console.log(
  `📎 Attach this file when reporting issues at: https://github.com/diegosouzapw/OmniRoute/issues`
);
