import { describe, it, expect } from 'vitest';
import type { HostState } from '../fleet-state.js';

// Production never runs a reconnect state machine: a host is 'connected' when
// the SSE handshake/poll succeeds and 'down' when it drops (index.ts sets only
// those two). The 'reconnecting' state lives on the WS *connection* pill
// (ControlConnection in apps/web), not on per-host liveness. This pins that
// two-state model.
type Liveness = HostState['liveness'];

function transitionLiveness(_current: Liveness, event: 'connect' | 'disconnect'): Liveness {
  return event === 'connect' ? 'connected' : 'down';
}

function makeHost(liveness: Liveness, lastSeenAt: Date | null): HostState {
  return {
    providerId: 'test',
    liveness,
    lastSeenAt,
    seq: 0,
    inflightTotal: 0,
    models: new Map(),
  };
}

describe('liveness state machine', () => {
  it('starts as down', () => {
    expect(makeHost('down', null).liveness).toBe('down');
  });

  it('connect -> connected', () => {
    const state = makeHost('down', null);
    state.liveness = transitionLiveness(state.liveness, 'connect');
    expect(state.liveness).toBe('connected');
  });

  it('connected -> down on disconnect', () => {
    const state = makeHost('connected', new Date());
    state.liveness = transitionLiveness(state.liveness, 'disconnect');
    expect(state.liveness).toBe('down');
  });

  it('down -> connected on reconnect (no intermediate reconnecting state)', () => {
    const state = makeHost('down', null);
    state.liveness = transitionLiveness(state.liveness, 'connect');
    expect(state.liveness).toBe('connected');
  });
});
