import React, { useEffect, useState } from 'react'
import { ChatAnswerAttachment } from './ChatAnswerAttchment'
import { ChatAnswerOperate } from './ChatAnswerOperate'
import { formatMarkdown } from './markdownFormatter'
import type { Answer } from '@/types/chat'
import { MarkdownDetail } from '@/components/MarkdownDetail'
import { fetchTerminateQuestion } from '@/api/chat'
import { fetchGetDocumentLinks } from '@/api/common'

interface ChatAnswerParserProps {
  answer: Answer
  isStopTyping: boolean | undefined
  isLastAnswer: boolean
  onTyping: () => void
  onComplate: () => void
  onSubmitQuestion: (question: string, productCode?: string) => void
}

export const ChatAnswerParser: React.FC<ChatAnswerParserProps> = ({ isLastAnswer, onTyping, onComplate, answer, isStopTyping, onSubmitQuestion }) => {
  const formatAnswer = formatMarkdown(answer.answer || '')
  const [displayedText, setDisplayedText] = useState('')
  const [currentIndex, setCurrentIndex] = useState(0)
  const [isTyping, setIsTyping] = useState(false)
  const [hideOperate, setHideOperate] = useState(false)
  const [isImageAnswer, setIsImageAnswer] = useState(false)

  function extractImageSources(htmlString: string): string[] {
    const imgRegex = /<img[^>]+src="([^">]+)"/gi
    const srcRegex = /src="([^">]+)"/i
    const matches = htmlString.match(imgRegex)

    const sources: string[] = []

    if (matches) {
      matches.forEach((match) => {
        const srcMatch = match.match(srcRegex)
        if (srcMatch && srcMatch[1])
          sources.push(srcMatch[1])
      })
    }

    return sources
  }

  function replaceImageSources(str: string, originalSrcs: string[], newSrcs: string[]): string {
    if (originalSrcs.length !== newSrcs.length)
      return str

    return originalSrcs.reduce((acc, originalSrc, index) => {
      const newSrc = newSrcs[index]
      const regex = new RegExp(originalSrc, 'g')
      return acc.replace(regex, newSrc)
    }, str)
  }

  async function formatImgAnswer(str: string) {
    const imagesSrc = extractImageSources(str)
    const res = await fetchGetDocumentLinks(imagesSrc)
    if (res.data) {
      const arr = replaceImageSources(str, imagesSrc, res.data.map((item: any) => item.docUrl))
      return arr
    }

    else { return replaceImageSources(str, imagesSrc, []) }
  }

  const handleImageAnswer = async () => {
    const res = await formatImgAnswer(formatAnswer)
    setDisplayedText(res)
    setIsTyping(false)
    onComplate()
  }

  useEffect(() => {
    if (isStopTyping) {
      return
    }
    if (!isTyping) {
      onTyping()
      setIsTyping(true)
    }
    if (currentIndex < formatAnswer.length) {
      const nextChar = formatAnswer[currentIndex]
      if (nextChar === '<' || isImageAnswer) {
        setIsImageAnswer(true)
        const timer = setTimeout(() => {
          setCurrentIndex(prevIndex => prevIndex + 1)
        }, 20) // 调整此值以改变打字速度
        return () => clearTimeout(timer)
      }
      else {
        const timer = setTimeout(() => {
          setDisplayedText(formatAnswer.slice(0, currentIndex + 1))
          setCurrentIndex(prevIndex => prevIndex + 1)
        }, 20) // 调整此值以改变打字速度
        return () => clearTimeout(timer)
      }
    }
    else {
      if (answer.endAnswerFlag) {
        if (isImageAnswer) {
          handleImageAnswer()
        }
        else {
          setIsTyping(false)
          onComplate()
        }
      }
    }
  }, [answer, currentIndex])

  const handleStopTyping = async () => {
    const res = await fetchTerminateQuestion(answer)
    if (res.ok) {
      setIsTyping(false)
      onComplate()
    }
  }

  useEffect(() => {
    if (isStopTyping) {
      handleStopTyping()
    }
  }, [isStopTyping])

  useEffect(() => {
    setHideOperate((answer.attachmentList || []).some(attachment => attachment.type === 'box'))
  }, [answer.attachmentList])

  return (
    <div className="answerParser">
      {!!displayedText.length && (
        <div className={answer.attachmentList?.length ? 'mb-[20px]' : ''}>
          <MarkdownDetail>
            {displayedText}
          </MarkdownDetail>
        </div>
      )}
      {!isTyping
      && answer.attachmentList
      && answer.attachmentList?.length !== 0
      && <ChatAnswerAttachment isLastAnswer={isLastAnswer} onSubmitQuestion={onSubmitQuestion} answer={answer} />}

      {!isTyping && !hideOperate && <ChatAnswerOperate answer={answer} />}
    </div>
  )
}
