import assert from 'node:assert/strict';
import { test } from 'node:test';
import { buildGroups, lastOwnSent, lastSenderIs } from '../src/lib/timeline-groups.ts';
import type { TimelineEvent, TimelineItem } from '../src/lib/types.ts';

const MINUTE = 60 * 1000;

function event(id: string, sender: string, timestamp_ms: number, extra: Partial<TimelineEvent> = {}): TimelineItem {
  return {
    kind: 'event',
    event: { item_id: id, event_id: id, timestamp_ms, own: false, send_state: { kind: 'Sent' }, sender: { user_id: sender }, ...extra } as TimelineEvent
  };
}

test('a sender run shares one header until a gap or another sender', () => {
  const groups = buildGroups([
    event('a', '@x', 0),
    event('b', '@x', MINUTE),
    event('c', '@x', 10 * MINUTE),
    event('d', '@y', 11 * MINUTE),
    { kind: 'day', timestamp_ms: 12 * MINUTE },
    event('e', '@y', 12 * MINUTE)
  ]);
  assert.deepEqual(groups.map((g) => g.showSender), [true, false, true, true, true, true]);
});

test('gap rows are keyed by their id so pagination keeps them mounted', () => {
  const gap = { kind: 'historyGap', gap: { id: 'g1', older_boundary: null, newer_boundary: null, lifecycle: 'Idle', continuity: 'Unresolved', failure: null } } as TimelineItem;
  assert.equal(buildGroups([event('a', '@x', 0), gap])[1].key, 'gap-g1');
});

test('the latest own sent event and the latest sender are found from the end', () => {
  const list = [event('a', '@me', 0, { own: true }), event('b', '@x', 1), event('c', '@me', 2, { own: true, send_state: { kind: 'Sending' } })];
  assert.equal(lastOwnSent(list), 'a');
  assert.equal(lastSenderIs(list, '@me'), true);
  assert.equal(lastSenderIs([], '@me'), false);
});
