/**
 * SET 14 — shared Tier 1 metrics display / aggregation helpers.
 * Used by the web UI (and mirrored in extension/offscreen.js for live merge).
 */

/** Format elapsed seconds as H:MM:SS (hours unpadded, minutes/seconds zero-padded). */
export function formatHms(totalSeconds: number): string {
  const s = Math.max(0, Math.floor(Number(totalSeconds) || 0));
  const h = Math.floor(s / 3600);
  const m = Math.floor((s % 3600) / 60);
  const sec = s % 60;
  return `${h}:${String(m).padStart(2, '0')}:${String(sec).padStart(2, '0')}`;
}

/** Σ passesPerFeature — the only authoritative cycle total (SET 14a). */
export function derivePassesTotal(passesPerFeature?: Record<string, number> | null): number {
  if (!passesPerFeature || typeof passesPerFeature !== 'object') return 0;
  let sum = 0;
  for (const n of Object.values(passesPerFeature)) sum += Number(n) || 0;
  return sum;
}

export interface Tier1StatusMetricsInput<T> {
  running: boolean;
  /** Metrics from a completed run — may be stale (from a PRIOR run) while a new one is starting up. */
  stored: T | null;
  /** Freshly derived live metrics (liveMetrics + usage, merged monotonically) — always available while running. */
  live: T;
}

/**
 * SET 24a — status metrics selection contract: while a run is in flight,
 * ALWAYS surface live metrics, never a stale `stored` value left over from a
 * prior run in the same offscreen document. Only once the run has finished
 * does `stored` become authoritative. Mirrored inline in extension/offscreen.js
 * (tier1:status) — that file can't import this module directly.
 */
export function selectTier1StatusMetrics<T>(input: Tier1StatusMetricsInput<T>): T | null {
  return input.running ? input.live : input.stored;
}

export type MonoMetricFloor = {
  passesTotal: number;
  tokensIn: number;
  tokensOut: number;
  llmCalls: number;
};

/**
 * Live-status merge: cycles/tokens/calls never decrease within a run
 * (kills the live-snapshot vs recomputed-sum race observed as 20 → 19).
 */
export function mergeMonotonicLiveMetrics<T extends Record<string, unknown>>(
  prev: Partial<MonoMetricFloor> | null | undefined,
  next: T & Partial<MonoMetricFloor> & { passesPerFeature?: Record<string, number> },
): T & MonoMetricFloor {
  const ppf = next.passesPerFeature;
  const derived = ppf && Object.keys(ppf).length > 0
    ? derivePassesTotal(ppf)
    : (Number(next.passesTotal) || 0);
  const floor: MonoMetricFloor = {
    passesTotal: Math.max(Number(prev?.passesTotal) || 0, derived),
    tokensIn: Math.max(Number(prev?.tokensIn) || 0, Number(next.tokensIn) || 0),
    tokensOut: Math.max(Number(prev?.tokensOut) || 0, Number(next.tokensOut) || 0),
    llmCalls: Math.max(Number(prev?.llmCalls) || 0, Number(next.llmCalls) || 0),
  };
  return { ...next, ...floor };
}
