import React, { useEffect, useMemo, memo, useCallback, useRef, useState } from "react";
import useForceUpdate from "use-force-update";
import {
  Controller,
  PID,
  OldSelection,
  Word,
  TranslateMode,
  SID,
  TextPolishMode,
} from "@tingwujs/core";
import { isMacOS } from "@tingwujs/util";
import { agendasState, generateViewedWords } from "../../model";
import { TextEditor, TextEditorHandler } from "../textEditor";
import {
  Wrapper,
  ParagraphStyledWrapper,
  ParagraphStyled,
  ParagraphInner,
  Mask,
  MaskInner,
  ParagraphOrigin,
  ParagraphWrapper,
  QAMarkStyled,
} from "./styled";
import { UnfixSentense } from "./unfixSentense";
import { ParagraphHeading } from "./paragraphHeading";
import { TranslateContent } from "../translateContent";
import { TextPolishContent } from "../textPolish/textPolishContent";
import { getTranscriptionController, useTranscriptionHooks } from "../../controller";
import { useSyncEffect, isIntersectRanges } from "@tingwujs/common";
import { useRecoilValue } from "recoil";
import { AssistantActiveType, QAModel, QAModelType, QnAController } from "@tingwujs/sphere";

export interface ParagraphProps {
  controller: Controller;
  pid?: PID;
  isUnfix: boolean;
  timestamp?: string;
  selections?: OldSelection[];
  translateSelections?: OldSelection[];
  textPolishSelections?: OldSelection[];
  renderBeforeMask?: () => React.ReactNode;
  visible?: boolean;
  qnaQSids?: SID[];
  qnaASids?: SID[];
  activeQnaASids?: SID[];
  activeQnaQSids?: SID[];
  qnaModel?: QAModelType;
  aiReviewPid?: string;
  isAnaQ?: boolean;
  isAnaQa?: boolean;
  shareDisabled?: boolean;
  qaController?: QnAController;
}
/**
 * qnaActive值
 * 0 无样式 -> question模式
 * 1 -> mainPoin模式
 * 2 问 -> questionAndanswer模式
 * 3 答 -> questionAndanswer模式
 * 4 问答 -> questionAndanswer模式
 */
export enum QnaActive {
  none,
  mainPoin,
  question,
  answer,
  questionAndanswer,
}

export const ParagraphContent: React.FC<ParagraphProps> = memo(props => {
  const {
    pid,
    isUnfix,
    controller,
    qaController,
    timestamp,
    selections,
    translateSelections,
    textPolishSelections,
    renderBeforeMask,
    visible = true,
    qnaQSids, // TODO QA
    // qnaASids,
    activeQnaQSids,
    activeQnaASids,
    qnaModel,
    aiReviewPid,
    isAnaQ,
    isAnaQa,
    shareDisabled,
  } = props;

  const transController = getTranscriptionController(controller);
  const [editorFocus, setEditorFocus] = useState(false);
  const [isMouseEnter, setIsMouseEnter] = useState(false);
  const emptyUnfix = isUnfix && !pid;

  const { theme } = useTranscriptionHooks(controller, ["theme"]);

  const handleMouseEnter = useCallback(() => {
    setIsMouseEnter(true);
  }, []);

  const handleMouseLeave = useCallback(() => {
    setIsMouseEnter(false);
  }, []);

  const forceUpdate = useForceUpdate();
  const paragraphRef = useRef<HTMLDivElement>(null);
  const containerRef = useRef<HTMLDivElement>(null);
  const textEditorRef = useRef<TextEditorHandler>(null);
  const readonly = controller.getReadonly();
  const defaultSpeakerReadonly = controller.getDefaultSpeakerReadonly();

  useSyncEffect(() => {
    return controller.on("readonlyChange", forceUpdate);
  }, [controller, forceUpdate]);

  const paragraph = pid ? controller.getParagraph(pid) : undefined;

  useSyncEffect(() => {
    if (emptyUnfix) {
      return;
    }
    return controller.on("paragraphChange", ({ pid: _pid }) => {
      if (_pid !== pid) {
        return;
      }
      forceUpdate();
    });
  }, [pid, controller, forceUpdate, emptyUnfix]);

  useSyncEffect(() => {
    return controller.on("livingModeChange", forceUpdate);
  }, [controller, forceUpdate]);

  const handleClick = useCallback((event: React.MouseEvent) => {
    if (event.target === containerRef.current) {
      textEditorRef.current?.focus();
    }
  }, []);

  useSyncEffect(() => {
    return controller.on("playingVoiceWordChange", args => {
      const { pid: _pid } = args;
      if (_pid === pid) {
        forceUpdate();
      }
    });
  }, [controller, pid, forceUpdate]);

  useSyncEffect(() => {
    return controller.on("selectionChange", args => {
      const isFocus = args.selection && args.selection.range.start.pid === pid;
      setEditorFocus(!!isFocus);
    });
  }, [controller, pid]);

  const livingMode = controller.getLivingMode();
  // eslint-disable-next-line react-hooks/exhaustive-deps
  const words: Word[] = pid ? controller.getWords(pid) : [];
  const textContent = words.map(word => word.text).join("");

  // TODO QA type style init
  const qnaActive = useMemo((): QnaActive => {
    if (
      !paragraph ||
      !activeQnaQSids ||
      qnaModel === QAModel.question ||
      words.length === 0 ||
      activeQnaQSids?.length === 0
    ) {
      return QnaActive.none;
    }
    if (qnaModel === QAModel.mainPoin && activeQnaASids) {
      for (const activeQnaASid of activeQnaASids) {
        if (words.find(item => item.sentenceId === activeQnaASid)) {
          return QnaActive.mainPoin;
        }
      }
    }
    if (qnaModel === QAModel.questionAndanswer && activeQnaASids) {
      const qnaQActive = activeQnaQSids.some(
        activeQnaQSid => words.findIndex(item => item.sentenceId === activeQnaQSid) > -1
      );
      const qnaAActive = activeQnaASids.some(
        activeQnaASid => words.findIndex(item => item.sentenceId === activeQnaASid) > -1
      );

      if (qnaQActive && qnaAActive) {
        return QnaActive.questionAndanswer;
      } else if (qnaQActive && !qnaAActive) {
        return QnaActive.question;
      } else if (!qnaQActive && qnaAActive) {
        return QnaActive.answer;
      }
    }
    return QnaActive.none;
  }, [qnaModel, activeQnaQSids, activeQnaASids]);

  // 如果有pid 且 打开了音字对照功能，才会获取playingWord
  const playingWord =
    pid && controller.getIsEnablePlayingVoice() ? controller.getPlayingWord(pid) : undefined;

  const activeFoundSelection = controller.getActiveFoundSelection();
  const activeAgendaHighlightSids = controller.getActiveAgendaHighlightSids();
  const activeTodoListHighlightSids = controller.getActiveTodoListHighlightSids();
  const meetingActiveAgendaPid = controller.getMeetingActiveAgendaPid();

  const meetingAgendaActive = useMemo((): boolean => {
    if (!livingMode) return false;
    return meetingActiveAgendaPid === pid;
  }, [meetingActiveAgendaPid, pid, livingMode]);

  const notHasSid = words.every(word => !activeAgendaHighlightSids.includes(word.sentenceId));

  const viewedWords = useMemo(() => {
    if (emptyUnfix) {
      return [];
    }
    return generateViewedWords(
      words,
      selections,
      activeFoundSelection,
      playingWord,
      false,
      activeAgendaHighlightSids,
      activeTodoListHighlightSids,
      qnaQSids,
      activeQnaQSids,
      qnaModel
    );
  }, [
    playingWord,
    words,
    selections,
    activeFoundSelection,
    emptyUnfix,
    !notHasSid ? activeAgendaHighlightSids.join(" ") : "",
    qnaQSids,
    activeQnaQSids,
    qnaModel,
    activeAgendaHighlightSids,
  ]);

  const translateMode = controller.getTranslateMode(pid);
  const textPolishMode = controller.getTextPolishMode(); // AI改写模式 备注：不和翻译同时存在

  useSyncEffect(() => {
    return controller.on("translateModeChange", forceUpdate);
  }, [controller, forceUpdate]);

  useSyncEffect(() => {
    // 当translateMode强制为disabled时的时候，如果有translate值了，需要看下translateMode是不是变化触发刷新
    return controller.on("fixParagraphTranslateChange", ({ pid: _pid }) => {
      if (_pid === pid && controller.getTranslateMode() !== translateMode) {
        forceUpdate();
      }
    });
  }, [controller, forceUpdate, pid, translateMode]);

  /** * AI 改写 START */
  // AI 改写模式变更监听
  useSyncEffect(() => {
    return controller.on("textPolishModeChange", forceUpdate);
  }, [controller, forceUpdate]);

  // AI 改写数据变更监听
  useSyncEffect(() => {
    // 当textPolishMode强制为disabled时的时候，如果有textPolish值了，需要看下textPolishMode是不是变化触发刷新
    return controller.on("fixParagraphTextPolishChange", ({ pid: _pid }) => {
      if (_pid === pid && controller.getTextPolishMode() !== textPolishMode) {
        forceUpdate();
      }
    });
  }, [controller, forceUpdate, pid, translateMode]);
  /** * AI 改写 END */

  useSyncEffect(() => {
    return controller.on("playingVoiceWordEnableChange", forceUpdate);
  }, [controller, forceUpdate]);

  useSyncEffect(() => {
    return controller.on("activeAgendaChange", forceUpdate);
  }, [controller, forceUpdate]);

  useSyncEffect(() => {
    if (!emptyUnfix) {
      return;
    }
    return controller.on("emptyUnfixParagraphChange", forceUpdate);
  }, [controller, forceUpdate, emptyUnfix]);

  useEffect(() => {
    if (!isUnfix) {
      return;
    }

    const setUnfixMarked = () => {
      if (readonly) return;
      if (emptyUnfix) {
        const currentMark = controller.getEmptyUnfixTempParagraphMark();
        controller.setEmptyUnfixTempParagraphMark(!currentMark ? "blue" : "");
      } else {
        const isBlueTag = controller.isHasParagraphMarkColor(pid!, "blue");
        controller.setParagraphMark(pid!, !isBlueTag ? "blue" : "");
      }
    };

    const handler = (event: KeyboardEvent) => {
      if (readonly) return;
      const isPressE = event.key === "e" || event.keyCode === 69; // key: e
      if (isPressE && ((isMacOS && event.metaKey) || event.ctrlKey)) {
        event.preventDefault();
        setUnfixMarked();
      }
    };

    window.addEventListener("keydown", handler);
    return () => {
      window.removeEventListener("keydown", handler);
    };
  }, [controller, isUnfix, readonly, emptyUnfix, pid]);

  useEffect(() => {
    if (!paragraphRef.current || !isUnfix) {
      return;
    }

    transController.setUnfixElement(paragraphRef.current);
    return () => {
      transController.setUnfixElement(undefined);
    };
  }, [isUnfix, transController]);

  // 展示翻译
  const showTranslate = [TranslateMode.OriginAndTranslate, TranslateMode.TranslateOnly].includes(
    translateMode
  );
  // 展示AI原文改写
  const showTextPolish = [
    TextPolishMode.OriginAndTextPolish,
    TextPolishMode.TextPolishOnly,
  ].includes(textPolishMode);
  // 展示原文
  const showOrigin =
    [TranslateMode.Disabled, TranslateMode.OriginAndTranslate].includes(translateMode) &&
    [TextPolishMode.Disabled, TextPolishMode.OriginAndTextPolish].includes(textPolishMode);

  const isHighlight = isUnfix || Boolean(playingWord);

  useEffect(() => {
    if (isUnfix && textContent.length === 0) {
      setEditorFocus(false);
    }
  }, [textContent, isUnfix]);

  const originNode = useMemo(() => {
    if (!showOrigin) {
      return null;
    }

    const _isHighlight = isHighlight && !showTranslate && !showTextPolish;
    const isPlaying = Boolean(playingWord);

    // 原文和改写同时存在时，需要改变 原文默认颜色；
    const modifyDefaultFontColor = [TextPolishMode.OriginAndTextPolish].includes(textPolishMode)
      ? "rgba(39, 38, 77, 0.45)"
      : "";
    return (
      <ParagraphOrigin
        className="tingwu2_paragraphOrigin"
        showTranslate={showTranslate}
        showTextPolish={showTextPolish}
        meetingAgendaActive={meetingAgendaActive}
        isHighlight={_isHighlight}
        isLivingMode={livingMode}
        isUnfix={isUnfix}
        isPlaying={isPlaying}
        qnaActive={qnaActive}
        aiReviewActive={aiReviewPid === pid ? AssistantActiveType.originActive : null}
      >
        <ParagraphInner>
          {!emptyUnfix && (
            <TextEditor
              ref={textEditorRef}
              isHighlight={_isHighlight}
              isUnfix={isUnfix}
              textContent={textContent}
              viewedWords={viewedWords}
              pid={pid!}
              controller={controller}
              qaController={qnaActive ? undefined : qaController}
              timestamp={timestamp}
              readonly={readonly}
              isPlaying={isPlaying}
              modifyDefaultFontColor={modifyDefaultFontColor}
              meetingAgendaActive={meetingAgendaActive}
            />
          )}
          {isUnfix && (
            <UnfixSentense
              controller={controller}
              emptyUnfix={emptyUnfix}
              pid={pid}
              isHighlight={_isHighlight}
            />
          )}
        </ParagraphInner>
      </ParagraphOrigin>
    );
  }, [
    showOrigin,
    isHighlight,
    showTranslate,
    showTextPolish,
    playingWord,
    livingMode,
    isUnfix,
    qnaActive,
    aiReviewPid,
    pid,
    emptyUnfix,
    textContent,
    qaController,
    viewedWords,
    controller,
    timestamp,
    readonly,
    textPolishMode,
    meetingAgendaActive,
  ]);
  const translateNode = useMemo(() => {
    if (!showTranslate) {
      return null;
    }
    return (
      <TranslateContent
        showOrigin={showOrigin}
        aiReviewActive={aiReviewPid === pid ? AssistantActiveType.originActive : null}
        isHighlight={
          isHighlight ||
          [
            QnaActive.mainPoin,
            QnaActive.answer,
            QnaActive.question,
            QnaActive.questionAndanswer,
          ].includes(qnaActive)
        }
        controller={controller}
        pid={pid}
        isUnfix={isUnfix}
        translateSelections={translateSelections}
        activeFoundSelection={activeFoundSelection}
        playingWord={playingWord}
        qaController={qnaActive ? undefined : qaController}
      />
    );
  }, [
    showOrigin,
    showTranslate,
    controller,
    isUnfix,
    pid,
    qaController,
    translateSelections,
    activeFoundSelection,
    playingWord,
    isHighlight,
    aiReviewPid,
    qnaActive,
  ]);

  /** 渲染 AI原文改写 段落节点 */
  const textPolishNode = useMemo(() => {
    if (!showTextPolish) return null;
    return (
      <TextPolishContent
        showOrigin={showOrigin}
        aiReviewActive={aiReviewPid === pid ? AssistantActiveType.originActive : null}
        isHighlight={isHighlight}
        controller={controller}
        pid={pid}
        textPolishSelections={textPolishSelections}
        activeFoundSelection={activeFoundSelection}
        qaController={qnaActive ? undefined : qaController}
      />
    );
  }, [
    showTextPolish,
    showOrigin,
    aiReviewPid,
    pid,
    isHighlight,
    controller,
    textPolishSelections,
    activeFoundSelection,
    qnaActive,
  ]);

  const getParagraphContainer = useCallback(() => {
    return paragraphRef.current as HTMLDivElement;
  }, []);

  const agendas = useRecoilValue(agendasState);
  const agendasAttrs = useMemo<Record<string, boolean>>(() => {
    if (isUnfix || !paragraph) {
      return {};
    }
    const { wids } = paragraph;
    const firstWid = wids[0];
    const lastWid = wids[wids.length - 1];
    const firstWord = controller.getWord(firstWid);
    const lastWord = controller.getWord(lastWid);
    const attrs: Record<string, boolean> = {};

    agendas.forEach(agenda => {
      const isIntersect = isIntersectRanges(
        {
          start: agenda.beginTime,
          end: agenda.endTime,
        },
        {
          start: firstWord.beginTime,
          end: lastWord.endTime,
        }
      );
      if (isIntersect) {
        attrs[`data-in-agenda-${agenda.id}`] = true;
      }
    });
    return attrs;
  }, [agendas, isUnfix, paragraph, controller]);

  const QAbgColor = useMemo(() => {
    if (!qnaActive) return "";
    if (isHighlight) {
      return "var(--Fill_Background_Light)";
    }
    if (qnaActive === QnaActive.question || qnaActive === QnaActive.questionAndanswer) {
      return "var(--Fill_Background_Light)";
    }
    if (qnaActive === QnaActive.answer) {
      return "var(--Fill_Background_Light)";
    }
    return "";
  }, [isHighlight, qnaActive]);

  const QAfontColor = useMemo(() => {
    if (!qnaActive) return "";
    if (
      isHighlight &&
      (qnaActive === QnaActive.question || qnaActive === QnaActive.questionAndanswer)
    ) {
      return "var(--Text_Primary)";
    }
    if (isHighlight && qnaActive === QnaActive.answer) {
      return "var(--Text_Primary)";
    }
    return "var(--Text_Primary)";
  }, [isHighlight, qnaActive]);

  const QAMarkText = useMemo(() => {
    if (!qnaActive) return "";
    if (qnaActive === QnaActive.question) {
      return "问";
    }
    if (qnaActive === QnaActive.answer) {
      return "答";
    }
    return <span style={{ transform: "scale(0.8)" }}>问答</span>;
  }, [qnaActive]);

  const QAMark = useMemo(() => {
    if (qnaModel === QAModel.questionAndanswer && qnaActive) {
      return (
        <QAMarkStyled
          bgColor={QAbgColor}
          fontColor={QAfontColor}
          large={qnaActive === QnaActive.questionAndanswer}
        >
          {QAMarkText}
        </QAMarkStyled>
      );
    }

    // 这里暂时不需要展示了
    // if (!qnaActive && qnaModel === QAModel.questionAndanswer && (isAnaQ || isAnaQa)) {
    //   return (
    //     <QAMarkStyled
    //       bgColor={'rgba(231,231,251,1)'}
    //       fontColor={'rgba(96,92,229,1)'}
    //       large={isAnaQa}
    //     >
    //       {isAnaQ ? '问' : '问答'}
    //     </QAMarkStyled>
    //   );
    // }
    return null;
  }, [qnaActive, QAbgColor, QAfontColor, qnaModel, isAnaQ, isAnaQa]);

  return (
    <Wrapper
      ref={paragraphRef}
      sticky={isUnfix ? theme.unfixParagraphContentSticky : false}
      data-paragraph-id={pid}
      data-paragraph-is-unfix={isUnfix}
      visible={visible}
      onMouseEnter={handleMouseEnter}
      onMouseLeave={handleMouseLeave}
      {...agendasAttrs}
    >
      {renderBeforeMask && (
        <Mask>
          <MaskInner>{renderBeforeMask()}</MaskInner>
        </Mask>
      )}
      <ParagraphWrapper isUnfix={isUnfix} data-e2e-test-id="trans_paragraph_unfix_div">
        <ParagraphHeading
          getParagraphContainer={getParagraphContainer}
          /* 当有renderBeforeMask的时候，需要heading有个背景色 */
          showBackground={Boolean(renderBeforeMask)}
          isUnfix={isUnfix}
          emptyUnfix={emptyUnfix}
          controller={controller}
          pid={pid}
          paragraph={paragraph}
          words={words}
          readonly={readonly}
          defaultSpeakerReadonly={defaultSpeakerReadonly}
          isParagraphMouseEnter={isMouseEnter}
          isEditorFocus={editorFocus}
          translateMode={translateMode}
          textPolishMode={textPolishMode}
          shareDisabled={shareDisabled}
        />
        <ParagraphStyledWrapper>
          {/* TODO QA style */}
          {QAMark}
          <ParagraphStyled
            className="tignwu2_paragraphStyled"
            ref={containerRef}
            qnaActive={qnaActive}
            isHighlight={isHighlight}
            onClick={emptyUnfix ? handleClick : undefined}
            isUnfix={isUnfix}
            focus={editorFocus}
            showOutline={showOrigin && !readonly}
            fileModel={controller.getFileModel()}
          >
            {originNode}
            {translateNode}
            {textPolishNode}
          </ParagraphStyled>
        </ParagraphStyledWrapper>
      </ParagraphWrapper>
    </Wrapper>
  );
});
