/**
 * `madarx doctor` — diagnose whether this machine can run madarX OS.
 *
 * Presence/health checks only — never opens the SQLite DB, never starts daemons.
 * `hard` checks gate a healthy verdict (and the exit code); soft checks are
 * advisory (shown with `!`).
 */

import fs from 'node:fs';
import net from 'node:net';
import path from 'node:path';
import { resolveHome } from './home.js';
import { PKG_ROOT } from './dispatch.js';
import { readEnvFile } from './env-file.js';

function checkNode() {
  const v = process.versions.node;
  const [maj, min] = v.split('.').map(Number);
  const ok = maj > 22 || (maj === 22 && min >= 5);
  return { name: 'Node ≥ 22.5', ok, detail: `found ${v}`, hard: true };
}

async function checkSqlite() {
  try {
    await import('node:sqlite');
    return { name: 'node:sqlite', ok: true, detail: 'available', hard: true };
  } catch (err) {
    return { name: 'node:sqlite', ok: false, detail: err.message, hard: true };
  }
}

function checkHomeWritable(layout) {
  try {
    fs.mkdirSync(layout.home, { recursive: true });
    const probe = path.join(layout.home, '.write-probe');
    fs.writeFileSync(probe, 'x');
    fs.rmSync(probe, { force: true });
    return { name: 'Data home writable', ok: true, detail: layout.home, hard: true };
  } catch (err) {
    return { name: 'Data home writable', ok: false, detail: `${layout.home}: ${err.message}`, hard: true };
  }
}

function checkMasterKey(layout) {
  const key = process.env.MADARX_MASTER_KEY || readEnvFile(layout.envFile).MADARX_MASTER_KEY;
  if (!key) {
    return {
      name: 'Master key',
      ok: false,
      hard: false,
      detail: 'not set — generated automatically on first run / `madarx setup`',
    };
  }
  const len = Buffer.from(key, 'base64').length;
  return {
    name: 'Master key',
    ok: len === 32,
    hard: false,
    detail: len === 32 ? 'present (32 bytes)' : `present but wrong length (${len} bytes — vault will not open)`,
  };
}

function checkStandalone() {
  const p = path.join(PKG_ROOT, '.next', 'standalone', 'server.js');
  const ok = fs.existsSync(p);
  return { name: 'Web build', ok, hard: false, detail: ok ? 'standalone bundle present' : 'missing — run `npm run build`' };
}

function checkWhatsAppDeps() {
  const ok = fs.existsSync(path.join(PKG_ROOT, 'scripts', 'whatsapp-bridge', 'node_modules'));
  return { name: 'WhatsApp bridge deps', ok, hard: false, detail: ok ? 'installed' : 'not installed (auto-installed on first WhatsApp use)' };
}

function checkPort() {
  return new Promise((resolve) => {
    const sock = net.connect({ host: '127.0.0.1', port: 8787 });
    let done = false;
    const finish = (inUse) => {
      if (done) return;
      done = true;
      try { sock.destroy(); } catch {}
      resolve({
        name: 'Port 8787',
        ok: true,
        hard: false,
        detail: inUse ? 'in use (madarx may already be running)' : 'free',
      });
    };
    sock.on('connect', () => finish(true));
    sock.on('error', () => finish(false));
    setTimeout(() => finish(false), 600);
  });
}

/** Run all checks. Returns { checks, ok } where ok is false if any hard check failed. */
export async function runDoctor() {
  const layout = resolveHome();
  const checks = [
    checkNode(),
    await checkSqlite(),
    checkHomeWritable(layout),
    checkMasterKey(layout),
    checkStandalone(),
    checkWhatsAppDeps(),
    await checkPort(),
  ];
  return { checks, ok: !checks.some((c) => c.hard && !c.ok) };
}

export async function doctor() {
  const { checks, ok } = await runDoctor();
  console.log('madarx doctor\n');
  for (const c of checks) {
    const mark = c.ok ? '✓' : (c.hard ? '✗' : '!');
    console.log(`  ${mark} ${c.name.padEnd(22)} ${c.detail}`);
  }
  console.log('');
  console.log(ok ? 'All hard checks passed.' : 'Some hard checks FAILED — fix the ✗ items above.');
  return ok ? 0 : 1;
}
