import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { apiClient } from '@/api/client'
import type {
  IChatMessage,
  IConversation,
  IChatRequest,
  WsClientMessage,
  WsServerMessage,
} from '@/api/types'

function generateId(): string {
  return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`
}

export const useChatStore = defineStore('chat', () => {
  // --- State ---
  const conversations = ref<IConversation[]>([])
  const currentConversationId = ref<string | null>(null)
  const isLoading = ref(false)
  const isWsConnected = ref(false)
  const ws = ref<WebSocket | null>(null)
  const streamingSteps = ref<string[]>([])

  // --- Getters ---
  const currentConversation = computed<IConversation | undefined>(() => {
    return conversations.value.find((c) => c.id === currentConversationId.value)
  })

  const currentMessages = computed<IChatMessage[]>(() => {
    return currentConversation.value?.messages ?? []
  })

  // --- Actions ---

  /** Load all conversations from the server */
  async function loadConversations(): Promise<void> {
    try {
      const data = await apiClient.getConversations()
      conversations.value = data
    } catch (error) {
      console.error('Failed to load conversations:', error)
    }
  }

  /** Select a conversation by ID */
  function selectConversation(id: string): void {
    currentConversationId.value = id
    streamingSteps.value = []
  }

  /** Create a new empty conversation */
  function createConversation(): void {
    const newConversation: IConversation = {
      id: generateId(),
      title: '新对话',
      messages: [],
      created_at: new Date().toISOString(),
      updated_at: new Date().toISOString(),
    }
    conversations.value.unshift(newConversation)
    currentConversationId.value = newConversation.id
    streamingSteps.value = []
  }

  /** Send a message using REST API (fallback) */
  async function sendMessage(message: string, sources?: string[]): Promise<void> {
    if (!currentConversationId.value) {
      createConversation()
    }

    const conversationId = currentConversationId.value as string

    // Add user message
    const userMessage: IChatMessage = {
      id: generateId(),
      role: 'user',
      content: message,
      timestamp: new Date().toISOString(),
    }
    appendMessage(conversationId, userMessage)

    // Add placeholder assistant message
    const assistantMessage: IChatMessage = {
      id: generateId(),
      role: 'assistant',
      content: '',
      timestamp: new Date().toISOString(),
      status: 'pending',
    }
    appendMessage(conversationId, assistantMessage)

    isLoading.value = true

    try {
      const request: IChatRequest = {
        message,
        conversation_id: conversationId,
        sources,
      }
      const response = await apiClient.chat(request)

      // Update assistant message with response
      updateMessage(conversationId, assistantMessage.id, {
        content: response.message,
        matched_skill: response.matched_skill,
        routing_method: response.routing_method,
        confidence: response.confidence,
        task_id: response.task_id,
        status: response.status,
      })

      // Update conversation title from first message
      const conv = conversations.value.find((c) => c.id === conversationId)
      if (conv && conv.messages.length <= 2) {
        conv.title = message.length > 20 ? `${message.substring(0, 20)}...` : message
      }
    } catch (error) {
      updateMessage(conversationId, assistantMessage.id, {
        content: `请求失败: ${error instanceof Error ? error.message : '未知错误'}`,
        status: 'completed',
      })
    } finally {
      isLoading.value = false
    }
  }

  /** Send a message via WebSocket for streaming */
  function sendWsMessage(message: string, sources?: string[]): void {
    if (!currentConversationId.value) {
      createConversation()
    }

    const conversationId = currentConversationId.value as string

    // Add user message
    const userMessage: IChatMessage = {
      id: generateId(),
      role: 'user',
      content: message,
      timestamp: new Date().toISOString(),
    }
    appendMessage(conversationId, userMessage)

    // Add placeholder assistant message
    const assistantMessage: IChatMessage = {
      id: generateId(),
      role: 'assistant',
      content: '',
      timestamp: new Date().toISOString(),
      status: 'pending',
    }
    appendMessage(conversationId, assistantMessage)

    streamingSteps.value = []

    const wsMessage: WsClientMessage = {
      type: 'chat',
      message,
      sources,
      conversation_id: conversationId,
    }

    if (ws.value && ws.value.readyState === WebSocket.OPEN) {
      ws.value.send(JSON.stringify(wsMessage))
    } else {
      // Fallback to REST
      sendMessage(message, sources)
    }
  }

  /** Connect to WebSocket for real-time streaming */
  function connectWebSocket(): void {
    if (ws.value && ws.value.readyState === WebSocket.OPEN) {
      return
    }

    const socket = apiClient.createWebSocket()

    socket.onopen = () => {
      isWsConnected.value = true
      console.log('WebSocket connected')
    }

    socket.onmessage = (event: MessageEvent) => {
      try {
        const data = JSON.parse(event.data as string) as WsServerMessage
        handleWsMessage(data)
      } catch (error) {
        console.error('Failed to parse WebSocket message:', error)
      }
    }

    socket.onclose = () => {
      isWsConnected.value = false
      console.log('WebSocket disconnected')
      // Auto reconnect after 3 seconds
      setTimeout(() => {
        if (!ws.value || ws.value.readyState === WebSocket.CLOSED) {
          connectWebSocket()
        }
      }, 3000)
    }

    socket.onerror = (error) => {
      console.error('WebSocket error:', error)
      isWsConnected.value = false
    }

    ws.value = socket
  }

  /** Disconnect WebSocket */
  function disconnectWebSocket(): void {
    if (ws.value) {
      ws.value.close()
      ws.value = null
      isWsConnected.value = false
    }
  }

  // --- Internal helpers ---

  function handleWsMessage(data: WsServerMessage): void {
    const conversationId = currentConversationId.value
    if (!conversationId) return

    const conv = conversations.value.find((c) => c.id === conversationId)
    if (!conv) return

    const lastAssistantMsg = [...conv.messages]
      .reverse()
      .find((m) => m.role === 'assistant')

    switch (data.type) {
      case 'routing':
        if (lastAssistantMsg) {
          updateMessage(conversationId, lastAssistantMsg.id, {
            matched_skill: data.skill,
            confidence: data.confidence,
            routing_method: data.method,
          })
        }
        streamingSteps.value.push(`路由至: ${data.skill} (置信度: ${(data.confidence * 100).toFixed(1)}%)`)
        break

      case 'step':
        streamingSteps.value.push(data.step)
        break

      case 'result':
        if (lastAssistantMsg) {
          updateMessage(conversationId, lastAssistantMsg.id, {
            content: data.message,
            status: 'completed',
          })
        }
        isLoading.value = false
        streamingSteps.value = []
        break

      case 'error':
        if (lastAssistantMsg) {
          updateMessage(conversationId, lastAssistantMsg.id, {
            content: `错误: ${data.message}`,
            status: 'completed',
          })
        }
        isLoading.value = false
        streamingSteps.value = []
        break
    }
  }

  function appendMessage(conversationId: string, message: IChatMessage): void {
    const conv = conversations.value.find((c) => c.id === conversationId)
    if (conv) {
      conv.messages.push(message)
      conv.updated_at = new Date().toISOString()
    }
  }

  function updateMessage(
    conversationId: string,
    messageId: string,
    updates: Partial<IChatMessage>
  ): void {
    const conv = conversations.value.find((c) => c.id === conversationId)
    if (!conv) return
    const msg = conv.messages.find((m) => m.id === messageId)
    if (msg) {
      Object.assign(msg, updates)
    }
  }

  return {
    // State
    conversations,
    currentConversationId,
    isLoading,
    isWsConnected,
    streamingSteps,
    // Getters
    currentConversation,
    currentMessages,
    // Actions
    loadConversations,
    selectConversation,
    createConversation,
    sendMessage,
    sendWsMessage,
    connectWebSocket,
    disconnectWebSocket,
  }
})
