import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import {
  type WsFrame,
} from '@boocode/contracts/ws-frames';
import { createBroker } from '../broker.js';

const VALID_UUID_A = '00000000-0000-0000-0000-000000000001';
const VALID_UUID_B = '00000000-0000-0000-0000-000000000002';
const VALID_TIMESTAMP = '2026-05-22T14:30:00.000Z';

describe('broker.publishFrame / publishUserFrame fail-closed behavior', () => {
  let logErrors: Array<{ obj: unknown; msg: string }>;
  let mockLog: Parameters<typeof createBroker>[0];

  beforeEach(() => {
    logErrors = [];
    mockLog = {
      error: (obj: unknown, msg: string) => {
        logErrors.push({ obj, msg });
      },
      info: () => {},
      warn: () => {},
      debug: () => {},
      trace: () => {},
      fatal: () => {},
      child: () => mockLog as never,
      level: 'info',
      silent: () => {},
    } as unknown as Parameters<typeof createBroker>[0];
  });

  afterEach(() => {
    vi.restoreAllMocks();
  });

  it('publishFrame delivers a valid frame to subscribers', () => {
    const broker = createBroker(mockLog);
    const received: WsFrame[] = [];
    broker.subscribe('sess-1', (f) => received.push(f as WsFrame));
    broker.publishFrame('sess-1', {
      type: 'delta',
      message_id: VALID_UUID_A,
      chat_id: VALID_UUID_B,
      content: 'hello',
    });
    expect(received).toHaveLength(1);
    expect((received[0] as { type: string }).type).toBe('delta');
    expect(logErrors).toHaveLength(0);
  });

  it('publishFrame drops + logs an invalid frame instead of delivering it', () => {
    const broker = createBroker(mockLog);
    const received: WsFrame[] = [];
    broker.subscribe('sess-1', (f) => received.push(f as WsFrame));
    broker.publishFrame('sess-1', {
      type: 'delta',
      message_id: 'not-a-uuid',
      content: 'hello',
    } as never);
    expect(received).toHaveLength(0);
    expect(logErrors).toHaveLength(1);
    expect(logErrors[0]!.msg).toMatch(/ws-frame-validation-failed/);
  });

  it('publishUserFrame drops + logs an invalid user-channel frame', () => {
    const broker = createBroker(mockLog);
    const received: WsFrame[] = [];
    broker.subscribeUser('default', (f) => received.push(f as WsFrame));
    broker.publishUserFrame('default', {
      type: 'chat_status',
      chat_id: VALID_UUID_A,
      status: 'working', // v1.12.1 dropped this enum value
      at: VALID_TIMESTAMP,
    } as never);
    expect(received).toHaveLength(0);
    expect(logErrors).toHaveLength(1);
  });

  it('publishFrame validation failure does not throw (no cascade into stream-phase)', () => {
    const broker = createBroker(mockLog);
    expect(() =>
      broker.publishFrame('sess-1', { type: 'unknown_type' } as never),
    ).not.toThrow();
  });
});
