import { describe, it, expect, beforeEach, vi } from 'vitest'
import { useChatStore } from './chat-store'
import { ChatService } from '../../services/chat-service'
import { LLMService } from '../../services/llm-service'
import { db } from '../db'

describe('ChatStore', () => {
    beforeEach(async () => {
        await db.delete()
        await db.open()
        useChatStore.setState({ messages: [], isLoading: false })
    })

    it('should initialize with empty state', () => {
        const { messages, isLoading } = useChatStore.getState()
        expect(messages).toEqual([])
        expect(isLoading).toBe(false)
    })

    it('should hydrate from service', async () => {
        await ChatService.saveMessage({ role: 'user', content: 'Hi', timestamp: 1000 })

        await useChatStore.getState().hydrate()

        const { messages } = useChatStore.getState()
        expect(messages).toHaveLength(1)
        expect(messages[0].content).toBe('Hi')
    })

    it('should add message to store and service', async () => {
        // Mock LLMService streaming to prevent AI response
        vi.spyOn(LLMService, 'getTeacherResponseStream').mockResolvedValue(undefined)

        const spy = vi.spyOn(ChatService, 'saveMessage')

        await useChatStore.getState().addMessage('Hello', 'user')

        const { messages } = useChatStore.getState()
        // With LLM error, should still have user message + error message
        expect(messages.length).toBeGreaterThanOrEqual(1)
        expect(messages[0].content).toBe('Hello')
        expect(spy).toHaveBeenCalled()
        expect(spy.mock.calls[0][0]).toMatchObject({ content: 'Hello', role: 'user' })
    })

    it('should add AI response when user sends message', async () => {
        // Mock successful LLM streaming response
        vi.spyOn(LLMService, 'getTeacherResponseStream').mockImplementation(async (
            _input: string,
            _history: any[],
            callbacks: any
        ) => {
            // Simulate intent callback
            await callbacks.onIntent('venting')
            // Simulate token streaming
            await callbacks.onToken('I')
            await callbacks.onToken(' can')
            await callbacks.onToken(' help')
            await callbacks.onToken(' with')
            await callbacks.onToken(' that')
            await callbacks.onToken('!')
            // Simulate completion
            await callbacks.onComplete('I can help with that!')
        })

        await useChatStore.getState().addMessage('I am frustrated', 'user')

        const { messages, currentIntent, isProcessing } = useChatStore.getState()
        // Should have user message + AI response
        expect(messages.length).toBeGreaterThanOrEqual(2)
        expect(messages[0].content).toBe('I am frustrated')
        expect(messages[0].role).toBe('user')
        expect(messages[1].role).toBe('assistant')
        expect(messages[1].content).toBe('I can help with that!')
        expect(currentIntent).toBe('venting')
        expect(isProcessing).toBe(false)
    })
})
