import React, { useCallback, useEffect, useRef, useState } from 'react'
import { useLocation, useParams, useSearchParams } from 'react-router-dom'
import { Button } from '@heroui/react'
import { motion } from 'framer-motion'
import { useScroll } from 'ahooks'
import styles from './Chat.module.less'
import { processApiResponse } from './helper'
import { ChatWelcome } from './components/ChatWelcome'
import { ChatItemUser } from './components/ChatItem/ChatItemUser'
import { ChatAnswerBox } from './components/ChatItem/ChatAnswerBox'
import { trimSpacesOnly } from './components/ChatItem/markdownFormatter'
import { ChatEditor } from '@/components/ChatEditor'
import type { ChatRecord } from '@/types/chat'
import { fetchUserQaRecordPage } from '@/api/conversation'
import { fetchCheckTokenApi, fetchStreamResponse } from '@/api/chat'
import { fetchToolList } from '@/api/home'
import { clearCurrentToolId, clearShouldSendQuestion, fetchConversations, setCurrentToolId } from '@/store/conversationSlice'
import { getUserRolesForApi } from '@/lib/utils'
import type { RootState } from '@/store'
import { useAppDispatch, useAppSelector } from '@/store/hook'
import ScrollBtoIcon from '@/assets/svg/scrollBto.svg?react'
import { setIsAsking } from '@/store/chatSlice'
import SdreamLoading from '@/components/SdreamLoading'

export const Chat: React.FC = () => {
  const { id } = useParams<{ id: string }>()
  const location = useLocation()
  const [searchParams, setSearchParams] = useSearchParams()
  // 优先从 URL 查询参数读取 toolId（刷新后仍能保留），其次从 location.state 读取
  const rawToolIdFromUrl = searchParams.get('toolId')
  // 20251211 调试：记录进入聊天页时 URL 与 state 的 toolId 来源
  // eslint-disable-next-line no-console
  console.log('20251211 Chat url/state init', {
    rawToolIdFromUrl,
    locationState: location.state,
  })
  // 只有在非 SPA 导航（location.state 不存在）且链接携带 toolId 时才清空，避免影响站内点击历史记录
  const shouldForceClearUrlToolId = !location.state && Boolean(rawToolIdFromUrl)
  const toolIdFromUrl = shouldForceClearUrlToolId ? null : rawToolIdFromUrl
  // 添加调试日志，查看 location.state 的实际值
  // eslint-disable-next-line no-console
  console.log('20251211 [Chat] location.state:', location.state)
  const toolIdFromState = (location.state as { toolId?: string | null } | null)?.toolId
  // 优先使用 URL 中的 toolId，其次使用 state 中的 toolId
  const initialToolId = toolIdFromUrl !== null ? toolIdFromUrl : toolIdFromState
  // eslint-disable-next-line no-console
  console.log('20251211[Chat] initialToolId:', {
    fromUrl: toolIdFromUrl,
    fromState: toolIdFromState,
    final: initialToolId,
  })
  const [isLoading, setIsLoading] = useState(false)
  const [allItems, setAllItems] = useState<ChatRecord[]>([])
  const dispatch = useAppDispatch()
  const { shouldSendQuestion, currentToolId, conversations } = useAppSelector((state: RootState) => state.conversation)
  const scrollableRef = useRef<HTMLDivElement | any>(null)
  const position = useScroll(scrollableRef)
  const currentIdRef = useRef<string | undefined>(id)
  const lastSentQuestionRef = useRef<string>('')
  const abortControllerRef = useRef<AbortController | null>(null)
  const [currentToolName, setCurrentToolName] = useState<string | undefined>(undefined)
  // 使用 ref 保存从 location.state 传递的 toolId，避免被异步操作覆盖
  const toolIdFromStateRef = useRef<string | null | undefined>(undefined)

  // 当外部系统直接以 /chat/:id 链接进入（没有 location.state，且 URL 中也没有 toolId）时，
  // 视为一次新的会话入口：重置为通用模式，清除历史遗留的工具模式状态
  useEffect(() => {
    if (!location.state && !rawToolIdFromUrl) {
      // 20251211 调试：无 URL、无 state 时清除 toolId
      // eslint-disable-next-line no-console
      console.log('20251211 Chat clear toolId (no state & no url)')
      dispatch(clearCurrentToolId())
      // sessionStorage.removeItem('currentToolId')
    }
  }, [location.state, rawToolIdFromUrl, dispatch])
  // 若链接中带有 toolId，进入页面后强制清空（避免沿用历史链接参数）
  useEffect(() => {
    if (!shouldForceClearUrlToolId)
      return

    // 20251211 调试：URL 携带 toolId 且需要强制清空
    // eslint-disable-next-line no-console
    console.log('20251211 Chat force clear url toolId', {
      rawToolIdFromUrl,
      shouldForceClearUrlToolId,
    })

    // 1. 清除 Redux 中的 currentToolId
    dispatch(clearCurrentToolId())
    // 2. 清除 sessionStorage 中的 currentToolId
    // sessionStorage.removeItem('currentToolId')
    // 3. 清除 URL 中的 toolId 参数（如果存在）
    const currentUrl = new URL(window.location.href)
    if (currentUrl.searchParams.has('toolId')) {
      currentUrl.searchParams.delete('toolId')
      window.history.replaceState({}, '', currentUrl.toString())
    }
    // 4. 触发自定义事件，通知 ChatEditor 强制重置为通用模式
    window.dispatchEvent(new CustomEvent('forceResetToGeneralMode'))

    // 同步 react-router 的 searchParams 状态
    const newParams = new URLSearchParams(searchParams)
    newParams.delete('toolId')
    setSearchParams(newParams, { replace: true })
  }, [searchParams, setSearchParams, shouldForceClearUrlToolId, dispatch])
  // 调试用：展示当前页面链接与缓存中的 toolId
  const [debugInfo, setDebugInfo] = useState<{ href: string, sessionToolId: string | null }>({
    href: '',
    sessionToolId: null,
  })

  // 进入聊天页时，同步当前链接和缓存中的 toolId 到页面上展示
  useEffect(() => {
    try {
      const href = window.location.href
      const sessionToolId = sessionStorage.getItem('currentToolId')
      setDebugInfo({
        href,
        sessionToolId,
      })
    }
    catch (error) {
      console.error('同步页面链接与缓存信息失败:', error)
    }
  }, [])

  useEffect(() => {
    if (!debugInfo.href && !debugInfo.sessionToolId)
      return
    // eslint-disable-next-line no-console
    console.debug('[Chat] 当前链接 / 缓存 toolId:', debugInfo)
  }, [debugInfo])

  // 历史记录点击时将 toolId 通过路由 state 传入，优先使用该值快速同步高亮
  useEffect(() => {
    // 保存从 location.state 传递的 toolId 到 ref
    toolIdFromStateRef.current = initialToolId
    if (typeof initialToolId === 'undefined')
      return
    if (initialToolId) {
      // 统一转换为字符串，确保类型一致（真实API可能返回数字，需要转换为字符串）
      const normalizedToolId = String(initialToolId)
      // eslint-disable-next-line no-console
      console.log('[Chat] 从路由state设置toolId:', {
        originalToolId: initialToolId,
        originalType: typeof initialToolId,
        normalizedToolId,
        normalizedType: typeof normalizedToolId,
      })
      dispatch(setCurrentToolId(normalizedToolId))
    }
    else {
      dispatch(clearCurrentToolId())
    }
  }, [dispatch, initialToolId])

  /** 处理正常stream的数据 */
  const handleStreamMesageData = (msg: any, question: string) => {
    setAllItems((prevItems) => {
      const newItems = [...prevItems] // 创建数组的浅拷贝
      const lastIndex = newItems.length - 1
      if (lastIndex >= 0) {
        // 创建最后一项的新对象，合并现有数据和新的 answer
        const originalAnswer = (newItems[lastIndex].answerList?.[0]?.answer || '') + msg.content.data.answer
        // 移除所有括号及其内容
        let filteredAnswer = originalAnswer.replace(/\([^)]*\)/g, '')
        // 去除 [参考文档《任意内容》 《任意内容》...] 格式的内容
        filteredAnswer = filteredAnswer.replace(/\[参考文档(?:《[^》]*》\s*)+\]/g, '')
        // 只移除空格和制表符，保留换行符（避免移除末尾的 \n\n）
        filteredAnswer = trimSpacesOnly(filteredAnswer)

        newItems[lastIndex] = {
          ...newItems[lastIndex],
          question,
          answerList: [
            {
              ...msg.content.data,
              isShow: false,
              answer: filteredAnswer,
            },
          ],
        }
      }
      return newItems
    })
  }

  /** 处理超过最大条数的数据 */
  const handleChatMaxCount = (msg: any, question: string) => {
    // toast(t => (
    //   <div className="flex items-center">
    //     <p className="text-[14px]">⚠️ 超过最大轮数上限！请新建对话 👉🏻</p>
    // <Button
    //   color="primary"
    //   size="sm"
    //   variant="light"
    //   isIconOnly
    //   onClick={() => {
    //     dispatch(createConversation({
    //       conversationData: {},
    //       shouldNavigate: true,
    //       shouldSendQuestion: '',
    //     }))
    //     toast.dismiss(t.id)
    //   }}
    // >
    //   <AddNewChat />
    // </Button>
    //   </div>
    // ), {
    //   position: 'bottom-center',
    //   duration: 0,
    //   style: {
    //     marginBottom: '120px',
    //   },
    // })
    setAllItems((prevItems) => {
      const newItems = [...prevItems] // 创建数组的浅拷贝
      const lastIndex = newItems.length - 1
      if (lastIndex >= 0) {
        // 创建最后一项的新对象，合并现有数据和新的 answer
        newItems[lastIndex] = {
          ...newItems[lastIndex],
          question,
          answerList: [
            {
              ...msg.content.data,
              isShow: false,
              isChatMaxCount: true,
              endAnswerFlag: true,
              answer: '已达上限',
            },
          ],
        }
      }
      return newItems
    })
  }

  /** 提交问题 */
  const handleSubmitQuestion = async (question: string, productCode?: string, toolId?: string) => {
    // 优先读取缓存中的 toolId，再回退到传参或 Redux
    const sessionToolId = sessionStorage.getItem('currentToolId') ?? undefined
    const resolvedToolId = toolId ?? sessionToolId ?? currentToolId ?? undefined
    // 停止之前的请求
    if (abortControllerRef.current) {
      abortControllerRef.current.abort()
    }

    const isNew = allItems.length <= 1
    dispatch(setIsAsking(true))

    // 检查token
    await fetchCheckTokenApi()

    // 一次性添加用户问题和空的AI回答
    setAllItems(prevItems => [
      ...prevItems,
      {
        role: 'user',
        question,
      } as ChatRecord,
      {
        role: 'ai',
        answerList: [{ answer: '' }],
      } as ChatRecord,
    ])

    // 创建新的 AbortController
    abortControllerRef.current = new AbortController()

    let fetchUrl = `/conversation/api/conversation/mobile/v1/submit_question_stream`

    const viteOutputObj = import.meta.env.VITE_OUTPUT_OBJ || 'open'

    let proxy = ''
    if (viteOutputObj === 'open') {
      proxy = import.meta.env.MODE !== 'prod' ? '/api' : '/dev-sdream-api'
    }
 else {
      proxy = import.meta.env.MODE === 'dev' ? '/api' : '/dev-sdream-api'
    }

    fetchUrl = proxy + fetchUrl

    fetchStreamResponse(
      fetchUrl,
      {
        question,
        conversationId: currentIdRef.current,
        stream: true,
        productCode,
        toolId: resolvedToolId,
      },
      (msg) => {
        // 检查是否已被取消
        if (abortControllerRef.current?.signal.aborted) {
          return
        }

        // 处理错误
        if (msg?.type === 'ERROR') {
          // 如果是 AbortError，不显示错误
          if (msg.content?.name === 'AbortError') {
            return
          }
          return
        }

        // 正常的stream数据
        if (msg?.type === 'DATA' && msg?.content?.code === '00000000') {
          // eslint-disable-next-line no-console
          console.log('========================流式输出====================', msg)
          // eslint-disable-next-line no-console
          console.log('========================流式输出字符串====================', msg.content?.data)
          handleStreamMesageData(msg, question)
        }
        if (msg?.type === 'DATA' && msg?.content?.code === '01010005') {
          handleChatMaxCount(msg, question)
          return
        }
        if (msg.type === 'END') {
          if (isNew) {
            setTimeout(() => {
              dispatch(fetchConversations())
            }, 2000)
          }
        }
      },
      abortControllerRef.current.signal,
    )
  }

  /** 获取qa记录 */
  const getUserQaRecordPage = useCallback(async (conversationId: string) => {
    setIsLoading(true)
    try {
      // 检测是否从收藏页返回
      const fromCollect = location.state?.fromCollect
      // eslint-disable-next-line no-console
      console.log('[Chat] 开始获取历史记录:', conversationId)
      const res = await fetchUserQaRecordPage(conversationId)
      const qaRecords = res.data || []
      const messages = [{ role: 'system' } as ChatRecord, ...processApiResponse(qaRecords)]
      // 处理历史记录中的参考文档标记
      const processedMessages = messages.map((item) => {
        if (item.role === 'ai' && item.answerList?.[0]?.answer) {
          return {
            ...item,
            answerList: item.answerList.map(answerItem => ({
              ...answerItem,
              answer: answerItem.answer
                ?.replace(/\([^)]*\)/g, '')
                .replace(/\[参考文档(?:《[^》]*》\s*)+\]/g, '')
                .trim(),
            })),
          }
        }
        return item
      })
      setAllItems(processedMessages)
      // 优先从 qaRecords 中查找 toolId（这是实际使用的）
      const latestToolId = [...qaRecords].reverse().find(item => Boolean(item.toolId))?.toolId?.trim?.()
      const hasQaRecords = qaRecords.length > 0

      // 如果 qaRecords 中没有 toolId，尝试从 conversations 中查找当前会话的 toolId（会话级别）
      const conversationToolId = latestToolId || (conversations.find(conv => conv.conversationId === conversationId)?.toolId?.trim?.())

        // 优先使用从 location.state 传递的 toolId（如果存在），这是从历史记录点击传递过来的
      const toolIdFromState = toolIdFromStateRef.current !== undefined
        ? (toolIdFromStateRef.current ? String(toolIdFromStateRef.current) : null)
        : undefined

      // eslint-disable-next-line no-console
      console.log('[Chat] 从历史记录获取 toolId:', {
        conversationId,
        toolIdFromState,
        latestToolIdFromQaRecords: latestToolId,
        conversationToolId,
        hasQaRecords,
        currentToolIdInRedux: currentToolId,
      })

      // 确定最终使用的 toolId：优先使用从 location.state 传递的，其次使用 qaRecords 中的，最后使用 conversation 中的
      // 如果从 location.state 传递了 toolId，直接使用它（最高优先级）
      if (toolIdFromState !== undefined) {
        if (toolIdFromState) {
          // 只有当 Redux 中的 toolId 与最终确定的 toolId 不一致时，才更新
          if (currentToolId !== toolIdFromState) {
            // eslint-disable-next-line no-console
            console.log('[Chat] 使用从路由state传递的 toolId:', {
              from: currentToolId,
              to: toolIdFromState,
              source: 'location.state',
            })
            dispatch(setCurrentToolId(toolIdFromState))
            // 从收藏返回时，同步到 sessionStorage，避免 ChatEditor 清除 toolId
            if (fromCollect) {
              sessionStorage.setItem('currentToolId', toolIdFromState)
            }
          }
          else {
            // eslint-disable-next-line no-console
            console.log('[Chat] toolId 已一致，无需更新:', toolIdFromState)
            // 从收藏返回时，确保 sessionStorage 中有值
            if (fromCollect && !sessionStorage.getItem('currentToolId')) {
              sessionStorage.setItem('currentToolId', toolIdFromState)
            }
          }
        }
        else {
          // 如果从 location.state 传递的是 null，清除 toolId
          if (currentToolId) {
            // eslint-disable-next-line no-console
            console.log('[Chat] 清除 toolId (从路由state传递null)')
            dispatch(clearCurrentToolId())
          }
        }
        // 清除 ref，避免下次路由变化时误用
        toolIdFromStateRef.current = undefined
      }
      else {
        // 如果没有从 location.state 传递 toolId（可能是嵌套路由传递失败），使用原来的逻辑
        // 优先使用 qaRecords 中的 toolId，其次使用 conversation 中的 toolId
        const finalToolId = latestToolId || conversationToolId || undefined

        if (finalToolId) {
          // 只有当 Redux 中的 toolId 与最终确定的 toolId 不一致时，才更新
          if (currentToolId !== finalToolId) {
            // eslint-disable-next-line no-console
            console.log('[Chat] 更新 toolId (不一致):', {
              from: currentToolId,
              to: finalToolId,
              source: latestToolId ? 'qaRecords' : 'conversation',
            })
            dispatch(setCurrentToolId(finalToolId))
            // 从收藏返回时，同步到 sessionStorage，避免 ChatEditor 清除 toolId
            if (fromCollect) {
              sessionStorage.setItem('currentToolId', finalToolId)
            }
          }
          else {
            // eslint-disable-next-line no-console
            console.log('[Chat] toolId 已一致，无需更新:', finalToolId)
            // 从收藏返回时，确保 sessionStorage 中有值
            if (fromCollect && !sessionStorage.getItem('currentToolId')) {
              sessionStorage.setItem('currentToolId', finalToolId)
            }
          }
        }
        else {
          // 如果 qaRecords 和 conversation 中都没有 toolId
          // 如果有历史记录但没有 toolId，说明是通用模式，应该清除
          if (hasQaRecords && currentToolId) {
            // eslint-disable-next-line no-console
            console.log('[Chat] 清除 toolId (qaRecords 中有记录但没有 toolId，通用模式)')
            dispatch(clearCurrentToolId())
          }
          // 如果没有历史记录，可能是新会话，但如果 Redux 中已经有 toolId（从 HistoryBarList 设置的），暂时保留
          // 因为可能是刚点击历史记录但 API 还没返回，或者 location.state 传递失败但 Redux 中已有正确的值
          else if (!hasQaRecords && currentToolId) {
            // eslint-disable-next-line no-console
            console.log('[Chat] 没有历史记录，保留 Redux 中的 toolId (可能是 location.state 传递失败):', currentToolId)
            // 从收藏返回时，确保 sessionStorage 中有值
            if (fromCollect && !sessionStorage.getItem('currentToolId')) {
              sessionStorage.setItem('currentToolId', currentToolId)
            }
          }
        }
      }
    }
    catch {
      // 错误处理
    }
    finally {
      setIsLoading(false)
    }
  }, [dispatch, currentToolId, conversations, location.state])

  /** 点击滚动到底部 */
  const scrollToBottom = () => {
    scrollableRef.current.scrollTo(scrollableRef.current.scrollHeight, { behavior: 'smooth' })
  }

  useEffect(() => {
    if (id) {
      // 停止之前的请求
      if (abortControllerRef.current) {
        abortControllerRef.current.abort()
        dispatch(setIsAsking(false))
      }

      currentIdRef.current = id
      lastSentQuestionRef.current = '' // 重置标记
      getUserQaRecordPage(id)
    }
  }, [id])

  // 处理shouldSendQuestion的变化 - 自动发送问题
  useEffect(() => {
    if (
      shouldSendQuestion
      && currentIdRef.current
      && !isLoading
      && shouldSendQuestion !== lastSentQuestionRef.current
    ) {
      lastSentQuestionRef.current = shouldSendQuestion
      // 立即清除shouldSendQuestion，防止重复发送
      dispatch(clearShouldSendQuestion())
      // 确保历史记录加载完成后再发送问题
      setTimeout(() => {
        handleSubmitQuestion(shouldSendQuestion, undefined, currentToolId)
      }, 100)
    }
  }, [shouldSendQuestion, isLoading, currentToolId])

  // 根据 currentToolId 获取对应的 toolName
  useEffect(() => {
    const getToolNameFromToolId = async () => {
      if (currentToolId) {
        try {
          // 使用mock数据（已注释）
          // const res = await mockFetchToolList()
          // 真实API调用
          const userRoles = getUserRolesForApi()
          const res = await fetchToolList({ userRoles })
          if (res?.data) {
            const tool = res.data.find((t: any) => t.toolId === currentToolId)
            if (tool?.toolName) {
              setCurrentToolName(tool.toolName)
            }
          }
        }
        catch (error) {
          console.error('获取工具列表失败:', error)
        }
      }
      else {
        // 通用模式
        setCurrentToolName('通用模式')
      }
    }
    getToolNameFromToolId()
  }, [currentToolId])

  // 监听工具按钮点击事件，更新 ChatWelcome 提示语和 toolId
  useEffect(() => {
    const handleToolClickEvent = (event: CustomEvent) => {
      const { isToolBtn, toolId, toolName } = event.detail
      // 保存当前选择的 toolName
      setCurrentToolName(toolName)
      // 保存当前选择的 toolId 到 Redux
      if (!isToolBtn && toolId) {
        // 提质增效模式，保存 toolId
        dispatch(setCurrentToolId(toolId))
      }
      else {
        // 通用模式，清除 toolId
        dispatch(clearCurrentToolId())
      }
    }
    window.addEventListener('toolButtonClick', handleToolClickEvent as EventListener)
    return () => {
      window.removeEventListener('toolButtonClick', handleToolClickEvent as EventListener)
    }
  }, [dispatch])

  return (
    <div className={styles.scrollView}>
      <div className={`${styles.chatPage} relative`}>
        {/* <ChatSlogan />
        <ChatMaskBar /> */}
        <div className={`${styles.content}`}>
          {isLoading && (
            <div className="w-full h-full flex justify-center items-center">
              <SdreamLoading />
            </div>
          )}
          {!isLoading && (
            <motion.div
              ref={scrollableRef}
              initial={{ opacity: 0, y: -10 }}
              animate={{ opacity: 1, y: 0 }}
              transition={{
                duration: 0.3,
                opacity: { duration: 0.1 },
              }}
              className={`${styles.scrollable} scrollbar-hide scroll-smooth`}
            >
              <div className={styles.inter}>
                {allItems.map((record, index) => {
                  const recordId = record.answerList?.[0]?.recordId || record.groupId
                  const uniqueKey = recordId
                    ? `${record.role}-${recordId}`
                    : `${record.role}-${record.question || record.answerList?.[0]?.answer || ''}-${index}`
                  return (
                  <div
                    className="w-full chatItem mx-auto"
                    key={uniqueKey}
                  >
                    {record.role === 'system' && <ChatWelcome toolName={currentToolName} />}
                    {record.role === 'user' && <ChatItemUser record={record} />}
                    {record.role === 'ai' && (
                      <ChatAnswerBox
                        onSubmitQuestion={handleSubmitQuestion}
                        isLastAnswer={index === allItems.length - 1}
                        showIndex={0}
                        record={record}
                        index={index}
                      />
                    )}
                  </div>
                  )
                })}
              </div>
            </motion.div>
          )}
        </div>
        <div className="relative box-border px-[0] mx-auto iptContainer w-full flex-shrink-0 sm:px-0 pb-[18px]">
          <div className="absolute left-1/2 ml-[-20px] top-[-45px] sm:top-[-65px]">
            <motion.div
              initial="hidden"
              animate={(position?.top as number) < -20 ? 'visible' : 'hidden'}
              variants={{
                hidden: { opacity: 0, y: 20, pointerEvents: 'none' as const },
                visible: { opacity: 1, y: 0, pointerEvents: 'auto' as const },
              }}
              transition={{ duration: 0.3, ease: 'easeInOut' }}
            >
              <Button onPress={scrollToBottom} radius="full" isIconOnly color="primary">
                <ScrollBtoIcon />
              </Button>
            </motion.div>
          </div>
          <ChatEditor
            onSubmit={(question, toolId) => handleSubmitQuestion(question, undefined, toolId)}
            onToolClick={(isToolBtn, toolId, toolName, shouldChangeStyle) => {
            // 发送自定义事件到父组件
            window.dispatchEvent(new CustomEvent('toolButtonClick', {
              detail: { isToolBtn, toolId, toolName, shouldChangeStyle },
            }))
          }}
            placeholders={[]}
          />
          <div className="hidden sm:block w-full text-center mt-[12px] text-[#3333334d] text-[12px]">
            内容由AI模型生成，其准确性和完整性无法保证，仅供参考
          </div>
        </div>
      </div>
    </div>
  )
}
