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

import { buildGameEventChannel, type RealtimeEvent } from '@sammo-ts/common';
import { parseRealtimeEvent } from '../src/realtime/eventHub.js';
import { formatSseFrame } from '../src/realtime/sse.js';

describe('formatSseFrame', () => {
    it('renders basic SSE payloads', () => {
        const output = formatSseFrame({
            event: 'ping',
            id: '1',
            retry: 1500,
            data: 'ok',
        });

        expect(output).toBe(['event: ping', 'id: 1', 'retry: 1500', 'data: ok', ''].join('\n') + '\n');
    });

    it('splits multiline data', () => {
        const output = formatSseFrame({
            event: 'notice',
            data: 'first\nsecond',
        });

        expect(output).toBe(['event: notice', 'data: first', 'data: second', ''].join('\n') + '\n');
    });
});

describe('parseRealtimeEvent', () => {
    it('accepts valid realtime events', () => {
        const payload: RealtimeEvent = {
            type: 'turnCompleted',
            at: '2026-01-01T00:00:00.000Z',
            lastTurnTime: '2026-01-01T00:00:00.000Z',
        };
        const parsed = parseRealtimeEvent(JSON.stringify(payload));

        expect(parsed?.type).toBe('turnCompleted');
    });

    it('rejects invalid payloads', () => {
        expect(parseRealtimeEvent('not-json')).toBeNull();
        expect(parseRealtimeEvent(JSON.stringify({}))).toBeNull();
    });

    it('accepts the minimal tournament state wake-up', () => {
        expect(parseRealtimeEvent(JSON.stringify({ type: 'tournamentChanged' }))).toEqual({
            type: 'tournamentChanged',
        });
    });
});

describe('buildGameEventChannel', () => {
    it('namespaces channels by profile', () => {
        expect(buildGameEventChannel('che:default')).toBe('sammo:che:default:realtime:events');
    });
});
