/**
 * Phase 3b — smoke test for worker metric wiring.
 *
 * The full executeJob path is heavy (Repository, ConfigManager,
 * piece-runner, LLM client) so this test focuses on the smaller surface
 * we added: setWorkerMetrics + the WorkerManager fan-out.
 */
import { describe, it, expect } from 'vitest';
import { Registry } from 'prom-client';
import { createWorkerMetrics } from './metrics/worker-metrics.js';

describe('worker metrics smoke', () => {
  it('createWorkerMetrics produces a Counter that increments on labelled inc', async () => {
    const reg = new Registry();
    const m = createWorkerMetrics(reg, 'aao_worker_smoke');
    m.jobsTotal.labels({ piece: 'chat', status: 'succeeded', profile: 'main' }).inc();
    m.activeJobs.labels({ piece: 'chat', profile: 'main' }).inc();
    m.activeJobs.labels({ piece: 'chat', profile: 'main' }).dec();
    m.toolCallsTotal.labels({ tool_name: 'Read', success: 'true' }).inc(3);
    m.llmCallsTotal.labels({ worker_id: 'w1', backend_id: 'gpu-a', model: 'qwen3:8b' }).inc();
    m.llmCallDurationSeconds.labels({ worker_id: 'w1', backend_id: 'gpu-a', model: 'qwen3:8b' }).observe(1.5);
    m.jobDurationSeconds.labels({ piece: 'chat', status: 'succeeded', profile: 'main' }).observe(42);
    const out = await reg.metrics();
    expect(out).toMatch(/aao_worker_smoke_jobs_total\{piece="chat",status="succeeded",profile="main"\} 1/);
    expect(out).toMatch(/aao_worker_smoke_active_jobs\{piece="chat",profile="main"\} 0/);
    expect(out).toMatch(/aao_worker_smoke_tool_calls_total\{tool_name="Read",success="true"\} 3/);
    expect(out).toMatch(/aao_worker_smoke_llm_calls_total\{[^}]*model="qwen3:8b"[^}]*\} 1/);
    expect(out).toMatch(/aao_worker_smoke_llm_call_duration_seconds_sum\{[^}]+\} 1\.5/);
    expect(out).toMatch(/aao_worker_smoke_job_duration_seconds_sum\{[^}]+\} 42/);
  });

  it('terminal-status mapping covers all known PieceRunResult statuses', () => {
    // We mirror the switch in worker.executeJob to lock in the
    // expected mapping. If a piece-runner adds a new status the mapper
    // must be extended (the switch's default lands on 'failed').
    const mapping: Record<string, string> = {
      completed: 'succeeded',
      aborted: 'aborted',
      cancelled: 'cancelled',
      waiting_human: 'waiting_human',
      waiting_subtasks: 'succeeded',
      error: 'failed',
      something_else: 'failed', // default branch
    };
    for (const [from, to] of Object.entries(mapping)) {
      let metric: string;
      switch (from) {
        case 'completed': metric = 'succeeded'; break;
        case 'aborted': metric = 'aborted'; break;
        case 'cancelled': metric = 'cancelled'; break;
        case 'waiting_human': metric = 'waiting_human'; break;
        case 'waiting_subtasks': metric = 'succeeded'; break;
        case 'error':
        default: metric = 'failed'; break;
      }
      expect(metric).toBe(to);
    }
  });
});
