import { useState, useEffect, useRef, useCallback } from 'react'
import { Message } from '../types'
import { api } from '../services/api'
import { logger } from '../utils/logger'
import { isNotificationLikeMessage, isMessageFromSelf } from '../utils/messageTypes'

export function useMessages(
  token: string,
  currentUserId: number | null,
  activeContactId: number | null,
  setContacts: React.Dispatch<React.SetStateAction<any[]>>,
  unreadCountsRef: React.MutableRefObject<Record<number, number>>
) {
  const [messages, setMessages] = useState<Record<number, Message[]>>({})
  const [loadedContacts, setLoadedContacts] = useState<Set<number>>(new Set())
  const [isLoadingMessages, setIsLoadingMessages] = useState(false)
  const [isLoadingMore, setIsLoadingMore] = useState(false)
  const [hasMoreMessages, setHasMoreMessages] = useState<Record<number, boolean>>({})
  const [uploadProgress, setUploadProgress] = useState<{ [key: string]: number }>({})
  const isLoadingMoreRef = useRef(false)

  // 退出登录或切换账号时清空内存中的会话消息，避免同一 contactId 跨账号串数据
  useEffect(() => {
    if (!token) {
      setMessages({})
      setLoadedContacts(new Set())
      setHasMoreMessages({})
      setUploadProgress({})
      isLoadingMoreRef.current = false
      setIsLoadingMessages(false)
      setIsLoadingMore(false)
      return
    }
    setMessages({})
    setLoadedContacts(new Set())
    setHasMoreMessages({})
    setUploadProgress({})
    isLoadingMoreRef.current = false
    setIsLoadingMore(false)
  }, [token, currentUserId])

  const formatMessageData = useCallback((msg: any): Message => {
    const notificationLike = isNotificationLikeMessage(msg.type, msg.content_type)
    const isSelf = isMessageFromSelf(msg, currentUserId)

    let messageType: 'text' | 'image' | 'file' | 'video' | 'notification' = 'text'
    if (notificationLike) {
      messageType = 'notification'
    } else if (msg.content_type === 'IMAGE') {
      messageType = 'image'
    } else if (msg.content_type === 'VIDEO') {
      messageType = 'video'
    } else if (msg.content_type === 'FILE') {
      messageType = 'file'
    }

    return {
      id: msg.id,
      content: msg.content || msg.title || '',
      isSelf: isSelf,
      type: messageType,
      timestamp: new Date(msg.created_at).getTime(),
      title: msg.title,
      actionUrl: msg.action_url,
      actionText: msg.action_text,
      messageType: msg.type,
      content_type: msg.content_type,
      size: (msg as any).size
    }
  }, [currentUserId])

  // 拉取该会话最新一页；切换会话时也会调用，并与本地已加载的更早历史、未入库的本地消息合并
  const refreshMessages = useCallback(async (contactId: number) => {
    if (!token) return

    setIsLoadingMessages(true)
    try {
      const messagesData = await api.getMessages(token, contactId, {
        skip: 0,
        limit: 50
      })

      logger.info('App: Refreshed messages', { contactId, count: messagesData.length })

      const formattedMessages: Message[] = messagesData.map(formatMessageData)
      formattedMessages.sort((a, b) => a.timestamp - b.timestamp)

      setMessages(prev => {
        const existing = prev[contactId] || []
        if (formattedMessages.length === 0) {
          return { ...prev, [contactId]: existing }
        }
        const serverIds = new Set(formattedMessages.map(m => m.id))
        const oldestFetched = formattedMessages[0].timestamp
        const preservedOlder = existing.filter(
          m => !serverIds.has(m.id) && m.timestamp < oldestFetched
        )
        const pendingLocal = existing.filter(
          m => !serverIds.has(m.id) && m.timestamp >= oldestFetched
        )
        const merged = [...preservedOlder, ...formattedMessages, ...pendingLocal].sort(
          (a, b) => a.timestamp - b.timestamp
        )
        return { ...prev, [contactId]: merged }
      })

      setHasMoreMessages(prev => ({
        ...prev,
        [contactId]: messagesData.length >= 50
      }))

      setLoadedContacts(prev => new Set(prev).add(contactId))
    } catch (error: any) {
      logger.error('App: Failed to refresh messages', { contactId, error: error.message })
    } finally {
      setIsLoadingMessages(false)
    }
  }, [token, formatMessageData])

  const fetchMoreMessages = useCallback(async (contactId: number) => {
    if (!token || isLoadingMoreRef.current || !hasMoreMessages[contactId]) return

    const currentMessages = messages[contactId] || []
    const skip = currentMessages.length

    isLoadingMoreRef.current = true
    setIsLoadingMore(true)
    try {
      const messagesData = await api.getMessages(token, contactId, {
        skip,
        limit: 50
      })

      logger.info('App: Fetched more messages', { contactId, skip, count: messagesData.length })

      setHasMoreMessages(prev => ({
        ...prev,
        [contactId]: messagesData.length >= 50
      }))

      if (messagesData.length === 0) return

      const formattedMessages: Message[] = messagesData.map(formatMessageData)
      formattedMessages.sort((a, b) => a.timestamp - b.timestamp)

      const existingIds = new Set(currentMessages.map(m => m.id))
      const newMessages = formattedMessages.filter(m => !existingIds.has(m.id))

      setMessages(prev => ({
        ...prev,
        [contactId]: [...newMessages, ...(prev[contactId] || [])]
      }))
    } catch (error: any) {
      logger.error('App: Failed to fetch more messages', { contactId, error: error.message })
    } finally {
      isLoadingMoreRef.current = false
      setIsLoadingMore(false)
    }
  }, [token, messages, hasMoreMessages, formatMessageData])

  // 发送文本消息
  const sendMessage = useCallback(async (content: string, contactId: number) => {
    if (!content.trim() || !contactId) return
    
    const tempMessageId = Date.now()
    const tempMessage: Message = {
      id: tempMessageId,
      content: content.trim(),
      isSelf: true,
      type: 'text',
      timestamp: Date.now()
    }

    setMessages(prev => ({
      ...prev,
      [contactId]: [...(prev[contactId] || []), tempMessage]
    }))

    setContacts(prev => prev.map(c => 
      c.id === contactId 
        ? { ...c, lastMessage: content.trim(), lastMessageTime: '刚刚' } 
        : c
    ))

    try {
      const response = await api.sendMessage(token, contactId, content.trim(), 'TEXT')
      logger.info('App: Message sent successfully', { content, receiverId: contactId, messageId: response.id })
      
      let messageType: 'text' | 'image' | 'file' | 'video' | 'notification' = 'text'
      if (isNotificationLikeMessage(response.type, response.content_type)) {
        messageType = 'notification'
      } else if (response.content_type === 'IMAGE') {
        messageType = 'image'
      } else if (response.content_type === 'VIDEO') {
        messageType = 'video'
      } else if (response.content_type === 'FILE') {
        messageType = 'file'
      }
      
      const realMessage: Message = {
        id: response.id,
        content: response.content,
        isSelf: true,
        type: messageType,
        timestamp: new Date(response.created_at).getTime(),
        messageType: response.type,
        content_type: response.content_type,
        title: response.title,
        actionUrl: response.action_url,
        actionText: response.action_text
      }
      
      setMessages(prev => ({
        ...prev,
        [contactId]: (prev[contactId] || [])
          .filter(msg => msg.id !== tempMessageId)
          .concat(realMessage)
      }))
    } catch (error: any) {
      logger.error('App: Failed to send message', { error: error.message, receiverId: contactId })
      setMessages(prev => ({
        ...prev,
        [contactId]: (prev[contactId] || []).filter(msg => msg.id !== tempMessageId)
      }))
      throw error
    }
  }, [token, setContacts])

  // 发送文件消息
  const sendFileMessage = useCallback(async (file: File, contentType: 'IMAGE' | 'VIDEO' | 'FILE' = 'FILE', contactId: number) => {
    if (!contactId || !token) return
    
    const fileId = `${Date.now()}-${file.name}`
    
    try {
      setUploadProgress(prev => ({ ...prev, [fileId]: 0 }))
      
      const uploadResult = await api.uploadFile(
        token,
        file,
        (percent) => {
          setUploadProgress(prev => ({ ...prev, [fileId]: percent }))
        }
      )
      
      const messageResponse = await api.sendMessage(
        token,
        contactId,
        uploadResult.key,
        contentType,
        file.name
      )
      
      const newMessage: Message = {
        id: messageResponse.id,
        content: messageResponse.content,
        isSelf: true,
        type: contentType.toLowerCase() as 'image' | 'file' | 'video',
        timestamp: new Date(messageResponse.created_at).getTime(),
        title: messageResponse.title || file.name,
        content_type: contentType,
        size: uploadResult.size
      }
      
      setMessages(prev => ({
        ...prev,
        [contactId]: [...(prev[contactId] || []), newMessage]
      }))
      
      setUploadProgress(prev => {
        const newProgress = { ...prev }
        delete newProgress[fileId]
        return newProgress
      })
      
      logger.info('File message sent', { messageId: messageResponse.id, contentType })
    } catch (error: any) {
      logger.error('Send file message failed', error)
      setUploadProgress(prev => {
        const newProgress = { ...prev }
        delete newProgress[fileId]
        return newProgress
      })
      throw error
    }
  }, [token])

  // 切换到某个会话时，清除该会话的本地未读计数
  useEffect(() => {
    if (activeContactId) {
      unreadCountsRef.current[activeContactId] = 0
      setContacts(prev => prev.map(c =>
        c.id === activeContactId ? { ...c, unreadCount: 0 } : c
      ))
      if (window.electron && window.electron.ipcRenderer) {
        window.electron.ipcRenderer.send('clear-unread', activeContactId)
      }
    }
  }, [activeContactId, setContacts, unreadCountsRef])

  // 切换联系人时重新拉取该会话最新消息（含再次进入已打开过的会话）
  useEffect(() => {
    if (activeContactId && token) {
      void refreshMessages(activeContactId)
    }
  }, [activeContactId, token, refreshMessages])

  return {
    messages,
    setMessages,
    isLoadingMessages,
    isLoadingMore,
    hasMoreMessages,
    uploadProgress,
    sendMessage,
    sendFileMessage,
    fetchMessages: refreshMessages,
    fetchMoreMessages,
    loadedContacts
  }
}
