import { useState, useEffect, useRef, useCallback } from 'react'
import { createWebSocketClient, ReadyState, type Result as WebSocketResult } from '@/app/api/websocket'
// import { createRequestClient, type RequestClient } from '@/api/request'
import { request } from '@/http/request'
import type { ApiEvent } from '../types'

export type { ApiEvent }

export interface PlatformConfig {
  wssUrl: string
  apiBaseUrl: string
  agentId: string
  agentName: string
}

interface UseNovaEventsOptions {
  mode: 'chat' | 'share'
  conversationId?: string
  platformConfig: PlatformConfig
  /** WebSocket 重连次数限制，默认 3 */
  reconnectLimit?: number
  /** WebSocket 重连间隔（毫秒），默认 3000 */
  reconnectInterval?: number
  /** 获取认证 Token */
  getToken?: () => string | undefined
  /** 获取租户 ID */
  getTenantId?: () => string | undefined
  /** 新事件回调 */
  onEvent?: (event: ApiEvent) => void
  /** 连接状态变化回调 */
  onConnectionChange?: (connected: boolean) => void
  /** 错误回调 */
  onError?: (error: Error) => void
}

interface UseNovaEventsResult {
  /** 原始事件列表 */
  rawEvents: ApiEvent[]
  /** 是否正在加载历史记录 */
  loading: boolean
  /** WebSocket 是否已连接 */
  connected: boolean
  /** WebSocket 连接状态 */
  readyState: ReadyState
  /** 错误信息 */
  error: Error | null
  /** 手动刷新历史记录 */
  refresh: () => Promise<void>
  /** 手动重连 WebSocket */
  reconnect: () => void
  /** 清空事件列表 */
  clear: () => void
  /** 切换会话 */
  switchConversation: (conversationId: string) => void
  /** 发送消息 */
  sendMessage: WebSocket['send']
}

function isApiEventLike(value: unknown): value is ApiEvent {
  return !!value && typeof value === 'object' && 'event_id' in value
}

function normalizeIncomingEvent(payload: unknown): ApiEvent | null {
  if (isApiEventLike(payload)) {
    return payload
  }

  if (
    payload &&
    typeof payload === 'object' &&
    'data' in payload &&
    isApiEventLike((payload as { data?: unknown }).data)
  ) {
    return (payload as { data: ApiEvent }).data
  }

  return null
}

/**
 * Nova 事件管理 Hook
 * 
 * 负责：
 * 1. 建立 WebSocket 连接接收实时事件
 * 2. 请求 event_list 接口获取历史记录
 * 3. 合并和管理事件列表
 */
export function useNovaEvents({
  mode,
  conversationId,
  platformConfig,
  reconnectLimit = 3,
  reconnectInterval = 3000,
  getToken,
  getTenantId,
  onEvent,
  onConnectionChange,
  onError,
}: UseNovaEventsOptions): UseNovaEventsResult {
  // 状态
  const [rawEvents, setRawEvents] = useState<ApiEvent[]>([])
  const [loading, setLoading] = useState(false)
  const [connected, setConnected] = useState(false)
  const [readyState, setReadyState] = useState<ReadyState>(ReadyState.Closed)
  const [error, setError] = useState<Error | null>(null)

  // Refs
  const wsClientRef = useRef<WebSocketResult | null>(null)
  const isUnmountedRef = useRef(false)
  const conversationIdRef = useRef(conversationId)
  const mountCountRef = useRef(0)

  // 保持 conversationId ref 同步
  conversationIdRef.current = conversationId

  // 回调 refs（避免重新创建 WebSocket）
  const onEventRef = useRef(onEvent)
  const onConnectionChangeRef = useRef(onConnectionChange)
  const onErrorRef = useRef(onError)

  onEventRef.current = onEvent
  onConnectionChangeRef.current = onConnectionChange
  onErrorRef.current = onError

  // 更新连接状态
  const updateConnected = useCallback((value: boolean) => {
    setConnected(value)
    onConnectionChangeRef.current?.(value)
  }, [])

  // 更新错误状态
  const updateError = useCallback((err: Error | null) => {
    setError(err)
    if (err) {
      onErrorRef.current?.(err)
    }
  }, [])

  // 合并事件到列表（按 event_id 去重，新事件替换旧事件）
  const mergeEvent = useCallback((newEvent: ApiEvent) => {
    setRawEvents(prev => {
      const index = prev.findIndex(e => e.event_id === newEvent.event_id)
      if (index === -1) {
        // 新事件，追加到末尾
        return [...prev, newEvent]
      }
      // 已存在，替换
      const updated = [...prev]
      updated[index] = newEvent
      return updated
    })
  }, [])

  // 批量合并事件（用于历史记录）
  const mergeEvents = useCallback((newEvents: ApiEvent[]) => {
    setRawEvents((prev) => {
      const eventsMap = new Map<string, ApiEvent>()
      
      // 先放入现有事件
      for (const event of prev) {
        eventsMap.set(event.event_id, event)
      }
      
      // 合并新事件（会覆盖同 id 的旧事件）
      for (const event of newEvents) {
        eventsMap.set(event.event_id, event)
      }
      
      return Array.from(eventsMap.values())
    })
  }, [])

  // 获取历史记录
  const fetchEventList = useCallback(async () => {
    if (!conversationIdRef.current) return

    setLoading(true)
    updateError(null)

    try {
      const payload = {
        conversation_id: conversationIdRef.current,
        page_no: 1,
        page_size: 3000,
      }

      const response = mode === 'share'
        ? await request.post<{
          data: {
            chat_event_list: ApiEvent[]
          }
        }>('/v1/super_agent/chat/event_list_share', payload)
        : await request.get<{
        data: {
          chat_event_list: ApiEvent[]
        }
      }>('/chat/event', payload)

      // 提取 data.data.chat_event_list 字段
      const events = response?.data?.chat_event_list || []

      if (!isUnmountedRef.current) {
        // 使用 mergeEvents 而不是直接 setRawEvents，以保留实时推送的新事件
        mergeEvents(events)
      }
    } catch (err) {
      if (!isUnmountedRef.current) {
        const error = err instanceof Error ? err : new Error('Failed to fetch event list')
        updateError(error)
      }
    } finally {
      if (!isUnmountedRef.current) {
        setLoading(false)
      }
    }
  }, [mergeEvents, updateError, mode])

  // 创建 WebSocket 连接
  const createWebSocket = useCallback(() => {
    if (!conversationIdRef.current) return
    
    // 已有连接，不重复创建
    if (wsClientRef.current) return

    // 构建 WebSocket URL
    const wsUrl = new URL(platformConfig.wssUrl)
    wsUrl.searchParams.set('conversation_id', conversationIdRef.current)

    const wsClient = createWebSocketClient(wsUrl.toString(), {
      reconnectLimit,
      reconnectInterval,
      manual: true, // 手动连接，避免 React Strict Mode 下的问题
      getToken,
      getTenantId,
      onOpen: () => {
        if (isUnmountedRef.current) return
        setReadyState(ReadyState.Open)
        updateConnected(true)
        updateError(null)
        
        // 连接成功后切换到当前会话
        if (conversationIdRef.current && wsClientRef.current) {
          wsClientRef.current.switchConversation(conversationIdRef.current)
        }
      },
      onClose: () => {
        if (isUnmountedRef.current) return
        setReadyState(ReadyState.Closed)
        updateConnected(false)
      },
      onError: () => {
        if (isUnmountedRef.current) return
        updateError(new Error('WebSocket connection error'))
      },
      onMessage: (message: ApiEvent) => {
        if (isUnmountedRef.current) return
        const normalizedEvent = normalizeIncomingEvent(message)
        if (!normalizedEvent) return

        mergeEvent(normalizedEvent)
        onEventRef.current?.(normalizedEvent)
      },
    })

    wsClientRef.current = wsClient
    
    // 手动触发连接
    wsClient.connect()
  }, [
    platformConfig.wssUrl,
    reconnectLimit,
    reconnectInterval,
    getToken,
    getTenantId,
    mergeEvent,
    updateConnected,
    updateError,
  ])

  // 手动重连
  const reconnect = useCallback(() => {
    if (wsClientRef.current) {
      wsClientRef.current.connect()
    } else {
      createWebSocket()
    }
  }, [createWebSocket])

  // 清空事件列表
  const clear = useCallback(() => {
    setRawEvents([])
  }, [])

  // 切换会话
  const switchConversation = useCallback((newConversationId: string) => {
    if (wsClientRef.current) {
      wsClientRef.current.switchConversation(newConversationId)
    }
  }, [])

  // 发送消息
  const sendMessage = useCallback<WebSocket['send']>((data) => {
    if (wsClientRef.current) {
      wsClientRef.current.sendMessage(data)
    } else {
      throw new Error('WebSocket not connected')
    }
  }, [])

  // 主 effect：当 conversationId 或 platformConfig 变化时处理
  useEffect(() => {
    isUnmountedRef.current = false
    console.log('conversationId', conversationId)
    // 无会话 ID 时清空
    if (!conversationId) {
      setRawEvents([])
      setConnected(false)
      setReadyState(ReadyState.Closed)
      return
    }

    // conversationId 存在，获取历史记录
    fetchEventList()
    
    // 如果已有连接且已打开，直接切换会话；否则创建新连接
    if (wsClientRef.current && wsClientRef.current.readyState === ReadyState.Open) {
      wsClientRef.current.switchConversation(conversationId)
    } else {
      createWebSocket()
    }

    // 清理函数
    return () => {
      isUnmountedRef.current = true
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [conversationId, platformConfig.wssUrl, platformConfig.apiBaseUrl])


  // 组件卸载时清理
  useEffect(() => {
    mountCountRef.current += 1
    const currentMount = mountCountRef.current
    
    return () => {
      // 延迟执行，如果 mountCount 变了说明重新 mount 了（Strict Mode），不清理
      setTimeout(() => {
        if (currentMount === mountCountRef.current && wsClientRef.current) {
          wsClientRef.current.cleanup()
          wsClientRef.current = null
        }
      }, 0)
    }
  }, [])
  return {
    rawEvents,
    loading,
    connected,
    readyState,
    error,
    refresh: fetchEventList,
    reconnect,
    clear,
    switchConversation,
    sendMessage,
  }
}

export { ReadyState }
export default useNovaEvents
