import { assert, createLogicSuite } from '@genesislcap/foundation-testing';
import {
  clearMetaEventRegistry,
  clearSession,
  getMetaEvents,
  type MetaEvent,
  mergeMetaEvents,
  recordMetaEvent,
} from './debug-event-log';

const event = (overrides: Partial<MetaEvent> = {}): MetaEvent => ({
  index: 0,
  timestamp: '2026-06-19T16:00:00.000Z',
  type: 'turn.retry',
  importance: 'normal',
  ...overrides,
});

const suite = createLogicSuite('debug-event-log merge/clear');

suite('mergeMetaEvents is a no-op for an empty batch', () => {
  clearMetaEventRegistry();
  mergeMetaEvents('k', []);
  assert.is(getMetaEvents('k').length, 0);
});

suite('mergeMetaEvents preserves each event timestamp and re-indexes monotonically', () => {
  clearMetaEventRegistry();
  mergeMetaEvents('k', [
    event({ index: 7, timestamp: '2026-06-19T16:00:01.000Z', detail: { a: 1 } }),
    event({ index: 99, timestamp: '2026-06-19T16:00:02.000Z', detail: { b: 2 } }),
  ]);
  const out = getMetaEvents('k');
  assert.is(out.length, 2);
  // original timestamps kept (not re-stamped) ...
  assert.is(out[0].timestamp, '2026-06-19T16:00:01.000Z');
  assert.is(out[1].timestamp, '2026-06-19T16:00:02.000Z');
  // ... indices re-assigned from the target's counter, not carried from source.
  assert.is(out[0].index, 0);
  assert.is(out[1].index, 1);
  assert.equal(out[0].detail, { a: 1 });
});

suite('mergeMetaEvents appends after existing events with a continuing index', () => {
  clearMetaEventRegistry();
  recordMetaEvent('k', 'turn.start'); // index 0, real timestamp
  mergeMetaEvents('k', [event({ type: 'turn.error', importance: 'high' })]);
  const out = getMetaEvents('k');
  assert.is(out.length, 2);
  assert.is(out[0].type, 'turn.start');
  assert.is(out[1].type, 'turn.error');
  assert.is(out[1].index, 1); // continues the monotonic counter
});

suite('mergeMetaEvents into a fresh key creates the bucket', () => {
  clearMetaEventRegistry();
  mergeMetaEvents('brand-new', [event()]);
  assert.is(getMetaEvents('brand-new').length, 1);
});

suite('mergeMetaEvents evicts oldest non-high events past the cap but keeps every high', () => {
  clearMetaEventRegistry();
  const highStamp = '2026-06-19T16:30:00.000Z';
  // One `high` failure first, then a flood of `normal` events well past the cap.
  const batch: MetaEvent[] = [
    event({ type: 'turn.error', importance: 'high', timestamp: highStamp }),
  ];
  for (let i = 0; i < 2000; i += 1) {
    batch.push(event({ type: 'turn.retry', importance: 'normal' }));
  }
  mergeMetaEvents('k', batch);
  const out = getMetaEvents('k');
  // Eviction ran (bounded below what we merged) ...
  assert.ok(out.length < 2001);
  // ... and the lone high-importance failure was never dropped.
  assert.is(out.filter((e) => e.importance === 'high').length, 1);
  assert.ok(out.some((e) => e.timestamp === highStamp));
});

suite('clearSession drops one key without touching others', () => {
  clearMetaEventRegistry();
  recordMetaEvent('child', 'turn.retry');
  recordMetaEvent('parent', 'turn.start');
  clearSession('child');
  assert.is(getMetaEvents('child').length, 0);
  assert.is(getMetaEvents('parent').length, 1);
});

suite.run();
