import { describe, expect, it, vi } from 'vitest';
import { streamOpenAIResponse } from '../../providers/openai/streamResponse';
const createStream = (events) => ({
    async *[Symbol.asyncIterator]() {
        for (const event of events) {
            yield event;
        }
    }
});
const createResponse = (events, finalOutput) => {
    return {
        toStream: () => createStream(events),
        finalOutput
    };
};
describe('streamResponse reasoning events', () => {
    it('invokes reasoning handler for reasoning output items', async () => {
        const reasoningId = 'rs_test_reasoning';
        const reasoningAdded = {
            type: 'raw_model_stream_event',
            data: {
                type: 'model',
                event: {
                    type: 'response.output_item.added',
                    sequence_number: 12,
                    output_index: 3,
                    item: {
                        id: reasoningId,
                        type: 'reasoning',
                        summary: []
                    }
                }
            }
        };
        const reasoningDone = {
            type: 'raw_model_stream_event',
            data: {
                type: 'model',
                event: {
                    type: 'response.output_item.done',
                    sequence_number: 13,
                    output_index: 3,
                    item: {
                        id: reasoningId,
                        type: 'reasoning',
                        summary: []
                    }
                }
            }
        };
        const onReasoningEvent = vi.fn().mockResolvedValue(undefined);
        const handlers = {
            onOutputTextDelta: vi.fn().mockResolvedValue(undefined),
            onMessageOutputCreated: vi.fn().mockResolvedValue(undefined),
            onToolCall: vi.fn().mockResolvedValue(undefined),
            onToolOutput: vi.fn().mockResolvedValue(undefined),
            onReasoningEvent
        };
        const response = createResponse([reasoningAdded, reasoningDone]);
        await streamOpenAIResponse(response, handlers);
        expect(onReasoningEvent).toHaveBeenCalledTimes(2);
        const firstCall = onReasoningEvent.mock.calls[0][0];
        expect(firstCall).toMatchObject({ id: reasoningId, phase: 'started', summary: [] });
        expect(typeof firstCall.timestamp).toBe('number');
        const secondCall = onReasoningEvent.mock.calls[1][0];
        expect(secondCall).toMatchObject({ id: reasoningId, phase: 'completed', summary: [] });
        expect(secondCall.timestamp).toBeGreaterThanOrEqual(firstCall.timestamp);
    });
});
describe('streamResponse message events', () => {
    it('invokes message handler for message output items', async () => {
        const messageId = 'msg_test_message';
        const messageAdded = {
            type: 'raw_model_stream_event',
            data: {
                type: 'model',
                event: {
                    type: 'response.output_item.added',
                    sequence_number: 5,
                    output_index: 1,
                    item: {
                        id: messageId,
                        type: 'message',
                        role: 'assistant',
                        status: 'in_progress',
                        content: []
                    }
                }
            }
        };
        const messageDone = {
            type: 'raw_model_stream_event',
            data: {
                type: 'model',
                event: {
                    type: 'response.output_item.done',
                    sequence_number: 6,
                    output_index: 1,
                    item: {
                        id: messageId,
                        type: 'message',
                        role: 'assistant',
                        status: 'completed',
                        content: [{ type: 'output_text', text: 'All done' }]
                    }
                }
            }
        };
        const onMessageEvent = vi.fn().mockResolvedValue(undefined);
        const handlers = {
            onOutputTextDelta: vi.fn().mockResolvedValue(undefined),
            onMessageOutputCreated: vi.fn().mockResolvedValue(undefined),
            onToolCall: vi.fn().mockResolvedValue(undefined),
            onToolOutput: vi.fn().mockResolvedValue(undefined),
            onReasoningEvent: vi.fn().mockResolvedValue(undefined),
            onMessageEvent
        };
        const response = createResponse([messageAdded, messageDone]);
        await streamOpenAIResponse(response, handlers);
        expect(onMessageEvent).toHaveBeenCalledTimes(2);
        const firstCall = onMessageEvent.mock.calls[0][0];
        expect(firstCall).toMatchObject({
            id: messageId,
            role: 'assistant',
            status: 'in_progress',
            phase: 'started'
        });
        expect(typeof firstCall.timestamp).toBe('number');
        const secondCall = onMessageEvent.mock.calls[1][0];
        expect(secondCall).toMatchObject({
            id: messageId,
            role: 'assistant',
            status: 'completed',
            phase: 'completed'
        });
        expect(secondCall.timestamp).toBeGreaterThanOrEqual(firstCall.timestamp);
        expect(secondCall.content).toEqual([{ type: 'output_text', text: 'All done' }]);
    });
});
describe('streamResponse final output handling', () => {
    it('invokes onFinalOutputAccessed before message output handler', async () => {
        const onFinalOutputAccessed = vi.fn().mockResolvedValue(undefined);
        const onMessageOutputCreated = vi.fn().mockResolvedValue(undefined);
        const messageEvent = {
            type: 'run_item_stream_event',
            name: 'message_output_created',
            item: {
                toJSON: () => ({
                    rawItem: {
                        type: 'message',
                        role: 'assistant',
                        content: [{ type: 'output_text', text: 'Final response text' }]
                    }
                })
            }
        };
        const handlers = {
            onOutputTextDelta: vi.fn().mockResolvedValue(undefined),
            onMessageOutputCreated,
            onToolCall: vi.fn().mockResolvedValue(undefined),
            onToolOutput: vi.fn().mockResolvedValue(undefined),
            onFinalOutputAccessed
        };
        const response = createResponse([messageEvent], 'Final response text');
        await streamOpenAIResponse(response, handlers);
        expect(onFinalOutputAccessed).toHaveBeenCalledTimes(1);
        expect(onFinalOutputAccessed).toHaveBeenCalledWith('Final response text');
        expect(onMessageOutputCreated).toHaveBeenCalledTimes(1);
        expect(onFinalOutputAccessed.mock.invocationCallOrder[0]).toBeLessThan(onMessageOutputCreated.mock.invocationCallOrder[0]);
    });
});
