// *** 类型定义相关 ***
import { iDocTransResult } from '../../docBase/docBase.type';
import { eDocSpeakerSplitStatus, iDocTagData } from '../../docTag/docTag.type';
import { eDocScene } from '../../document.baseType';
import { iDocumentState } from '../../document.type';
import { iDocSpeaker, iDocSpeakerAPIData } from '../docSpeaker.type';
import { docTagActions } from '../../docTag/docTag.operator';
import * as docSpeakerActions from './docSpeaker.actions';

// *** 服务相关 ***
// *** 工具相关 ***
import { delay } from '../../../utils/delay.util';
import * as docSpeakerUtils from '../docSpeaker.utils';

const INTERVAL_SHORT_TIME = 50;

export const docSpeakerEffects = {
  // 初始化发言人数据
  *initDocSpeakerDataEffect(
    action: ReturnType<typeof docSpeakerActions.initDocSpeakerDataAction>,
    { select, take, put },
  ) {
    const { docId, docScene } = action.payload;
    // docTag 数据(并发请求，不一定更新完成)
    let { docTagData }: { docTagData?: iDocTagData } = yield select(
      (state: { documentModel: iDocumentState }) => ({
        docTagData: state.documentModel.docTagDataMap[docId],
      }),
    );

    // 非盒子请求tag
    if (docTagData === undefined) {
      // 确保 DocTag 返回数据
      yield (function* () {
        while (true) {
          yield take(docTagActions.updateDocTagDataAction(null as any).type);
          docTagData = yield select(
            (state: { documentModel: iDocumentState }) =>
              state.documentModel.docTagDataMap[docId],
          );
          if (docTagData) return docTagData;
          yield delay(INTERVAL_SHORT_TIME);
        }
      })();
    }

    const { identify, roleSplitTip, roleSplitNum } = docTagData || {};

    let speakersSplitIsOpen = false;
    let speakersSplitIsLoading = false;
    // 文档纪要，需要计算是否开启发言人区分
    if ([eDocScene.trans, eDocScene.transShare].includes(docScene)) {
      // 1. 正常纪要页内开启发言人区分
      if (roleSplitTip !== undefined) {
        // 发言人区分是否开启(开启、区分中、有结果)
        speakersSplitIsOpen =
          roleSplitTip !== undefined &&
          [
            eDocSpeakerSplitStatus.open,
            eDocSpeakerSplitStatus.spliting,
            eDocSpeakerSplitStatus.result,
          ].includes(roleSplitTip);
        // 发言人区分是否加载中
        speakersSplitIsLoading =
          speakersSplitIsOpen &&
          roleSplitTip === eDocSpeakerSplitStatus.spliting;
      }
      // 2. 其他预开启场景
      if (
        roleSplitTip === undefined &&
        roleSplitNum !== undefined &&
        [0, 1, 2].includes(roleSplitNum)
      ) {
        speakersSplitIsOpen = true;
      }
    }

    // 发言人区分类型
    const speakersSplitType =
      !roleSplitNum || roleSplitNum === -1 ? 0 : roleSplitNum;
    // console.log(
    //   'speakerData:inner: speakersSplitIsOpen,speakersSplitType,speakersSplitIsLoading',
    //   speakersSplitIsOpen,
    //   speakersSplitType,
    //   speakersSplitIsLoading,
    // );

    // 计算发言人列表数据
    let editedSpeakerList: iDocSpeaker[] = [];
    const speakerAvatarLength = docSpeakerUtils.getSpeakerAvatarLength(); // 发言人头像长度
    let speakerAvatarLastIndex: number | undefined; // 发言人头像当前下标

    // 智能区分发言人(仅从 identify 解析，后续有变更也是)
    if (roleSplitNum === 100 && identify) {
      const speakerUserInfoMap: iDocSpeakerAPIData = JSON.parse(
        identify || '{}',
      );
      // 更新发言人数据
      return yield put(
        docSpeakerActions.initDocSpeakerDataReducerAction({
          docId,
          docScene,
          data: {
            speakersSplitIsOpen,
            speakersSplitIsLoading,
            speakersSplitType,
            speakerAvatarLength,
            speakerAvatarLastIndex,
            speakersData: editedSpeakerList,
          },
        }),
      );
    }

    // 1. 发言人已经编辑，已有发言人 Map 映射数据，使用映射数据初始化发言人
    if (identify) {
      const speakerUserInfoMap: iDocSpeakerAPIData = JSON.parse(
        identify || '{}',
      );

      const computeSpeakerData = docSpeakerUtils.resolveSpeakerAPIData(
        speakerUserInfoMap,
        speakersSplitIsOpen,
      );
      editedSpeakerList = computeSpeakerData.speakerList;
      speakerAvatarLastIndex = computeSpeakerData.speakerAvatarLastIndex;
    }

    // 获取 Doc 基础数据
    const { docResult }: { docResult: string } = yield select(
      (state: { documentModel: iDocumentState }) => ({
        docResult: state.documentModel.docBaseDataMap[docId]?.result || '',
      }),
    );
    // 2. (否则)获取原文内发言人数据(未区分发言人未编辑、已区分发言人未编辑)
    const tranResult: iDocTransResult = JSON.parse(docResult);
    const paraphSpeakerList = docSpeakerUtils.resolveSpeakersFromParagraph(
      tranResult,
      // 原文区
      speakersSplitIsLoading ? false : speakersSplitIsOpen,
    );
    // console.log('speakerData:paraphSpeakerList', paraphSpeakerList);

    // 没有编辑过的发言人，仅从原文区取既可
    if (!editedSpeakerList.length) {
      editedSpeakerList = Array.from(paraphSpeakerList);
    } else {
      // 原文编辑发言人 & 之后区分发言人 => 取编辑数据、原文数据做合并
      for (let i = 0; i < paraphSpeakerList.length; i++) {
        const speaker = paraphSpeakerList[i];
        let modifyIndex;
        const identifySpeaker = editedSpeakerList.find((item, index) => {
          if (item.uid === speaker.uid) {
            modifyIndex = index;
            return true;
          }
          return false;
        });
        if (!identifySpeaker) {
          // 1. 只在原文区的发言人，合并到编辑后的发言人列表
          editedSpeakerList.push(speaker);
        } else {
          // 2. 都存在的发言人，做数据合并（解决创建副本后tag数据问题）
          // eslint-disable-next-line no-lonely-if
          if (modifyIndex !== undefined) {
            const editSpeaker = editedSpeakerList[modifyIndex];
            if (!editSpeaker.avatarUrl) {
              // 没有头像
              editedSpeakerList.splice(modifyIndex, 1, {
                ...speaker,
                ...editSpeaker,
              });
            }
          }
        }
      }
    }

    // 更新发言人数据
    yield put(
      docSpeakerActions.initDocSpeakerDataReducerAction({
        docId,
        docScene,
        data: {
          speakersSplitIsOpen,
          speakersSplitIsLoading,
          speakersSplitType,
          speakerAvatarLength,
          speakerAvatarLastIndex,
          speakersData: editedSpeakerList,
        },
      }),
    );
  },
};
