/**
 * Phase 3b — Worker-side Prometheus metrics.
 *
 * 6 metrics, prefixed `aao_worker_` by default. Worker mode emits these
 * from worker.ts (job lifecycle) and agent-loop.ts (LLM call + tool
 * call counters).
 *
 * Cardinality budget:
 *   - jobsTotal: pieces (~15) × statuses (~5) × profiles (~3) = ~225
 *   - llmCallsTotal: workerIds (~5) × backendIds (~10) × models (~5) =
 *     ~250 — the backendId axis matters when the worker talks to a
 *     proxy (LiteLLM or the AAO gateway itself).
 *   - toolCallsTotal: tool_names (~40) × success (2) = ~80
 *
 * Histograms emit bucket series proportional to label cardinality ×
 * 10 default buckets; even worst-case we stay well below the informal
 * 100k Prometheus cap.
 */
import { Counter, Gauge, Histogram, type Registry } from 'prom-client';

export interface WorkerMetrics {
  /** Total jobs completed by terminal status. */
  jobsTotal: Counter<'piece' | 'status' | 'profile'>;
  /** Currently-running jobs (gauge, inc on start / dec on end). */
  activeJobs: Gauge<'piece' | 'profile'>;
  /** Total wall-clock seconds per job (start → terminal). */
  jobDurationSeconds: Histogram<'piece' | 'status' | 'profile'>;
  /** Outbound LLM calls. backend_id is the proxy-resolved physical backend or the worker_id when direct. */
  llmCallsTotal: Counter<'worker_id' | 'backend_id' | 'model'>;
  /** Wall-clock seconds per LLM call. */
  llmCallDurationSeconds: Histogram<'worker_id' | 'backend_id' | 'model'>;
  /** Tool invocations from the agent loop. success is "true" / "false". */
  toolCallsTotal: Counter<'tool_name' | 'success'>;
}

export function createWorkerMetrics(
  registry: Registry,
  prefix: string = 'aao_worker',
): WorkerMetrics {
  const jobsTotal = new Counter({
    name: `${prefix}_jobs_total`,
    help: 'Total jobs completed by piece / status / profile.',
    labelNames: ['piece', 'status', 'profile'] as const,
    registers: [registry],
  });

  const activeJobs = new Gauge({
    name: `${prefix}_active_jobs`,
    help: 'Currently-running jobs.',
    labelNames: ['piece', 'profile'] as const,
    registers: [registry],
  });

  const jobDurationSeconds = new Histogram({
    name: `${prefix}_job_duration_seconds`,
    help: 'Wall-clock job duration in seconds.',
    labelNames: ['piece', 'status', 'profile'] as const,
    // Override default buckets — jobs run from seconds to many minutes,
    // so the HTTP-tuned defaults (5ms..10s) bury most observations.
    buckets: [1, 5, 15, 30, 60, 120, 300, 600, 1800, 3600],
    registers: [registry],
  });

  const llmCallsTotal = new Counter({
    name: `${prefix}_llm_calls_total`,
    help: 'Outbound LLM API calls.',
    labelNames: ['worker_id', 'backend_id', 'model'] as const,
    registers: [registry],
  });

  const llmCallDurationSeconds = new Histogram({
    name: `${prefix}_llm_call_duration_seconds`,
    help: 'Wall-clock latency per LLM call.',
    labelNames: ['worker_id', 'backend_id', 'model'] as const,
    // LLM calls vary 100ms..120s; widen the bucket range.
    buckets: [0.1, 0.5, 1, 2, 5, 10, 30, 60, 120, 300],
    registers: [registry],
  });

  const toolCallsTotal = new Counter({
    name: `${prefix}_tool_calls_total`,
    help: 'Tool invocations executed by the agent loop.',
    labelNames: ['tool_name', 'success'] as const,
    registers: [registry],
  });

  return {
    jobsTotal,
    activeJobs,
    jobDurationSeconds,
    llmCallsTotal,
    llmCallDurationSeconds,
    toolCallsTotal,
  };
}

/** Closed enum of job terminal statuses for the jobsTotal counter. */
export type WorkerJobStatus =
  | 'succeeded'
  | 'failed'
  | 'aborted'
  | 'cancelled'
  | 'waiting_human'
  | 'error';
