'use strict';

/**
 * Lightweight boot/phase profiler. Records labeled wall-clock durations so we can
 * SEE where Wall-E startup time actually goes (brain open, migrations, WAL pragma,
 * backfills, bootstrap, channel/scheduler setup, port bind) instead of guessing.
 *
 * Usage:
 *   const boot = require('./lib/boot-profile');
 *   boot.reset();
 *   boot.measure('brain.initDb', () => brain.initDb());
 *   await boot.measureAsync('backfill', () => brain.backfillTemporalValidity());
 *   boot.mark('startServer', msSpent);
 *   boot.done(); console.log(boot.summary());
 *
 * The captured profile is process-global (last boot) and exposed read-only via
 * getProfile() — surfaced at GET /api/wall-e/boot-profile.
 */

const { performance } = require('perf_hooks');

let _profile = null;

function reset() {
  _profile = { startedAt: performance.now(), startedIso: new Date().toISOString(), marks: [], totalMs: null };
  return _profile;
}

function _ensure() {
  if (!_profile) reset();
  return _profile;
}

// Record a phase that took `ms` milliseconds. `meta` is optional structured detail.
function mark(label, ms, meta) {
  const p = _ensure();
  const entry = { label, ms: Math.round(ms), atMs: Math.round(performance.now() - p.startedAt) };
  if (meta && typeof meta === 'object') entry.meta = meta;
  p.marks.push(entry);
  return entry;
}

// Time a synchronous function, record under `label`, return its result.
function measure(label, fn, meta) {
  const t0 = performance.now();
  try {
    return fn();
  } finally {
    mark(label, performance.now() - t0, meta);
  }
}

// Time an async function, record under `label`, return its (awaited) result.
async function measureAsync(label, fn, meta) {
  const t0 = performance.now();
  try {
    return await fn();
  } finally {
    mark(label, performance.now() - t0, meta);
  }
}

// Stamp total elapsed since reset(). Call when boot reaches "ready".
function done() {
  const p = _ensure();
  p.totalMs = Math.round(performance.now() - p.startedAt);
  return getProfile();
}

function getProfile() {
  if (!_profile) return null;
  return {
    startedIso: _profile.startedIso,
    totalMs: _profile.totalMs,
    marks: _profile.marks.map((m) => ({ ...m })),
  };
}

// Human-readable summary, slowest phases first, for the boot log.
function summary() {
  if (!_profile || _profile.marks.length === 0) return '[boot-profile] (no marks)';
  const sorted = [..._profile.marks].sort((a, b) => b.ms - a.ms);
  const lines = sorted.map((m) => `  ${String(m.ms).padStart(7)}ms  ${m.label}`);
  const total = _profile.totalMs != null ? `${_profile.totalMs}ms` : '(open)';
  return `[boot-profile] total=${total}, phases (slowest first):\n${lines.join('\n')}`;
}

module.exports = { reset, mark, measure, measureAsync, done, getProfile, summary };
