import { useGetState } from "ahooks";
import { Flex } from "antd";
import React, { useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
import { useSpeechRecognition } from "../../hooks";
import { Timer } from "../../utils";
import { MicLine, PauseFill, StopFill } from "../../Icons";
import { MicrophonePermissionCheck } from "../MicrophonePermissionCheck";
import { effectExperienceTabs } from "./constance";
import {
  eAudioEffectExperience,
  eControlsGroup,
  iAudioEffectExperiencePropsType,
} from "./index.type";
import MicrophoneAnimation from "./MicrophoneAnimation";
import { AudioEffectExperienceWrapper } from "./styled";
import { Tooltip } from "antd";

export interface iAudioEffectExperienceRef {
  initAudioHandler: () => void;
}

export const AudioEffectExperience = React.memo(
  React.forwardRef<iAudioEffectExperienceRef, iAudioEffectExperiencePropsType>((props, ref) => {
    const {
      dataId = "",
      appId,
      meetingJoinUrl,
      onStopRecord = () => {},
      onErrorMessage = () => {},
      onStopRecordBefore = () => {},
      postAgentRequest,
      checkMicPerm = true,
      meetingState,
      updateMeetingState,
      dataAutologs,
    } = props;

    const [activeTab, setActiveTab] = useState<eAudioEffectExperience>(
      eAudioEffectExperience.SINGLE_SENTENCE
    );
    const [speechTextList, setSpeechTextList, getSpeechTextList] = useGetState<
      Array<{
        text: string;
        translateText: string;
        sentenceId: string;
      }>
    >([]);
    const speechTextMapRef = useRef<any>(new Map());
    const [recordTime, setRecordTime] = useState<string>("--:--:--");
    const timerRef = useRef(
      new Timer((str: string) => {
        setRecordTime(str);
      })
    );

    const updateSpeechTextList = (output: any) => {
      const textList = [...getSpeechTextList()];
      const speechTextMap = speechTextMapRef.current;

      // 句子中、句子结束
      if (
        output?.transcription?.sentenceEnd !== undefined &&
        output?.transcription?.sentenceId !== undefined &&
        output?.transcription?.time !== undefined
      ) {
        const obj = speechTextMap.get(output?.transcription?.sentenceId);
        if (obj === undefined) {
          speechTextMap.set(output?.transcription?.sentenceId, {
            index: textList?.length,
          });
          textList.push({
            text: output?.transcription?.text || "",
            sentenceId: output?.transcription?.sentenceId,
            translateText: "",
          });
        } else {
          const str = output?.transcription?.text ?? "";
          textList[obj.index].text = str;
        }
      }

      // 句子翻译
      if (output?.translations !== undefined) {
        const transKey = Object.keys(output?.translations || {})[0];
        const translateResult = output?.translations?.[transKey]?.translateResult;
        if (Array.isArray(translateResult)) {
          translateResult.forEach(translate => {
            const obj = speechTextMap.get(translate.sentenceId);
            if (obj !== undefined && textList[obj.index]) {
              textList[obj.index].translateText = translate.text;
            }
          });
        }
      }

      setSpeechTextList(textList);
    };

    const { isRecording, isPaused, startRecording, pauseRecording, stopRecording } =
      useSpeechRecognition({
        dataId,
        appId,
        onErrorMessage,
        onMessage: data => {
          // 处理语音识别消息
          const { payload } = data;
          switch (payload?.output?.action) {
            case "speech-listen":
              break;
            case "recognize-result": {
              updateSpeechTextList(payload.output);
              break;
            }
            case "task-failed":
              break;
            case "speech-end":
              break;
            default:
              console.log("socket 收到未知事件 message:", payload);
          }
        },
        meetingJoinUrl,
        onDataIdChange: _dataId => {
          // 处理数据ID变化
          console.log("数据ID更新:", _dataId);
        },
        postAgentRequest,
      });

    useImperativeHandle(ref, () => {
      return {
        initAudioHandler: startRecording,
      };
    }, [startRecording]);

    useEffect(() => {
      updateMeetingState((draft: any) => {
        draft.submitLoading = isRecording;
      });
    }, [isRecording]);

    useEffect(() => {
      if (isRecording && isPaused) {
        timerRef?.current.stop();
      }

      if (isRecording && !isPaused) {
        timerRef?.current.start();
      }
    }, [isRecording, isPaused]);

    const controlsGroup = useMemo(
      () => [
        {
          key: !isPaused ? eControlsGroup.CONTINUE : eControlsGroup.PAUSE,
          tooltip: isPaused ? "继续录音" : "暂停录音",
          dataAutolog: isPaused ? dataAutologs?.continue : dataAutologs?.paused,
          onClick: () => {
            !isPaused ? pauseRecording() : startRecording();
          },
          icon: (
            <div className="AudioEffectExperience__ControlsGroup__Icon">
              {isPaused ? <MicLine width={24} height={24} /> : <PauseFill />}
            </div>
          ),
        },
        {
          key: eControlsGroup.END,
          tooltip: "结束录音",
          dataAutolog: dataAutologs?.end,
          onClick: async () => {
            await onStopRecordBefore();
            await stopRecording(meetingState?.createTaskOutput?.dataId || "");
            await onStopRecord();
          },
          icon: (
            <div className="AudioEffectExperience__ControlsGroup__Stop">
              <StopFill />
            </div>
          ),
        },
      ],
      [isPaused, startRecording, pauseRecording, stopRecording, onStopRecord]
    );

    const renderContent = useMemo(() => {
      const { text = "", translateText } = speechTextList?.[speechTextList?.length - 1] || {};
      if (activeTab === eAudioEffectExperience.SINGLE_SENTENCE) {
        return (
          <div className="AudioEffectExperience__Content">
            <div className="AudioEffectExperience__Content__Text">
              {text.slice(0, text.length - 1)}
              <span className="AudioEffectExperience__Content__LastText">
                {text[text.length - 1] || ""}
              </span>
            </div>
            <div className="AudioEffectExperience__Content__Description">{translateText}</div>
          </div>
        );
      }
      return (
        <div className="AudioEffectExperience__WholeText">
          {speechTextList.map(({ text: _text, translateText: _translateText, sentenceId }) => (
            <div className="AudioEffectExperience__WholeText__Content" key={sentenceId}>
              <div className="AudioEffectExperience__WholeText__Text">{_text}</div>
              <div className="AudioEffectExperience__WholeText__TranslateText">
                {_translateText}
              </div>
            </div>
          ))}
          <div className="AudioEffectExperience__WholeText__Mask" />
        </div>
      );
    }, [activeTab, speechTextList]);

    if (!isRecording && checkMicPerm) {
      return <MicrophonePermissionCheck onStartRecord={startRecording} />;
    }

    return (
      <AudioEffectExperienceWrapper>
        <div className="AudioEffectExperience__Title">
          <div className="AudioEffectExperience__Title__Text">{recordTime}</div>
          <Flex align="center" justify="center" gap={12}>
            <div className="AudioEffectExperience__Tabs">
              {effectExperienceTabs.map(({ label, key }) => (
                <div
                  onClick={() => {
                    setActiveTab(key);
                  }}
                  className={`AudioEffectExperience__Tabs__Item ${activeTab === key ? "AudioEffectExperience__Tabs__Item__Active" : ""} `}
                  key={key}
                >
                  {label}
                </div>
              ))}
            </div>
            {controlsGroup.map(({ tooltip, key, icon, onClick, dataAutolog }) => (
              <Tooltip placement="top" title={tooltip} key={key}>
                <div onClick={onClick} data-autolog={dataAutolog}>
                  {icon}
                </div>
              </Tooltip>
            ))}
          </Flex>
        </div>
        {renderContent}
        <div className="AudioEffectExperience__Bottom">
          <MicrophoneAnimation isStarting={!isPaused} />
        </div>
      </AudioEffectExperienceWrapper>
    );
  })
);
