// 问答功能独立聊天页
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useLocation, useNavigate, useParams, useSearchParams } from 'react-router-dom'
import { useLocalStorageState, useScroll } from 'ahooks'
import { Button } from '@heroui/react'
import { motion } from 'framer-motion'
import styles from '../Chat/Chat.module.less'
import { processApiResponse } from '../Chat/helper'
import { ChatItemUser } from '../Chat/components/ChatItem/ChatItemUser'
import { ChatAnswerBox } from '../Chat/components/ChatItem/ChatAnswerBox'
import { TacticsWelcome } from './components/TacticsWelcome'
import DeleteIcon from '@/assets/svg/delete.svg?react'
import RefreshIcon from '@/assets/svg/refresh.svg?react'
import { TacticsChatEditor } from '@/components/TacticsChatEditor'
import type { ChatRecord } from '@/types/chat'
import { fetchTacticsQaRecordPage } from '@/api/tactics'
import { fetchCheckTokenApi, fetchStreamResponse } from '@/api/chat'
import { fetchLoginByToken, fetchLoginByUid } from '@/api/common'
import { clearTacticsNavigationFlag, clearTacticsShouldSendQuestion, createTacticsConversation, deleteTacticsConversations, fetchTacticsConversations } from '@/store/tacticsSlice'
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 TacticsChat: React.FC = () => {
  const { id } = useParams<{ id: string }>()
  const location = useLocation()
  const navigate = useNavigate()
  const viteOutputObj = import.meta.env.VITE_OUTPUT_OBJ || 'open'
  const [isLoading, setIsLoading] = useState(false)
  const [allItems, setAllItems] = useState<ChatRecord[]>([])
  const [historyDividerIndex, setHistoryDividerIndex] = useState<number | null>(null)
  const [historyDividerTime, setHistoryDividerTime] = useState<string | null>(null)
  const dispatch = useAppDispatch()
  const {
    shouldSendQuestion: shouldSendQuestionFromState,
    shouldNavigateToNewConversation,
    currentConversationId,
  } = useAppSelector((state: RootState) => state.tactics)
  const [searchParams] = useSearchParams()
  const hasFetched = useRef(false)
  const hasCreatedRef = useRef(false)
  // 使用 useLocalStorageState 管理 token，与原有逻辑保持一致
  const [token, setToken] = useLocalStorageState<string | undefined>('__TOKEN__', {
    defaultValue: '',
  })
  // 优先从 location.state 获取，其次从 Redux state 获取
  const shouldSendQuestion = (location.state as { shouldSendQuestion?: string } | null)?.shouldSendQuestion || shouldSendQuestionFromState
  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)
  // 读取 from=tactics 且 version=2 的额外参数
  const tacticsMetaFromState = (location.state as { tacticsMeta?: any } | null)?.tacticsMeta
  const tacticsMetaFromQuery = useMemo(() => {
    const from = searchParams.get('from')
    const version = searchParams.get('version')
    if (from !== 'tactics' || version !== '2') {
      return undefined
    }
    return {
      version,
      taskId: searchParams.get('taskId') || undefined,
      pinBeginTime: searchParams.get('pinBeginTime') || undefined,
      pinEndTime: searchParams.get('pinEndTime') || undefined,
      partOrAll: searchParams.get('partOrAll') || undefined,
      channel: searchParams.get('channel') || undefined,
      channelName: searchParams.get('channelName') || undefined,
    }
  }, [searchParams])
  const tacticsMetaFromStorage = useMemo(() => {
    const raw = sessionStorage.getItem('tacticsMeta')
    if (!raw) {
      return undefined
    }
    try {
      const parsed = JSON.parse(raw)
      if (parsed?.version === '2') {
        return parsed
      }
    }
    catch {
      // ignore
    }
    return undefined
  }, [])
  const tacticsMeta = useMemo(() => tacticsMetaFromState || tacticsMetaFromQuery || tacticsMetaFromStorage, [tacticsMetaFromState, tacticsMetaFromQuery, tacticsMetaFromStorage])

  const formatCurrentTime = () => {
    const date = new Date()
    const pad = (value: number) => value.toString().padStart(2, '0')
    return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`
  }

  // 创建新会话（仅在 tactics 聊天页面且没有 id 时调用）
  const initTacticsConversation = useCallback(() => {
    // 只有在 tactics 聊天页面且没有会话 id 时才创建新对话
    if (!id && location.pathname.startsWith('/tactics/chat')) {
      if (hasCreatedRef.current) {
        return
      }
      hasCreatedRef.current = true
      dispatch(
        createTacticsConversation({
          conversationData: {},
          shouldNavigate: true,
          shouldSendQuestion: '',
        }),
      )
    }
  }, [id, location.pathname, dispatch])

  // 登录逻辑（复用原有逻辑，与 TacticsHome.tsx 保持一致）
  const login = useCallback(async () => {
    if (hasFetched.current) {
      return
    }
    hasFetched.current = true
    const url = new URL(window.location.href)
    const searchParams = new URLSearchParams(url.search)
    const _loginCode = searchParams.get('loginCode')
    let res = {} as any
    if (viteOutputObj === 'inner') {
      if (_loginCode) {
        res = await fetchLoginByToken(_loginCode)
        if (res.data) {
          setToken(res.data.token)
          window.dispatchEvent(
            new StorageEvent('storage', {
              key: '__TOKEN__',
              oldValue: token,
              newValue: res.data.token,
              url: window.location.href,
              storageArea: localStorage,
            }),
          )
          // 登录成功后，如果是 tactics 聊天页面且没有 id，则创建会话
          initTacticsConversation()
          dispatch(fetchTacticsConversations())
        }
      }
      else {
        // 如果没有 loginCode，但已有 token，直接尝试创建会话
        initTacticsConversation()
        dispatch(fetchTacticsConversations())
      }
    }
    else {
      res = await fetchLoginByUid('123123')
      if (res.data) {
        setToken(res.data.token)
        window.dispatchEvent(
          new StorageEvent('storage', {
            key: '__TOKEN__',
            oldValue: token,
            newValue: res.data.token,
            url: window.location.href,
            storageArea: localStorage,
          }),
        )
        // 登录成功后，如果是 tactics 聊天页面且没有 id，则创建会话
        initTacticsConversation()
        dispatch(fetchTacticsConversations())
      }
    }
  }, [setToken, dispatch, token, initTacticsConversation, viteOutputObj])

  /** 处理正常stream的数据 */
  const handleStreamMesageData = (msg: any, question: string) => {
    setAllItems((prevItems) => {
      const newItems = [...prevItems] // 创建数组的浅拷贝
      // 从后往前找到最后一个 AI 项
      let lastAiIndex = -1
      for (let i = newItems.length - 1; i >= 0; i--) {
        if (newItems[i].role === 'ai') {
          lastAiIndex = i
          break
        }
      }
      if (lastAiIndex >= 0) {
        // 创建最后一项的新对象，合并现有数据和新的 answer
        const originalAnswer = (newItems[lastAiIndex].answerList?.[0]?.answer || '') + msg.content.data.answer
        // 移除所有括号及其内容
        let filteredAnswer = originalAnswer.replace(/\([^)]*\)/g, '').trim()
        // 去除 [参考文档《任意内容》 《任意内容》...] 格式的内容
        filteredAnswer = filteredAnswer.replace(/\[参考文档(?:《[^》]*》\s*)+\]/g, '').trim()

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

  /** 处理超过最大条数的数据 */
  const handleChatMaxCount = (msg: any, question: string) => {
    setAllItems((prevItems) => {
      const newItems = [...prevItems]
      // 从后往前找到最后一个 AI 项
      let lastAiIndex = -1
      for (let i = newItems.length - 1; i >= 0; i--) {
        if (newItems[i].role === 'ai') {
          lastAiIndex = i
          break
        }
      }
      if (lastAiIndex >= 0) {
        newItems[lastAiIndex] = {
          ...newItems[lastAiIndex],
          question,
          answerList: [
            {
              ...msg.content.data,
              isShow: false,
              isChatMaxCount: true,
              endAnswerFlag: true,
              answer: '已达上限',
            },
          ],
        }
      }
      return newItems
    })
  }

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

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

    // 检查token
    await fetchCheckTokenApi()
    // 一次性添加用户问题和空的AI回答；如果不需要问题（自动触发场景），只添加 AI 占位
    const shouldIncludeQuestion = extra?.includeQuestion !== false && !!question
    setAllItems(prevItems => [
      ...prevItems,
      ...(shouldIncludeQuestion
        ? [
            {
              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

    const shouldSendQuestion = extra?.includeQuestion !== false

    const requestBody: Record<string, any> = {
      conversationId: currentIdRef.current,
      stream: true,
      productCode,
      toolId: resolvedToolId,
      ...(tacticsMeta || {}),
      ...(extra?.busiType ? { busiType: extra.busiType } : {}),
      ...(extra?.recordType ? { recordType: extra.recordType } : {}),
    }
    if (shouldSendQuestion) {
      requestBody.question = question ?? ''
    }

    // eslint-disable-next-line no-console
    console.log('[TacticsChat] handleSubmitQuestion:requesting', {
      fetchUrl,
      body: requestBody,
    })

    fetchStreamResponse(
      fetchUrl,
      requestBody,
      (msg) => {
        // eslint-disable-next-line no-console
        console.log('[TacticsChat] handleSubmitQuestion:onMessage', 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') {
          handleStreamMesageData(msg, question || '')
        }
        if (msg?.type === 'DATA' && msg?.content?.code === '01010005') {
          handleChatMaxCount(msg, question || '')
          return
        }
        if (msg.type === 'END') {
          dispatch(setIsAsking(false))
          if (isNew) {
            setTimeout(() => {
              dispatch(fetchTacticsConversations())
            }, 2000)
          }
        }
      },
      abortControllerRef.current.signal,
    )
  }

  /** 获取qa记录 */
  const getUserQaRecordPage = useCallback(async (conversationId: string) => {
    setIsLoading(true)
    try {
      const res = await fetchTacticsQaRecordPage(conversationId)
      const qaRecords = res.data || []
      // 始终添加 system 角色作为欢迎语
      const messages = [{ role: 'system' } as ChatRecord, ...processApiResponse(qaRecords)]
      const hasHistory = qaRecords.length > 0
      setHistoryDividerIndex(hasHistory ? messages.length : null)
      setHistoryDividerTime(hasHistory ? formatCurrentTime() : null)
      // 处理历史记录中的参考文档标记
      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)
    }
    catch {
      // 如果获取失败，至少显示欢迎语
      setAllItems([{ role: 'system' } as ChatRecord])
      setHistoryDividerIndex(null)
      setHistoryDividerTime(null)
    }
    finally {
      setIsLoading(false)
    }
  }, [])

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

  const handleClearRecord = useCallback(async () => {
    if (!currentIdRef.current)
      return
    try {
      await dispatch(deleteTacticsConversations([currentIdRef.current])).unwrap()
      // 停止正在进行的请求
      if (abortControllerRef.current) {
        abortControllerRef.current.abort()
        dispatch(setIsAsking(false))
      }
      // 清空对话列表，只保留欢迎语
      setAllItems([{ role: 'system' } as ChatRecord])
      setHistoryDividerIndex(null)
      setHistoryDividerTime(null)
      dispatch(
        createTacticsConversation({
          conversationData: {},
          shouldNavigate: false,
          shouldSendQuestion: '',
        }),
      )
    }
    catch (error) {
      console.error('清除记录失败:', error)
    }
  }, [dispatch])

  const handleReanalyze = useCallback(async () => {
    // 重新触发一次提问，与首次自动调用保持一致：busiType 01 / recordType A02
    await handleSubmitQuestion(undefined, undefined, undefined, { busiType: '01', recordType: 'A02', includeQuestion: false })
    // 重新拉取会话列表，保持原有行为
    await dispatch(fetchTacticsConversations())
    if (currentIdRef.current) {
      navigate(`/tactics/chat/${currentIdRef.current}`)
    }
  }, [dispatch, navigate, handleSubmitQuestion])

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

      currentIdRef.current = id
      lastSentQuestionRef.current = ''
      getUserQaRecordPage(id)
    }
    else {
      // 如果没有 id，显示欢迎语，等待登录成功后创建新会话
      setAllItems([{ role: 'system' } as ChatRecord])
      setHistoryDividerIndex(null)
      setHistoryDividerTime(null)
      setIsLoading(false)
    }
  }, [id, getUserQaRecordPage, dispatch])

  // 初始化时调用登录（登录成功后会自动创建会话）
  useEffect(() => {
    login()
  }, [login])

  // 进入会话后自动触发一次提交（不带 question），busiType 01 / recordType A02
  const hasAutoSubmittedRef = useRef(false)
  useEffect(() => {
    if (id) {
      // 当 id 变化时，重置自动提交标志
      hasAutoSubmittedRef.current = false
    }
  }, [id])
  useEffect(() => {
    if (currentIdRef.current && !isLoading && !hasAutoSubmittedRef.current) {
      hasAutoSubmittedRef.current = true
      handleSubmitQuestion(
        undefined,
        undefined,
        undefined,
        { busiType: '01', recordType: 'A02', includeQuestion: false },
      )
    }
  }, [isLoading, handleSubmitQuestion, id])

  // 创建新会话成功后跳转到新会话页面
  useEffect(() => {
    if (shouldNavigateToNewConversation && currentConversationId) {
      navigate(`/tactics/chat/${currentConversationId}`, {
        state: {
          shouldSendQuestion: shouldSendQuestionFromState,
          tacticsMeta,
        },
        replace: true,
      })
      dispatch(clearTacticsNavigationFlag())
    }
  }, [shouldNavigateToNewConversation, currentConversationId, navigate, dispatch, shouldSendQuestionFromState, tacticsMeta])

  // 处理shouldSendQuestion的变化 - 自动发送问题
  useEffect(() => {
    // eslint-disable-next-line no-console
    console.log('[TacticsChat] autoSend check', {
      shouldSendQuestion,
      currentId: currentIdRef.current,
      isLoading,
      lastSentQuestion: lastSentQuestionRef.current,
    })
    if (
      shouldSendQuestion
      && currentIdRef.current
      && !isLoading
      && shouldSendQuestion !== lastSentQuestionRef.current
    ) {
      lastSentQuestionRef.current = shouldSendQuestion
      dispatch(clearTacticsShouldSendQuestion())
      setTimeout(() => {
        handleSubmitQuestion(shouldSendQuestion)
      }, 100)
    }
  }, [shouldSendQuestion, isLoading, dispatch])

  return (
    <div
      className={styles.scrollView}
      style={{
        height: '100vh',
        display: 'flex',
        flexDirection: 'column',
        marginLeft: 'auto',
        marginRight: 0,
        backgroundColor: '#FFFFFF',
        zIndex: 1000,
      }}
    >
      {/* 右上操作区 */}
      <div className="flex justify-end items-center gap-[16px] px-[16px] pt-[16px] pb-[8px]">
        <button
          type="button"
          onClick={handleClearRecord}
          className="flex items-center gap-[4px] text-[#4A90E2] text-[14px] hover:opacity-80 transition-opacity cursor-pointer bg-transparent border-none outline-none"
        >
          <DeleteIcon className="w-[16px] h-[16px] text-[#B2B8C1]" />
          <span>清除记录</span>
        </button>
        <button
          type="button"
          onClick={handleReanalyze}
          className="flex items-center gap-[4px] text-[#4A90E2] text-[14px] hover:opacity-80 transition-opacity cursor-pointer bg-transparent border-none outline-none"
        >
          <RefreshIcon className="w-[16px] h-[16px] text-[#B2B8C1]" />
          <span>重新分析</span>
        </button>
      </div>
      <div className={`${styles.chatPage} relative flex flex-col h-full`}>
        <div className={`${styles.content} flex-1 overflow-hidden flex flex-col`}>
          {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 flex-1 overflow-y-auto px-[16px]`}
            >
              <div className={`${styles.inter} pt-[8px] pb-[24px]`}>
                {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 (
                    <React.Fragment key={uniqueKey}>
                      {historyDividerIndex !== null && index === historyDividerIndex && (
                        <div className="flex items-center gap-[12px] my-[16px] text-[#B2B8C1] text-[12px]">
                          <div className="flex-1 h-px bg-[#E4E7EC]" />
                          <span>{historyDividerTime || formatCurrentTime()}</span>
                          <div className="flex-1 h-px bg-[#E4E7EC]" />
                        </div>
                      )}
                      <div
                        className="w-full chatItem mx-auto"
                      >
                        {record.role === 'system' && <TacticsWelcome />}
                        {record.role === 'user' && <ChatItemUser record={record} />}
                        {record.role === 'ai' && (
                          <ChatAnswerBox
                            onSubmitQuestion={handleSubmitQuestion}
                            isLastAnswer={index === allItems.length - 1}
                            showIndex={0}
                            record={record}
                            index={index}
                          />
                        )}
                      </div>
                    </React.Fragment>
                  )
                })}
              </div>
            </motion.div>
          )}
        </div>
        <div className="relative box-border px-[16px] mx-auto iptContainer w-full flex-shrink-0 pb-[18px] pt-[12px] bg-white border-t border-gray-100">
          <div className="relative">
            <div className="absolute left-1/2 ml-[-20px] top-[-45px]">
              <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>
            <TacticsChatEditor
              onSubmit={(question) => {
                // eslint-disable-next-line no-console
                console.log('[TacticsChat] onSubmit wrapper', {
                  question,
                  currentId: currentIdRef.current,
                  isLoading,
                })
                return handleSubmitQuestion(
                  question,
                  undefined,
                  undefined,
                  { busiType: '02', recordType: 'A01', includeQuestion: true },
                )
              }}
              placeholders={['']}
            />
            <div className="w-full text-center mt-[12px] text-[#3333334d] text-[12px]">
              内容由AI模型生成，其准确性和完整性无法保证，仅供参考
            </div>
          </div>
        </div>
      </div>
    </div>
  )
}
