import { describe, it, expect, beforeEach } from 'vitest';
import {
  registerSSEClient,
  unregisterSSEClient,
  setSyncDocument,
  setSyncSelection,
  markClientActive,
  getLastActiveClientId,
  isClientConnected,
  sendToClient,
  clearSyncState,
} from '../utils/mcp-sync-state';
import type { PenDocument } from '../../src/types/pen';

describe('mcp-sync-state: active client tracking', () => {
  beforeEach(() => {
    clearSyncState();
  });

  it('getLastActiveClientId returns null initially', () => {
    expect(getLastActiveClientId()).toBeNull();
  });

  it('setSyncDocument updates lastActiveClientId when sourceClientId provided', () => {
    registerSSEClient('client-a', { push: () => {} });
    setSyncDocument({ version: '1.0.0', children: [] } as PenDocument, 'client-a');
    expect(getLastActiveClientId()).toBe('client-a');
  });

  it('setSyncSelection updates lastActiveClientId', () => {
    registerSSEClient('client-b', { push: () => {} });
    setSyncSelection(['node-1'], 'page-1', 'client-b');
    expect(getLastActiveClientId()).toBe('client-b');
  });

  it('markClientActive updates lastActiveClientId only for connected clients', () => {
    registerSSEClient('client-c', { push: () => {} });
    markClientActive('client-c');
    expect(getLastActiveClientId()).toBe('client-c');
    markClientActive('client-nonexistent');
    expect(getLastActiveClientId()).toBe('client-c');
  });

  it('isClientConnected reflects registration state', () => {
    registerSSEClient('client-d', { push: () => {} });
    expect(isClientConnected('client-d')).toBe(true);
    unregisterSSEClient('client-d');
    expect(isClientConnected('client-d')).toBe(false);
  });

  it('sendToClient dispatches payload to a specific client', () => {
    const received: string[] = [];
    registerSSEClient('client-e', { push: (data: string) => received.push(data) });
    const ok = sendToClient('client-e', { type: 'screenshot:request' });
    expect(ok).toBe(true);
    expect(received).toHaveLength(1);
    expect(JSON.parse(received[0]).type).toBe('screenshot:request');
  });

  it('sendToClient returns false for unknown client', () => {
    expect(sendToClient('nope', { type: 'x' })).toBe(false);
  });

  it('broadcasts document updates to other clients and prunes broken writers', () => {
    const received: string[] = [];
    registerSSEClient('client-source', { push: () => {} });
    registerSSEClient('client-target', { push: (data: string) => received.push(data) });
    registerSSEClient('client-broken', {
      push: () => {
        throw new Error('writer closed');
      },
    });

    setSyncDocument({ version: '1.0.0', children: [] } as PenDocument, 'client-source');

    expect(received).toHaveLength(1);
    expect(JSON.parse(received[0]).type).toBe('document:update');
    expect(isClientConnected('client-source')).toBe(true);
    expect(isClientConnected('client-target')).toBe(true);
    expect(isClientConnected('client-broken')).toBe(false);
  });
});
