import {
  parseCitationsData,
  parseStatusData,
  parseVersionedFrame,
} from './wsFrames';

describe('wsFrames', () => {
  it('parses a citations frame', () => {
    const raw = JSON.stringify({
      v: 1,
      type: 'citations',
      data: [
        {
          index: 1,
          title: 'Example',
          url: 'https://example.com',
          published_at: '2026-07-03',
        },
      ],
    });
    const frame = parseVersionedFrame(raw);
    expect(frame).toEqual({
      v: 1,
      type: 'citations',
      data: [
        {
          index: 1,
          title: 'Example',
          url: 'https://example.com',
          published_at: '2026-07-03',
        },
      ],
    });
    expect(parseCitationsData(frame!.data)).toHaveLength(1);
  });

  it('ignores unknown types without throwing', () => {
    const frame = parseVersionedFrame(
      JSON.stringify({ v: 1, type: 'status', data: { stage: 'search' } }),
    );
    expect(frame?.type).toBe('status');
  });

  it('returns null for sentinels and plain text', () => {
    expect(parseVersionedFrame('END_OF_THE_STREAM_ENDER_GAME_42')).toBeNull();
    expect(parseVersionedFrame('hello world')).toBeNull();
  });

  it('returns empty citations for bad data', () => {
    expect(parseCitationsData(null)).toEqual([]);
    expect(parseCitationsData('nope')).toEqual([]);
  });

  it('parses a status frame', () => {
    const raw = JSON.stringify({
      v: 1,
      type: 'status',
      data: { stage: 'searching', label: 'Searching the web', detail: 'query: cats' },
    });
    const frame = parseVersionedFrame(raw);
    expect(frame?.type).toBe('status');
    expect(parseStatusData(frame!.data)).toEqual({
      stage: 'searching',
      label: 'Searching the web',
      detail: 'query: cats',
    });
  });

  it('parses status data with no detail as null', () => {
    expect(parseStatusData({ stage: 'writing', label: 'Writing the answer' })).toEqual({
      stage: 'writing',
      label: 'Writing the answer',
      detail: null,
    });
  });

  it('passes through unknown/future stage values verbatim', () => {
    expect(
      parseStatusData({ stage: 'some_future_stage', label: 'Doing something new' }),
    ).toEqual({
      stage: 'some_future_stage',
      label: 'Doing something new',
      detail: null,
    });
  });

  it('returns null for malformed status data without throwing', () => {
    expect(parseStatusData(null)).toBeNull();
    expect(parseStatusData(undefined)).toBeNull();
    expect(parseStatusData('nope')).toBeNull();
    expect(parseStatusData([])).toBeNull();
    expect(parseStatusData({})).toBeNull();
    expect(parseStatusData({ stage: 'searching' })).toBeNull();
    expect(parseStatusData({ label: 'Searching the web' })).toBeNull();
    expect(parseStatusData({ stage: 123, label: 'Searching' })).toBeNull();
    expect(parseStatusData({ stage: 'searching', label: 42 })).toBeNull();
  });
});
