/**
 * Phase 3b post-review — tool_name label normalization.
 */
import { describe, it, expect } from 'vitest';
import { Registry } from 'prom-client';
import { normalizeToolNameForMetric, BUILTIN_TOOL_NAMES } from './tool-name-allowlist.js';
import { createWorkerMetrics } from './worker-metrics.js';

describe('normalizeToolNameForMetric', () => {
  it('passes built-in tool names through verbatim', () => {
    expect(normalizeToolNameForMetric('Read')).toBe('Read');
    expect(normalizeToolNameForMetric('WebFetch')).toBe('WebFetch');
    expect(normalizeToolNameForMetric('SpawnSubTask')).toBe('SpawnSubTask');
  });

  it('collapses every mcp__* name to a single mcp bucket', () => {
    expect(normalizeToolNameForMetric('mcp__alpha__foo')).toBe('mcp');
    expect(normalizeToolNameForMetric('mcp__beta__bar')).toBe('mcp');
    expect(normalizeToolNameForMetric('mcp__github__create_issue')).toBe('mcp');
  });

  it('collapses anything else to unknown', () => {
    expect(normalizeToolNameForMetric('some_random_tool')).toBe('unknown');
    expect(normalizeToolNameForMetric('')).toBe('unknown');
    expect(normalizeToolNameForMetric('not_a_real_tool_name')).toBe('unknown');
  });

  it('does not treat partial mcp_ prefix as MCP (must be `mcp__`)', () => {
    expect(normalizeToolNameForMetric('mcp_foo')).toBe('unknown');
    expect(normalizeToolNameForMetric('mcpwhatever')).toBe('unknown');
  });

  it('runtime tools (transition, complete) pass through', () => {
    expect(normalizeToolNameForMetric('transition')).toBe('transition');
    expect(normalizeToolNameForMetric('complete')).toBe('complete');
  });

  it('BUILTIN_TOOL_NAMES contains the documented set of built-ins', () => {
    // Smoke-checks: ensure we didn't accidentally drop a known tool.
    const required = ['Read', 'Write', 'Edit', 'Bash', 'Glob', 'Grep', 'WebFetch', 'BrowseWeb'];
    for (const name of required) {
      expect(BUILTIN_TOOL_NAMES.has(name)).toBe(true);
    }
  });

  it('label cardinality stays bounded: many mcp__* names share one bucket', async () => {
    const reg = new Registry();
    const m = createWorkerMetrics(reg, 'aao_worker_n');
    // Simulate 100 distinct mcp__* names.
    for (let i = 0; i < 100; i += 1) {
      m.toolCallsTotal
        .labels({ tool_name: normalizeToolNameForMetric(`mcp__server${i}__tool${i}`), success: 'true' })
        .inc();
    }
    const dump = await reg.metrics();
    // All 100 calls should have collapsed into the single mcp bucket.
    expect(dump).toMatch(/aao_worker_n_tool_calls_total\{tool_name="mcp",success="true"\} 100/);
    // No mcp__ literals should leak into the metric body.
    expect(dump).not.toMatch(/tool_name="mcp__/);
  });
});
