/**
 * SET 43e — Lesson→handler promotion (handler-candidate drafts).
 * Admission through mutation-oracle is later — not auto-admitted.
 */
import { describe, expect, it } from 'vitest';
import {
  promoteLessonsToHandlerCandidates,
  type HealedInstance,
} from '../src/tier1/handlerCandidate';

function heal(
  classKey: string,
  editShape: string,
  before = 'BEFORE',
  after = 'AFTER',
): HealedInstance {
  return { classKey, editShape, beforeSnippet: before, afterSnippet: after, path: 'src/a.ts' };
}

describe('SET 43e — promoteLessonsToHandlerCandidates', () => {
  it('3 matching heals → 1 candidate', () => {
    const instances = [
      heal('assertion|toBe', 'replace-literal'),
      heal('assertion|toBe', 'replace-literal', 'a', 'b'),
      heal('assertion|toBe', 'replace-literal', 'c', 'd'),
    ];
    const out = promoteLessonsToHandlerCandidates(instances);
    expect(out).toHaveLength(1);
    expect(out[0]!.status).toBe('handler-candidate');
    expect(out[0]!.classKey).toBe('assertion|toBe');
    expect(out[0]!.editShape).toBe('replace-literal');
    expect(out[0]!.support).toBe(3);
    expect(out[0]!.fixtures).toHaveLength(3);
    expect(out[0]!.draftRule).toMatch(/mechanical-candidate/);
    expect(out[0]!.draftRule).toMatch(/mutation-oracle/);
  });

  it('2 matching → none', () => {
    const instances = [
      heal('undefined-symbol|foo', 'add-export'),
      heal('undefined-symbol|foo', 'add-export'),
    ];
    expect(promoteLessonsToHandlerCandidates(instances)).toEqual([]);
  });

  it('different editShapes do not merge', () => {
    const instances = [
      heal('assertion|toBe', 'replace-literal'),
      heal('assertion|toBe', 'replace-literal'),
      heal('assertion|toBe', 'widen-type'),
      heal('assertion|toBe', 'widen-type'),
      heal('assertion|toBe', 'widen-type'),
    ];
    const out = promoteLessonsToHandlerCandidates(instances);
    expect(out).toHaveLength(1);
    expect(out[0]!.editShape).toBe('widen-type');
    expect(out[0]!.support).toBe(3);
    // replace-literal only has support 2 — excluded
    expect(out.every(c => c.editShape !== 'replace-literal')).toBe(true);
  });

  it('is pure/deterministic across calls', () => {
    const instances = [
      heal('x|y', 'shape-a'),
      heal('x|y', 'shape-a'),
      heal('x|y', 'shape-a'),
    ];
    expect(promoteLessonsToHandlerCandidates(instances)).toEqual(
      promoteLessonsToHandlerCandidates(instances),
    );
  });
});
