/**
 * SET 37i — eventTone single source of truth.
 * Enumerate kinds: zero unmapped; zero green without success predicate.
 */
import { describe, expect, it } from 'vitest';
import {
  allEventKinds,
  EVENT_KIND_TONES,
  GREEN_SUCCESS_KINDS,
  classifyEventKind,
  eventTone,
  isSuccessKind,
  jobEventToneCss,
  t1EventToneCss,
  toneForKind,
  toneToCss,
} from '../src/tier1/eventTone';

describe('SET 37i eventTone map', () => {
  it('enumerates every kind with a tone — zero unmapped', () => {
    const kinds = allEventKinds();
    expect(kinds.length).toBeGreaterThan(40);
    for (const k of kinds) {
      expect(EVENT_KIND_TONES[k]).toBeDefined();
      expect(['green', 'yellow', 'friction', 'red', 'dim']).toContain(toneForKind(k));
    }
  });

  it('zero green without success predicate', () => {
    for (const [kind, tone] of Object.entries(EVENT_KIND_TONES)) {
      if (tone === 'green') {
        expect(isSuccessKind(kind)).toBe(true);
        expect(GREEN_SUCCESS_KINDS.has(kind)).toBe(true);
      }
    }
    // llm / operational must never be green
    expect(toneForKind('llm-call')).toBe('yellow');
    expect(toneForKind('llm-usage')).toBe('yellow');
    expect(toneForKind('superbuffer')).toBe('yellow');
    expect(toneForKind('permutation-select')).toBe('yellow');
    expect(toneForKind('relay')).toBe('yellow');
    expect(toneToCss('yellow')).toBe('warn');
  });

  it('PINNED EXPECTATIONS — canonical success fixtures stay GREEN', () => {
    const pinned: Array<{ message: string; phase?: string }> = [
      { message: 'case "fn" filled by model', phase: 'ir' },
      { message: 'frozen suite tests/f1.test.ts (clades 2:0)', phase: 'ir' },
      { message: 'converged in 0 passes', phase: 'auth' },
      { message: 'case "x" healed via delimiter (0 tok)', phase: 'rha' },
      { message: 'case "x" rebound via clade (0 tok)', phase: 'rha' },
      { message: 'suite re-frozen after surgery', phase: 'rha' },
      { message: 'un-parked — ready', phase: 'rha' },
      { message: 'unparked — ready', phase: 'rha' },
    ];
    for (const fixture of pinned) {
      expect(eventTone(fixture)).toBe('green');
    }
    expect(classifyEventKind({ message: 'case "fn" filled by model' })).toBe('filled');
    expect(classifyEventKind({ message: 'case "x" rebound via clade (0 tok)' })).toBe('rebound');
    expect(classifyEventKind({ message: 'un-parked — ready' })).toBe('unparked');
    expect(classifyEventKind({ message: 'unparked — ready' })).toBe('unparked');
    expect(classifyEventKind({ message: 'case "x" healed via delimiter (0 tok)' })).toBe('healed');
  });

  it('classifies pipeline messages into the right tone buckets', () => {
    expect(eventTone({ message: 'case "fn" filled by model', phase: 'ir' })).toBe('green');
    expect(eventTone({ message: 'frozen suite tests/f1.test.ts (clades 2:0)', phase: 'ir' })).toBe('green');
    expect(eventTone({ message: 'converged in 0 passes', phase: 'auth' })).toBe('green');
    expect(eventTone({ message: 'LLM fixTestCases · F1: 100 in / 40 out', phase: 'ir' })).toBe('yellow');
    expect(eventTone({
      message: 'superbuffer: assembled pages [spec:120, contract:80] stage=fill for "x"',
      phase: 'ir',
    })).toBe('yellow');
    expect(eventTone({ message: 'case "x" dropped — unparseable: Unexpected token', phase: 'ir' })).toBe('red');
    expect(eventTone({ message: 'no-coverage — abandoned after metaloop 3', phase: 'ir' })).toBe('red');
    expect(eventTone({ message: 'persist failed: Object could not be cloned.', phase: 'done' })).toBe('red');
    expect(eventTone({ message: 'feature deferred to end-of-phase retry (2 frozen exemplars, 3 sibling cases now available)', phase: 'ir' })).toBe('dim');
    // SET 42g — incumbent-kept is friction (was dim); rejected draws are friction (was red).
    expect(eventTone({ message: 'pass 2: no improvement — incumbent kept', phase: 'rha' })).toBe('friction');
    expect(eventTone({ message: 'build draw rejected: unparseable in src/a.ts', phase: 'build' })).toBe('friction');
    // SET 81 — a substrate no-handler is a FAILURE to repair, not neutral
    // bookkeeping: it reads dark orange like every other failure (Andy).
    expect(eventTone({ message: 'substrate: assertion|eq → no-handler (0 tok)', phase: 'rha' })).toBe('friction');
  });

  it('App helpers: llm-usage is warn (yellow), never ok', () => {
    expect(jobEventToneCss({ kind: 'llm-usage', data: { op: 'build' } })).toBe('warn');
    expect(t1EventToneCss({
      phase: 'build',
      message: 'superbuffer: assembled pages [spec:10] stage=build for "fn"',
    })).toBe('warn');
    expect(t1EventToneCss({
      phase: 'auth',
      message: 'converged in 1 passes',
    })).toBe('ok');
    expect(classifyEventKind({ kind: 'llm-usage', message: '' })).toBe('llm-usage');
  });
});
