import { describe, it, expect } from 'vitest';

// Seq logic test: verify the buffer-then-filter rule.
// Client buffers pre-snapshot deltas, discards seq <= snapshot_seq per-host.

interface Delta {
  type: 'control_fleet';
  seq: number;
  hosts: Array<{ providerId: string; seq: number }>;
}

interface Snapshot {
  type: 'control_fleet';
  seq: number;
  hosts: Array<{ providerId: string; seq: number }>;
}

function applyDelta(delta: Delta, snapshotSeqs: Map<string, number>): boolean {
  // Apply only if seq > snapshot seq for that host.
  const firstHost = delta.hosts[0];
  if (!firstHost) return false;
  const snapshotSeq = snapshotSeqs.get(firstHost.providerId) ?? 0;
  return delta.seq > snapshotSeq;
}

function applySnapshot(snapshot: Snapshot, snapshotSeqs: Map<string, number>): void {
  for (const host of snapshot.hosts) {
    snapshotSeqs.set(host.providerId, host.seq);
  }
}

describe('seq logic: buffer-then-filter', () => {
  it('applies delta when seq > snapshot seq', () => {
    const snapshotSeqs = new Map([['host1', 5]]);
    const delta: Delta = {
      type: 'control_fleet',
      seq: 10,
      hosts: [{ providerId: 'host1', seq: 10 }],
    };
    expect(applyDelta(delta, snapshotSeqs)).toBe(true);
  });

  it('discards delta when seq <= snapshot seq', () => {
    const snapshotSeqs = new Map([['host1', 10]]);
    const delta: Delta = {
      type: 'control_fleet',
      seq: 5,
      hosts: [{ providerId: 'host1', seq: 5 }],
    };
    expect(applyDelta(delta, snapshotSeqs)).toBe(false);
  });

  it('discards delta when seq equals snapshot seq', () => {
    const snapshotSeqs = new Map([['host1', 10]]);
    const delta: Delta = {
      type: 'control_fleet',
      seq: 10,
      hosts: [{ providerId: 'host1', seq: 10 }],
    };
    expect(applyDelta(delta, snapshotSeqs)).toBe(false);
  });

  it('updates snapshot seqs on snapshot apply', () => {
    const snapshotSeqs = new Map<string, number>();
    const snapshot: Snapshot = {
      type: 'control_fleet',
      seq: 0,
      hosts: [
        { providerId: 'host1', seq: 100 },
        { providerId: 'host2', seq: 50 },
      ],
    };
    applySnapshot(snapshot, snapshotSeqs);
    expect(snapshotSeqs.get('host1')).toBe(100);
    expect(snapshotSeqs.get('host2')).toBe(50);
  });

  it('handles missing snapshot seq (treats as 0)', () => {
    const snapshotSeqs = new Map<string, number>();
    const delta: Delta = {
      type: 'control_fleet',
      seq: 1,
      hosts: [{ providerId: 'host1', seq: 1 }],
    };
    // Without a snapshot, seq 1 > 0, so delta applies.
    expect(applyDelta(delta, snapshotSeqs)).toBe(true);
  });

  it('discards out-of-order delta after snapshot', () => {
    // Simulate: snapshot arrives at seq 10, then delta at seq 5 arrives.
    const snapshotSeqs = new Map<string, number>();
    const snapshot: Snapshot = {
      type: 'control_fleet',
      seq: 0,
      hosts: [{ providerId: 'host1', seq: 10 }],
    };
    applySnapshot(snapshot, snapshotSeqs);

    const delta: Delta = {
      type: 'control_fleet',
      seq: 5,
      hosts: [{ providerId: 'host1', seq: 5 }],
    };
    expect(applyDelta(delta, snapshotSeqs)).toBe(false);
  });
});
