/**
 * GET  /api/system/update — update status: { current, latest, behind, ts }.
 *                            Reads the local .update_check ledger written by the
 *                            weekly job; falls back to current version when absent.
 * POST /api/system/update — owner/admin-initiated apply. The click IS the consent,
 *                            so this calls applyUpdate() directly (an explicit human
 *                            action) rather than routing through the agent-only,
 *                            always-gated self_update tool. Audited.
 */

import { requireSession } from '@/lib/auth.js';
import { resolveHome } from '@/lib/cli/home.js';
import { readUpdateCheck, currentVersion, runUpdateCheck, compareSemver } from '@/lib/update-check.js';
import { applyUpdate } from '@/lib/cli/update.js';

export const runtime = 'nodejs';
export const dynamic = 'force-dynamic';

function requireAdmin(session) {
  if (session.role !== 'admin' && session.role !== 'owner') {
    throw { status: 403, error: 'forbidden' };
  }
}

export async function GET(req) {
  try {
    await requireSession(req);
    const ledger = readUpdateCheck(resolveHome().updateCheckFile);
    const current = currentVersion();
    const latest = ledger?.latest || null;
    // Derive `behind` live from latest vs the current version rather than trusting
    // the ledger's stored flag — a ledger written by an older build that misread
    // its own version (e.g. '0.0.0') would otherwise pin the banner to "update
    // available" forever even after upgrading.
    const behind = latest ? compareSemver(latest, current) > 0 : false;
    return Response.json({
      ok: true,
      current,
      latest,
      behind,
      checked_at: ledger?.ts || null,
    });
  } catch (err) {
    if (err && typeof err === 'object' && err.status) {
      return Response.json({ error: err.error || 'unauthorized' }, { status: err.status });
    }
    throw err;
  }
}

export async function POST(req) {
  let body = {};
  try { body = await req.json(); } catch { /* empty body ok */ }

  try {
    const session = await requireSession(req);
    requireAdmin(session);
  } catch (err) {
    if (err && typeof err === 'object' && err.status) {
      return Response.json({ error: err.error || 'unauthorized' }, { status: err.status });
    }
    throw err;
  }

  // Re-check against the registry so we never apply when already current.
  const check = await runUpdateCheck({ file: resolveHome().updateCheckFile });
  if (!check.reachable) {
    return Response.json({ ok: false, error: 'npm registry unreachable' }, { status: 502 });
  }
  if (!check.behind && !body?.force) {
    return Response.json({ ok: true, applied: false, current: check.current, message: 'already up to date' });
  }

  const res = await applyUpdate({ initiatedBy: 'dashboard' });
  return Response.json({
    ok: res.ok,
    applied: res.ok,
    from: res.from,
    to: check.latest,
    message: res.ok ? `Updated to v${check.latest}. Restart madarx to run the new version.` : `Update failed (exit ${res.code}).`,
  }, { status: res.ok ? 200 : 500 });
}
