import { observer, useStore } from "@/stores/utils"
import { checkMeia, Tss } from "@/utils/tts"
import { Attachments, Sender } from "@ant-design/x"
import { FooterRender } from "@ant-design/x/es/sender"
import { Button, Divider, GetProp, message, Spin, Tooltip } from "antd"
import { useEffect, useRef, useState } from "react"
import "./index.scss"

const SenderBox = () => {
  const tssRef = useRef<Tss>(null)
  const { ChatStore } = useStore()
  const [speech, setSpeech] = useState(false)
  const {
    streamingChat,
    isLoading,
    abortChat,
    handleUploadFile,
    messageContent,
    setMessageContent,
    scrollToBottom,
    uploading,
    fileArr,
    onRemoveFile,
  } = ChatStore

  useEffect(() => {
    return () => {
      tssRef.current?.close()
    }
  }, [])

  const onSubmit = (nextContent: string) => {
    setSpeech(false)
    tssRef.current?.close()
    if (!nextContent) {
      return
    }
    scrollToBottom()
    streamingChat(nextContent)
    setMessageContent("")
  }

  const senderHeader = (
    <div className="sender_header">
      {fileArr.length > 0 && (
        <div className="file_list">
          {fileArr.map((file) => (
            <Attachments.FileCard
              className="file_card"
              key={file.id}
              onRemove={() => onRemoveFile(file.id)}
              item={{
                uid: file.id,
                name: file.originalName,
                url: file.path,
              }}
            />
          ))}
        </div>
      )}
      {uploading && (
        <div className="uploading_box flex_c">
          <Spin size="small" spinning={uploading} />
        </div>
      )}
    </div>
  )

  const handleFileChange: GetProp<typeof Attachments, "onChange"> = (info) => {
    handleUploadFile(info.file)
  }

  const renderFooter: FooterRender = ({ components }) => {
    const { SendButton, SpeechButton } = components
    return (
      <div className="flex_sb">
        <SpeechButton className="speech_btn" />
        <div className="flex_right">
          <Attachments
            accept=".png,.jpg,.jpeg,.gif,.pdf,.doc,.docx,.xls,.xlsx,.mp3,.wav,.csv"
            beforeUpload={() => false}
            onChange={handleFileChange}
          >
            <Tooltip
              title={
                <div className="fs-16">
                  上传文件：image、pdf、docx、excel、csv、audio。
                </div>
              }
            >
              <Button
                type="text"
                className="file_btn"
                icon={<i className="iconfont icon-icon02"></i>}
              />
            </Tooltip>
          </Attachments>
          <Divider type="vertical" />
          <SendButton
            type="primary"
            className="send_btn"
            icon={<i className="iconfont icon-fasong"></i>}
            disabled={messageContent && !isLoading && !uploading ? false : true}
          />
        </div>
      </div>
    )
  }

  const onRecordChange = async (nextSpeech: boolean) => {
    if (nextSpeech) {
      try {
        await checkMeia()
      } catch {
        message.error("获取麦克风失败")
      }

      tssRef.current = Tss.createInstance({
        onMessage(data) {
          if (!data) return
          setMessageContent(messageContent + data)
        },
        onError(e) {
          tssRef.current?.close()
        },
        onClose() {
          tssRef.current?.close()
        },
      })
    } else {
      tssRef.current?.close()
    }
    setSpeech(nextSpeech)
  }
  return (
    <div className="input_container">
      <div className="block_wrap">
        <Sender
          className="send_box"
          placeholder="发送消息..."
          actions={false}
          onChange={(value) => setMessageContent(value)}
          value={messageContent}
          onSubmit={onSubmit}
          header={senderHeader}
          autoSize={{ minRows: 2, maxRows: 6 }}
          footer={renderFooter}
          onCancel={abortChat}
          allowSpeech={{
            recording: speech,
            onRecordingChange: onRecordChange,
          }}
        />
        <div className="tips">内容由 AI 生成，仅供参考。</div>
      </div>
    </div>
  )
}

export default observer(SenderBox)
