/**
 * SET 64 — metasupercache pure algorithm: caps, trim/evict order, oversize
 * refusal, ring eviction, corpse detection.
 */
import { describe, expect, it } from 'vitest';
import {
  appendCandidate,
  corpseCheck,
  corpseHashesOf,
  drawHash,
  epochBytes,
  formatCorpseEvent,
  META_SB_EPOCH_CAP_BYTES,
  META_SB_REFUSE_WRITE_BYTES,
  normalizeDrawText,
  ringEvictions,
} from '../src/tier1/metaSb';
import type { MetaCandidateRecord } from '../src/tier1/metaSb';

function rec(partial?: Partial<MetaCandidateRecord>): MetaCandidateRecord {
  return {
    classKey: 'assertion|toBe', layer: 'L3', temp: 0.7, score: 2, findings: 1,
    parseStatus: 'parsed', hash: drawHash('export function f() { return 1; }'),
    ...partial,
  };
}

describe('SET 64 — metasupercache', () => {
  it('normalization: comments and whitespace churn hash identical; real edits differ', () => {
    const a = 'export function add(a, b) { return a + b; }';
    const b = 'export function add(a, b) {\n  // sum\n  return   a + b;\n}';
    const c = 'export function add(a, b) { return a - b; }';
    expect(drawHash(a)).toBe(drawHash(b));
    expect(drawHash(a)).not.toBe(drawHash(c));
    expect(normalizeDrawText(b)).not.toMatch(/\/\//);
  });

  it('append honors the epoch cap: diffs trimmed first, then oldest evicted', () => {
    const big = 'x'.repeat(900);
    let epoch: MetaCandidateRecord[] = [];
    for (let i = 0; i < 400; i++) {
      const r = appendCandidate(epoch, rec({ hash: `h${i}`, diffVsIncumbent: big }));
      expect(r.status).not.toBe('refused');
      epoch = r.epoch;
    }
    expect(epochBytes(epoch)).toBeLessThanOrEqual(META_SB_EPOCH_CAP_BYTES);
    // Oldest surviving records lost their diffs before any eviction of newer ones.
    const withDiff = epoch.filter(r => r.diffVsIncumbent);
    expect(withDiff.length).toBeLessThan(epoch.length);
  });

  it('oversize single write is refused with state kept', () => {
    const epoch = [rec({ hash: 'keep' })];
    const r = appendCandidate(epoch, rec({
      diffVsIncumbent: 'x'.repeat(META_SB_REFUSE_WRITE_BYTES * 2),
      classKey: 'x'.repeat(META_SB_REFUSE_WRITE_BYTES),
    }));
    expect(r.status).toBe('refused');
    expect(r.epoch).toEqual(epoch);
  });

  it('diff is bounded to 1KB on accept', () => {
    const r = appendCandidate([], rec({ diffVsIncumbent: 'y'.repeat(5000) }));
    expect(r.status).toBe('accepted');
    expect(r.epoch[0]!.diffVsIncumbent!.length).toBe(1024);
  });

  it('ring eviction: >4 epochs drop oldest; total cap enforced', () => {
    const epochs = ['a', 'b', 'c', 'd', 'e', 'f'].map(runId => ({ runId, bytes: 100 }));
    expect(ringEvictions(epochs)).toEqual(['a', 'b']);
    const fat = ['a', 'b', 'c', 'd'].map(runId => ({ runId, bytes: 400 * 1024 }));
    expect(ringEvictions(fat)).toEqual(['a', 'b']); // 2×400KB ≤ 1MB
  });

  it('draw identity is per-unit: identical content for a DIFFERENT path is not a corpse', async () => {
    const { drawHashForFiles } = await import('../src/tier1/metaSb');
    const content = 'export function add(a, b) { return a + b; }';
    const h1 = drawHashForFiles([{ path: 'src/adder1.ts', content }]);
    const h2 = drawHashForFiles([{ path: 'src/adder2.ts', content }]);
    expect(h1).not.toBe(h2); // cross-feature reuse is the flywheel, not a corpse
    expect(drawHashForFiles([{ path: 'src/adder1.ts', content }])).toBe(h1);
  });

  it('corpse detection distinguishes run vs metasupercache sources', () => {
    const h = drawHash('const x = 1;');
    expect(corpseCheck(h, new Set([h]), new Set())).toBe('run');
    expect(corpseCheck(h, new Set(), new Set([h]))).toBe('meta');
    expect(corpseCheck(h, new Set(), new Set())).toBeNull();
    expect(formatCorpseEvent('assertion|toBe', 'meta')).toMatch(/without execution.*metasupercache/);
  });

  it('corpseHashesOf unions epochs, deduped', () => {
    const e1 = [rec({ hash: 'h1' }), rec({ hash: 'h2' })];
    const e2 = [rec({ hash: 'h2' }), rec({ hash: 'h3' })];
    expect(corpseHashesOf([e1, e2]).sort()).toEqual(['h1', 'h2', 'h3']);
  });
});
