import { useState, useCallback, useEffect, useRef, useMemo } from 'react'
import type {
  Command,
  ChatMessage,
  Topic,
  WsOutbound,
  AssistantResponse,
  ToolCall,
  ToolResult,
  ToolPending,
  SessionEstablished,
  SessionList,
  SessionSummary,
  TopicList,
  TopicSummary,
  TaskMessagesLoaded,
  TaskStarted,
  Attachment,
  MemorySummary,
  MemoryList,
  SkillSummary,
  SkillList,
  TodoItemSummary,
  TodoList,
  SchedulerJobList,
  SchedulerJobSummary,
  SchedulerJobSessionLookup,
  Channel,
  ChannelList,
} from '../types/protocol'

// 简化后的层级状态
interface UseChatReturn {
  // 连接状态
  connectionId: string | null
  isConnected: boolean

  // 简化的层级状态
  sessions: SessionSummary[]
  selectedSessionId: string | null
  session: SessionSummary | null
  sessionId: string | null
  chatId: string
  topics: Topic[]
  selectedTopic: string | null

  // 消息
  messages: ChatMessage[]
  isLoading: boolean

  // 通道状态
  channels: Channel[]
  selectedChannel: string
  isWritable: boolean

  // 是否只读
  isReadOnly: boolean

  // 子智能体视图
  subAgentView: SubAgentView | null

  // 方法
  handleMessage: (content: string, attachments?: Attachment[]) => void
  handleCommand: (command: Command) => void
  clearMessages: () => void
  handleServerMessage: (message: WsOutbound) => void

  // Topic 方法
  selectTopic: (topicId: string) => void
  createTopic: (title?: string) => Command
  switchTopic: (topicId: string) => Command
  deleteTopic: (topicId: string) => Command

  // 初始化方法
  requestSessionList: () => Command
  requestTopicList: () => Command | null
  topicRefreshTrigger: number
  requestChannelList: () => Command
  selectChannel: (channelId: string) => void
  selectSession: (sessionId: string) => void

  // 子智能体导航方法
  enterSubAgentView: (taskId: string, description: string) => Command
  exitSubAgentView: () => void

  // 记忆状态
  memories: MemorySummary[]
  requestMemoryList: () => Command
  createMemory: (namespace: string, key: string, content: string) => Command
  updateMemory: (id: string, content: string) => Command
  deleteMemory: (id: string) => Command

  // 技能状态
  skills: SkillSummary[]
  requestSkillList: () => Command

  // Todo 状态
  todos: TodoItemSummary[]
  requestTodoList: () => Command
  requestSubAgentTodoList: (subTaskId: string) => Command

  // 定时任务状态
  schedulerJobs: SchedulerJobSummary[]
  sidebarTab: 'topics' | 'scheduler'
  setSidebarTab: (tab: 'topics' | 'scheduler') => void
  requestSchedulerJobList: () => Command

  // 定时任务执行对话查看
  schedulerView: SchedulerJobView | null
  enterSchedulerJobView: (lookup: SchedulerJobSessionLookup, jobId: string, description: string) => Command
  exitSchedulerJobView: () => void

  // 停止当前 Agent 执行
  handleStop: () => Command
}

interface SubAgentView {
  taskId: string
  description: string
  subagentType: string
  status: string
  summary?: string
  messages: ChatMessage[]
}

interface SchedulerJobView {
  jobId: string
  description: string
  channel: string
  chatId: string
  messages: ChatMessage[]
}

const DEFAULT_CHAT_ID = 'default'

export function useChat(): UseChatReturn {
  const [messages, setMessages] = useState<ChatMessage[]>([])
  const [isLoading, setIsLoading] = useState(false)

  // 简化的状态管理
  const [connectionId, setConnectionId] = useState<string | null>(null)
  const [topics, setTopics] = useState<Topic[]>([])
  const [selectedTopic, setSelectedTopic] = useState<string | null>(null)
  const [topicRefreshTrigger, setTopicRefreshTrigger] = useState(0)
  const [sessions, setSessions] = useState<SessionSummary[]>([])
  const [selectedSessionId, setSelectedSessionId] = useState<string | null>(null)
  const [subAgentView, setSubAgentView] = useState<SubAgentView | null>(null)
  const [memories, setMemories] = useState<MemorySummary[]>([])
  const [skills, setSkills] = useState<SkillSummary[]>([])
  const [todos, setTodos] = useState<TodoItemSummary[]>([])
  const [schedulerJobs, setSchedulerJobs] = useState<SchedulerJobSummary[]>([])
  const [sidebarTab, setSidebarTab] = useState<'topics' | 'scheduler'>('topics')
  const [schedulerView, setSchedulerView] = useState<SchedulerJobView | null>(null)
  const [channels, setChannels] = useState<Channel[]>([])
  const [selectedChannel, setSelectedChannel] = useState<string>('websocket')

  // Message ID generator
  const messageIdCounter = useRef(0)
  const generateMessageId = () => {
    messageIdCounter.current += 1
    return `msg_${Date.now()}_${messageIdCounter.current}`
  }

  // Ref to track subAgentView and schedulerView for use in callbacks
  const subAgentViewRef = useRef<SubAgentView | null>(null)
  const schedulerViewRef = useRef<SchedulerJobView | null>(null)
  const topicsRef = useRef<Topic[]>([])
  const selectedTopicRef = useRef<string | null>(null)
  const pendingNewTopicRef = useRef(false)

  const isConnected = useMemo(() => connectionId !== null, [connectionId])
  const selectedSession = useMemo(
    () => sessions.find(s => s.session_id === selectedSessionId) ?? null,
    [sessions, selectedSessionId]
  )
  const sessionId = useMemo(() => selectedSession?.session_id ?? null, [selectedSession])
  const chatId = useMemo(() => sessionId ?? DEFAULT_CHAT_ID, [sessionId])
  const isWritable = useMemo(
    () => channels.find(c => c.id === selectedChannel)?.isWritable ?? false,
    [channels, selectedChannel]
  )

  // Extract subagent_task_id from a message if present
  const getSubagentTaskId = (message: WsOutbound): string | undefined => {
    if (message.type === 'tool_call' || message.type === 'tool_result'
        || message.type === 'tool_pending' || message.type === 'assistant_response') {
      return (message as ToolCall | ToolResult | ToolPending | AssistantResponse).subagent_task_id
    }
    return undefined
  }

  // Extract topic_id from a message if present
  const getTopicId = (message: WsOutbound): string | undefined => {
    if (message.type === 'tool_call' || message.type === 'tool_result'
        || message.type === 'tool_pending' || message.type === 'assistant_response') {
      return (message as ToolCall | ToolResult | ToolPending | AssistantResponse).topic_id
    }
    return undefined
  }

  // Convert a server message to ChatMessage (extracted from handleServerMessage logic)
  const serverMessageToChatMessage = (message: WsOutbound): ChatMessage | null => {
    switch (message.type) {
      case 'assistant_response': {
        const msg = message as AssistantResponse
        const role = msg.role === 'user' || msg.role === 'tool' ? msg.role : 'assistant'
        return {
          id: msg.id,
          role: role as ChatMessage['role'],
          content: msg.content,
          timestamp: (message as any).timestamp ?? Math.floor(Date.now() / 1000),
          type: 'message',
          attachments: msg.attachments,
          subagentTaskId: msg.subagent_task_id,
          reasoningContent: msg.reasoning_content,
        }
      }
      case 'tool_call': {
        const msg = message as ToolCall
        return {
          id: msg.id,
          role: 'tool',
          content: msg.content,
          timestamp: (message as any).timestamp ?? Math.floor(Date.now() / 1000),
          type: 'tool_call',
          toolName: msg.tool_name,
          toolCallId: msg.tool_call_id,
          arguments: msg.arguments,
          subagentTaskId: msg.subagent_task_id,
          reasoningContent: msg.reasoning_content,
        }
      }
      case 'tool_result': {
        const msg = message as ToolResult
        return {
          id: msg.id,
          role: 'tool',
          content: msg.content,
          timestamp: (message as any).timestamp ?? Math.floor(Date.now() / 1000),
          type: 'tool_result',
          toolName: msg.tool_name,
          toolCallId: msg.tool_call_id,
          subagentTaskId: msg.subagent_task_id,
          durationMs: msg.duration_ms,
        }
      }
      case 'tool_pending': {
        const msg = message as ToolPending
        return {
          id: msg.id,
          role: 'tool',
          content: `${msg.content}\n\n${msg.resume_hint}`,
          timestamp: (message as any).timestamp ?? Math.floor(Date.now() / 1000),
          type: 'tool_pending',
          toolName: msg.tool_name,
          toolCallId: msg.tool_call_id,
          subagentTaskId: msg.subagent_task_id,
        }
      }
      case 'error': {
        return {
          id: generateMessageId(),
          role: 'assistant',
          content: `Error: ${message.message}`,
          timestamp: (message as any).timestamp ?? Math.floor(Date.now() / 1000),
          type: 'message',
        }
      }
      default:
        return null
    }
  }

  // Append a server message to the sub-agent view
  const appendToSubAgentViewMessage = (message: WsOutbound) => {
    const chatMsg = serverMessageToChatMessage(message)
    if (chatMsg) {
      setSubAgentView((prev) =>
        prev
          ? { ...prev, messages: [...prev.messages, chatMsg] }
          : prev
      )
    }
  }

  const handleServerMessage = useCallback((message: WsOutbound) => {
    console.log('Received message:', message)

    // Route to scheduler job view if active
    const currentSchedulerView = schedulerViewRef.current
    if (currentSchedulerView) {
      // Route chat messages to the scheduler view
      const chatMsg = serverMessageToChatMessage(message)
      if (chatMsg) {
        setSchedulerView((prev) =>
          prev
            ? { ...prev, messages: [...prev.messages, chatMsg] }
            : prev
        )
        return
      }
      // Non-chat messages (session_list, topic_list, etc.) fall through to main handler
    }

    // Route to sub-agent view if active
    const currentSubAgentView = subAgentViewRef.current
    if (currentSubAgentView) {
      if (message.type === 'task_messages_loaded') {
        const msg = message as TaskMessagesLoaded
        setSubAgentView((prev) =>
          prev
            ? {
                ...prev,
                subagentType: msg.subagent_type,
                status: msg.status,
                summary: msg.summary,
              }
            : prev
        )
        return
      }

      // Only accept messages explicitly tagged with matching subagent_task_id.
      // History messages are now tagged by the backend (send_task_messages),
      // and live sub-agent messages are tagged by SubAgentEmitter.
      const msgSubagentTaskId = getSubagentTaskId(message)
      if (msgSubagentTaskId && msgSubagentTaskId === currentSubAgentView.taskId) {
        appendToSubAgentViewMessage(message)
        return
      }
      // 丢弃其他子智能体的消息，避免 fall through 到主消息处理
      if (msgSubagentTaskId) {
        return
      }
    }

    // In main view, skip sub-agent messages (they belong to sub-agent view).
    // But use the task_id to associate with the running task tool card.
    const msgSubagentTaskId = getSubagentTaskId(message)
    if (msgSubagentTaskId) {
      // 只 backfill 当前话题的 task tool_call，避免跨话题串扰
      const msgTopicId = getTopicId(message)
      if (msgTopicId && msgTopicId !== selectedTopicRef.current) return

      setMessages((prev) => {
        for (let i = prev.length - 1; i >= 0; i--) {
          if (prev[i].type === 'tool_call' && prev[i].toolName === 'task' && !prev[i].subagentTaskId) {
            const updated = [...prev]
            updated[i] = { ...updated[i], subagentTaskId: msgSubagentTaskId }
            return updated
          }
        }
        return prev
      })
      return
    }

    switch (message.type) {
      case 'session_established': {
        const msg = message as SessionEstablished
        setConnectionId(msg.session_id)
        console.log('Connection established:', msg.session_id)
        break
      }

      case 'task_started': {
        const msg = message as TaskStarted
        // 只 backfill 当前话题的 task tool_call，避免跨话题串扰
        if (msg.topic_id && msg.topic_id !== selectedTopicRef.current) break

        // 立即更新对应的 task tool_call，让用户可以点击查看实时进度
        setMessages((prev) => {
          for (let i = prev.length - 1; i >= 0; i--) {
            if (prev[i].type === 'tool_call' && prev[i].toolName === 'task' && !prev[i].subagentTaskId) {
              const updated = [...prev]
              updated[i] = { ...updated[i], subagentTaskId: msg.task_id }
              return updated
            }
          }
          return prev
        })
        break
      }

      case 'session_list': {
        const msg = message as SessionList
        console.log('Session list received:', msg)

        // 清空旧数据（切换通道时避免数据污染）
        setTopics([])
        setSelectedTopic(null)
        setMessages([])

        // 存储全部 session
        setSessions(msg.sessions)

        // 自动选中：优先保持当前选中，否则选第一个
        setSelectedSessionId(prev => {
          if (prev && msg.sessions.some(s => s.session_id === prev)) {
            return prev
          }
          return msg.sessions.length > 0 ? msg.sessions[0].session_id : null
        })

        setIsLoading(false)
        break
      }

      case 'session_created': {
        // 创建新 Topic 后更新列表
        setIsLoading(false)
        break
      }

      case 'session_loaded': {
        setIsLoading(false)
        break
      }

      case 'topic_list': {
        const msg = message as TopicList
        console.log('Topic list received:', msg)

        // 转换 topics 格式
        const newTopics: Topic[] = msg.topics.map((t: TopicSummary) => ({
          id: t.topic_id,
          session_id: t.session_id,
          title: t.title,
          description: t.description || undefined,
          message_count: Number(t.message_count),
          created_at: t.created_at,
          updated_at: t.last_active_at,
        }))
        setTopics(newTopics)

        // 新建话题后自动聚焦到新话题（列表按 last_active_at DESC 排序，第一个即最新）
        if (pendingNewTopicRef.current) {
          pendingNewTopicRef.current = false
          if (newTopics.length > 0) {
            setSelectedTopic(newTopics[0].id)
            setMessages([])
          }
        }

        setIsLoading(false)
        break
      }

      case 'assistant_response': {
        const msg = message as AssistantResponse
        // 按 topic_id 隔离：如果消息属于其他话题则丢弃
        if (msg.topic_id && msg.topic_id !== selectedTopicRef.current) return
        const role = msg.role === 'user' || msg.role === 'tool' ? msg.role : 'assistant'
        setMessages((prev) => [
          ...prev,
          {
            id: msg.id,
            role,
            content: msg.content,
            timestamp: (message as any).timestamp ?? Math.floor(Date.now() / 1000),
            type: 'message',
            attachments: msg.attachments,
            reasoningContent: msg.reasoning_content,
          },
        ])
        setIsLoading(false)

        // 当前话题无描述时，可能刚触发了异步生成，标记需要刷新
        const currentTopic = topicsRef.current.find(t => t.id === selectedTopicRef.current)
        if (currentTopic && !currentTopic.description) {
          setTopicRefreshTrigger(n => n + 1)
        }
        break
      }

      case 'tool_call': {
        const msg = message as ToolCall
        // 按 topic_id 隔离：如果消息属于其他话题则丢弃
        if (msg.topic_id && msg.topic_id !== selectedTopicRef.current) return
        setMessages((prev) => [
          ...prev,
          {
            id: msg.id,
            role: 'tool',
            content: msg.content,
            timestamp: (message as any).timestamp ?? Math.floor(Date.now() / 1000),
            type: 'tool_call',
            toolName: msg.tool_name,
            toolCallId: msg.tool_call_id,
            arguments: msg.arguments,
            subagentTaskId: msg.subagent_task_id,
            reasoningContent: msg.reasoning_content,
          },
        ])
        break
      }

      case 'tool_result': {
        const msg = message as ToolResult
        // 按 topic_id 隔离：如果消息属于其他话题则丢弃
        if (msg.topic_id && msg.topic_id !== selectedTopicRef.current) return
        setMessages((prev) => [
          ...prev,
          {
            id: msg.id,
            role: 'tool',
            content: msg.content,
            timestamp: (message as any).timestamp ?? Math.floor(Date.now() / 1000),
            type: 'tool_result',
            toolName: msg.tool_name,
            toolCallId: msg.tool_call_id,
            subagentTaskId: msg.subagent_task_id,
            durationMs: msg.duration_ms,
          },
        ])
        break
      }

      case 'tool_pending': {
        const msg = message as ToolPending
        // 按 topic_id 隔离：如果消息属于其他话题则丢弃
        if (msg.topic_id && msg.topic_id !== selectedTopicRef.current) return
        setMessages((prev) => [
          ...prev,
          {
            id: msg.id,
            role: 'tool',
            content: `${msg.content}\n\n${msg.resume_hint}`,
            timestamp: (message as any).timestamp ?? Math.floor(Date.now() / 1000),
            type: 'tool_pending',
            toolName: msg.tool_name,
            toolCallId: msg.tool_call_id,
          },
        ])
        break
      }

      case 'execution_cancelled': {
        setMessages((prev) => [
          ...prev,
          {
            id: generateMessageId(),
            role: 'assistant',
            content: (message as { type: 'execution_cancelled'; message: string }).message,
            timestamp: (message as any).timestamp ?? Math.floor(Date.now() / 1000),
            type: 'message',
          },
        ])
        setIsLoading(false)
        break
      }

      case 'error': {
        setMessages((prev) => [
          ...prev,
          {
            id: generateMessageId(),
            role: 'assistant',
            content: `Error: ${message.message}`,
            timestamp: (message as any).timestamp ?? Math.floor(Date.now() / 1000),
            type: 'message',
          },
        ])
        setIsLoading(false)
        break
      }

      case 'scheduler_job_list': {
        const msg = message as SchedulerJobList
        setSchedulerJobs(msg.jobs)
        break
      }
      case 'memory_list': {
        const msg = message as MemoryList
        setMemories(msg.memories)
        break
      }
      case 'skill_list': {
        const msg = message as SkillList
        setSkills(msg.skills)
        break
      }
      case 'todo_list': {
        const msg = message as TodoList
        setTodos(msg.todos)
        break
      }

      case 'channel_list': {
        const msg = message as ChannelList
        console.log('Channel list received:', msg)
        setChannels(msg.channels)
        break
      }
      case 'pong':
        // 忽略这些消息
        break
    }
  }, [])

  const handleMessage = useCallback((content: string, attachments?: Attachment[]) => {
    setMessages((prev) => [
      ...prev,
      {
        id: generateMessageId(),
        role: 'user',
        content,
        timestamp: Math.floor(Date.now() / 1000),
        type: 'message',
        attachments: attachments || [],
      },
    ])
    setIsLoading(true)
  }, [])

  const handleCommand = useCallback((command: Command) => {
    switch (command.type) {
      case 'create_session':
      case 'switch_topic':
      case 'load_topic':
      case 'list_sessions':
      case 'list_sessions_by_channel':
      case 'delete_topic':
      case 'list_topics':
        setIsLoading(true)
        break
    }
  }, [])

  const clearMessages = useCallback(() => {
    setMessages([])
  }, [])

  // Topic 操作方法
  const selectTopic = useCallback((topicId: string) => {
    setSelectedTopic(topicId)
    setMessages([])
    setSubAgentView(null)
  }, [])

  const createTopic = useCallback((title?: string): Command => {
    pendingNewTopicRef.current = true
    return {
      type: 'create_session',
      title: title || `话题 ${new Date().toLocaleString('zh-CN', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })}`,
    }
  }, [])

  const switchTopic = useCallback((topicId: string): Command => {
    return {
      type: 'switch_topic',
      topic_id: topicId,
    }
  }, [])

  const deleteTopic = useCallback((topicId: string): Command => {
    return {
      type: 'delete_topic',
      topic_id: topicId,
    }
  }, [])

  // 初始化方法
  const requestSessionList = useCallback((): Command => {
    return {
      type: 'list_sessions_by_channel',
      channel_name: selectedChannel,
      include_archived: false,
    }
  }, [selectedChannel])

  const requestChannelList = useCallback((): Command => {
    return { type: 'list_channels' }
  }, [])

  const selectChannel = useCallback((channelId: string) => {
    if (channelId === selectedChannel) return
    setSelectedChannel(channelId)
    setSessions([])
    setSelectedSessionId(null)
    setTopics([])
    setSelectedTopic(null)
    setMessages([])
    setSubAgentView(null)
    setIsLoading(true)
  }, [selectedChannel])

  const selectSession = useCallback((sessionId: string) => {
    if (sessionId === selectedSessionId) return
    setSelectedSessionId(sessionId)
    setTopics([])
    setSelectedTopic(null)
    setMessages([])
    setSubAgentView(null)
    setIsLoading(true)
  }, [selectedSessionId])

  const requestTopicList = useCallback((): Command | null => {
    if (!sessionId) return null
    return {
      type: 'list_topics',
      session_id: sessionId,
    }
  }, [sessionId])

  // Keep refs in sync with state
  useEffect(() => {
    subAgentViewRef.current = subAgentView
  }, [subAgentView])

  useEffect(() => {
    schedulerViewRef.current = schedulerView
  }, [schedulerView])

  useEffect(() => {
    topicsRef.current = topics
  }, [topics])

  useEffect(() => {
    selectedTopicRef.current = selectedTopic
  }, [selectedTopic])

  const enterSubAgentView = useCallback((taskId: string, description: string): Command => {
    const newView: SubAgentView = {
      taskId,
      description,
      subagentType: '',
      status: 'loading',
      messages: [],
    }
    // Sync ref immediately so WebSocket response routing works correctly
    subAgentViewRef.current = newView
    setSubAgentView(newView)
    return {
      type: 'load_task_messages',
      task_id: taskId,
    }
  }, [])

  const exitSubAgentView = useCallback(() => {
    subAgentViewRef.current = null
    setSubAgentView(null)
  }, [])

  // 记忆方法
  const requestMemoryList = useCallback((): Command => {
    return { type: 'list_memories' }
  }, [])

  const createMemory = useCallback((namespace: string, key: string, content: string): Command => {
    return { type: 'create_memory', namespace, key, content }
  }, [])

  const updateMemory = useCallback((id: string, content: string): Command => {
    return { type: 'update_memory', id, content }
  }, [])

  const deleteMemory = useCallback((id: string): Command => {
    return { type: 'delete_memory', id }
  }, [])

  const requestSkillList = useCallback((): Command => {
    return { type: 'list_skills' }
  }, [])

  const requestTodoList = useCallback((): Command => {
    return { type: 'list_todos' }
  }, [])

  const requestSubAgentTodoList = useCallback((subTaskId: string): Command => {
    return { type: 'list_todos', task_id: subTaskId }
  }, [])

  // 定时任务方法
  const requestSchedulerJobList = useCallback((): Command => {
    return { type: 'list_scheduler_jobs' }
  }, [])

  const enterSchedulerJobView = useCallback(
    (lookup: SchedulerJobSessionLookup, jobId: string, description: string): Command => {
      const newView: SchedulerJobView = {
        jobId,
        description,
        channel: lookup.channel,
        chatId: lookup.chat_id,
        messages: [],
      }
      schedulerViewRef.current = newView
      setSchedulerView(newView)
      return {
        type: 'load_chat_messages',
        channel: lookup.channel,
        chat_id: lookup.chat_id,
      }
    },
    []
  )

  const exitSchedulerJobView = useCallback(() => {
    schedulerViewRef.current = null
    setSchedulerView(null)
  }, [])

  const handleStop = useCallback((): Command => {
    return { type: 'stop_execution' }
  }, [])

  // Memoize messages: sub-agent view > scheduler view > main
  const resolvedMessages = useMemo(() => {
    if (subAgentView) {
      return subAgentView.messages
    }
    if (schedulerView) {
      return schedulerView.messages
    }
    return messages
  }, [subAgentView, schedulerView, messages])

  // 只读状态由当前通道决定
  const isReadOnly = !isWritable

  return {
    connectionId,
    isConnected,
    sessions,
    selectedSessionId,
    session: selectedSession,
    sessionId,
    chatId,
    topics,
    selectedTopic,
    messages: resolvedMessages,
    isLoading,
    isReadOnly,
    isWritable,
    channels,
    selectedChannel,
    subAgentView,
    handleMessage,
    handleCommand,
    clearMessages,
    handleServerMessage,
    selectTopic,
    createTopic,
    switchTopic,
    deleteTopic,
    requestSessionList,
    requestTopicList,
    topicRefreshTrigger,
    requestChannelList,
    selectChannel,
    selectSession,
    enterSubAgentView,
    exitSubAgentView,
    memories,
    requestMemoryList,
    createMemory,
    updateMemory,
    deleteMemory,
    skills,
    requestSkillList,
    todos,
    requestTodoList,
    requestSubAgentTodoList,
    schedulerJobs,
    sidebarTab,
    setSidebarTab,
    requestSchedulerJobList,
    schedulerView,
    enterSchedulerJobView,
    exitSchedulerJobView,
    handleStop,
  }
}
