import {
  eAPIStatus,
  eDocScene,
  eTransLangTranslateMap,
  iDocDataUpdateBasePayload,
  iDocIDType,
} from '../../document.baseType';
import { iDocumentState } from '../../document.type';

import { iDocBaseData } from '../../docBase/docBase.type';
import * as docBaseUtils from '../../docBase/docBase.utils';
import { iDocTagData } from '../../docTag/docTag.type';
import { iDocTranslateData } from '../docTranslate.type';
import { delay } from '../../../utils/delay.util';
import { docTagActions } from '../../docTag/docTag.operator';
import * as docTranslateActions from './docTranslate.actions';
import { originApiTranslateToLocalTransfer } from './docTranslate.dataTransfer';

const INTERVAL_SHORT_TIME = 50; // 轮询短时间

// DocTranslate Effects
export const docTranslateEffects = {
  /** 对外 Action */
  // 初始化 Doc 翻译
  *initDocTranslateDataEffect(
    action: ReturnType<typeof docTranslateActions.initDocTranslateDataAction>,
    { take, call, select, put },
  ) {
    const { docId, docScene } = action.payload;
    // 1. 获取 Doc 基础数据
    const { docBaseData }: { docBaseData: iDocBaseData } = yield select(
      (state: { documentModel: iDocumentState }) => ({
        docBaseData: state.documentModel.docBaseDataMap[docId],
      }),
    );
    // 2. docTag 数据(并发请求，不一定更新完成)
    let { docTagData }: { docTagData?: iDocTagData } = yield select(
      (state: { documentModel: iDocumentState }) => ({
        docTagData: state.documentModel.docTagDataMap[docId],
      }),
    );
    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 docBaseTagData = docBaseUtils.getDocBaseTag(docBaseData);
    const {
      translateSwitch: docBaseTranslateSwitch,
      lang: docBaseOriginLanguageValue,
      transTargetValue: docBaseTransTargetValue,
      translateLanguageConf: docBaseTranslateLanguageConf,
    } = docBaseTagData!;

    // 个人查看纪要，单独获取翻译目标语言
    let serverDocBaseTransTargetValue = docBaseTransTargetValue;
    if (docBaseTranslateSwitch === 1 && docScene === eDocScene.trans) {
      const translateTargetLanguage = docBaseTransTargetValue;
      if (
        translateTargetLanguage &&
        eTransLangTranslateMap[translateTargetLanguage]
      ) {
        serverDocBaseTransTargetValue = eTransLangTranslateMap[
          translateTargetLanguage
        ] as unknown as number;
      }
    }

    const {
      originLanguageValue: docTagOriginLanguageValue,
      transTargetValue: docTagTransTargetValue,
      translateLanguageConf: docTagTranslateLanguageConf,
      translateSwitch: docTagTranslateSwitch,
      translateLoading: docTagTranslateLoading,
    } = docTagData!;
    const translateIsOpen = !!(docTagTranslateSwitch || docBaseTranslateSwitch); // 翻译是否开启
    const translateSourceLanguage =
      docTagOriginLanguageValue ||
      Number(eTransLangTranslateMap[docBaseOriginLanguageValue]); // 翻译源语言
    const translateTargetLanguage =
      docTagTransTargetValue || serverDocBaseTransTargetValue; // 翻译目标语言
    const translateDisplayMode =
      docTagTranslateLanguageConf || docBaseTranslateLanguageConf || 2; // 翻译展示模式
    const docTranslateData: iDocTranslateData = {
      translateIsOpen,
      translateSourceLanguage,
      translateTargetLanguage,
      translateDisplayMode,
      translateIsServerLoading: !!docTagTranslateLoading, // 翻译是否加载中不依赖服务端状态
    };
    // 更新翻译数据
    yield put(
      docTranslateActions.updateDocTranslateDataAction({
        docId,
        docScene,
        data: {
          ...docTranslateData,
          originTranslate: originApiTranslateToLocalTransfer(
            docBaseData.translatedDoc,
          ),
          translateOriginTargetLoading: 1,
        },
      }),
    );
    // 检测并执行翻译更新
    return yield put({
      type: 'checkAndExecuteDocTranslate',
      payload: { docId, docScene },
    });
  },
  // 更新翻译目标语言
  *changeDocTranslateTargetLangEffect(
    action: ReturnType<
      typeof docTranslateActions.changeDocTranslateTargetAction
    >,
    { put, select, call },
  ) {
    const { docId, docScene } = action.payload;
    const setTranslateTargetLang = action.payload.data!;
    // 根据翻译状态，执行翻译逻辑
    const docTranslateData: iDocTranslateData = yield select(
      (state: { documentModel: iDocumentState }) => {
        return state.documentModel.docTranslateDataMap[docId];
      },
    );
    const {
      // translateDisplayMode,
      // translateSourceLanguage,
      // translateIsLoading,
    } = docTranslateData;
    // 更新目标语言设置
    yield put(
      docTranslateActions.updateDocTranslatePartialDataAction({
        docId,
        docScene,
        data: {
          translateTargetLanguage: setTranslateTargetLang,
          translateBigModelTargetLoading: -1,
          translateOriginTargetLoading: -1,
          bigModelTranslate: {},
        },
      }),
    );

    // 检测翻译状态
    return yield put({
      type: 'checkAndExecuteDocTranslate',
      payload: { docId, docScene },
    });
  },
  // 更新翻译展示模式
  *changeDocTranslateDisplayEffect(
    action: ReturnType<
      typeof docTranslateActions.changeDocTranslateDisplayAction
    >,
    { put },
  ) {
    const { docId, docScene } = action.payload;
    const setTranslateDisplayMode = action.payload.data!;
    // 更新翻译展示模式
    yield put(
      docTranslateActions.updateDocTranslatePartialDataAction({
        docId,
        docScene,
        data: {
          translateDisplayMode: setTranslateDisplayMode,
        },
      }),
    );
    yield put({
      type: 'updateDocTranslateAndDocTag',
      payload: {
        docId,
        docScene,
        data: {
          translateDisplayMode: Number(setTranslateDisplayMode),
        },
      },
    });
    // // 检测翻译状态
    // return yield put({
    //   type: 'checkAndExecuteDocTranslate',
    //   payload: { docId, docScene },
    // });
  },
  /** 对内 Action */
  // 检测执行翻译操作(开启、关闭翻译，同步 Tag 等)
  *checkAndExecuteDocTranslate(
    { payload }: { payload: { docId: iDocIDType; docScene: eDocScene } },
    { select, call, put },
  ) {
    const { docId, docScene } = payload;
    // 根据翻译状态，执行翻译逻辑
    const docTranslateData: iDocTranslateData = yield select(
      (state: { documentModel: iDocumentState }) => {
        return state.documentModel.docTranslateDataMap[docId];
      },
    );
    const {
      translateIsOpen,
      translateSourceLanguage,
      translateTargetLanguage,
      translateIsLoading, // 内部逻辑，与服务端无关系
    } = docTranslateData;

    // 1. 已在加载中，不需要处理
    if (translateIsLoading) {
      return eAPIStatus.LOADING;
    }
    // 2. 翻译开启
    if (
      translateIsOpen &&
      translateSourceLanguage !== translateTargetLanguage
    ) {
      yield put(
        docTranslateActions.updateDocTranslatePartialDataAction({
          docId,
          docScene,
          data: {
            translateOriginTargetLoading: 0,
            translateBigModelTargetLoading: 0,
          },
        }),
      );
    }
  },
  // 更新翻译 & DocTag
  *updateDocTranslateAndDocTag(
    action: { payload: iDocDataUpdateBasePayload<Partial<iDocTranslateData>> },
    { put },
  ) {
    const { docId, docScene, data } = action.payload;
    // 1.更新 DocTranslate 数据
    yield put(
      docTranslateActions.updateDocTranslatePartialDataAction({
        docId,
        docScene,
        data: data!,
      }),
    );
    if ([eDocScene.transShare].includes(docScene)) return;
    // 2. 更新 DocTag
    const {
      translateIsOpen,
      translateSourceLanguage,
      translateTargetLanguage,
      translateDisplayMode,
      translateIsLoading,
    } = data!;
    // 更新 DocTag 数据
    const docTagData: Partial<iDocTagData> = {};
    if (translateIsOpen !== undefined)
      docTagData.translateSwitch = translateIsOpen ? 1 : 0;
    if (translateSourceLanguage !== undefined)
      docTagData.originLanguageValue = translateSourceLanguage;
    if (translateTargetLanguage !== undefined)
      docTagData.transTargetValue = translateTargetLanguage;
    if (translateDisplayMode !== undefined)
      docTagData.translateLanguageConf = translateDisplayMode;
    if (translateIsLoading !== undefined)
      docTagData.translateLoading = translateIsLoading ? 1 : 0;

    yield put(
      docTagActions.updateDocTagAndSyncTagAction({
        docId,
        docScene,
        data: docTagData,
      }),
    );
  },

  // 更新翻译数据
  *updateDocTranslatePartialData(
    action: ReturnType<
      typeof docTranslateActions.updateDocTranslatePartialQueryDataAction
    >,
    { put },
  ) {
    const { docId, docScene, data } = action.payload;
    yield put(
      docTranslateActions.updateDocTranslatePartialDataAction({
        docId,
        docScene,
        data: { ...data },
      }),
    );
  },
};
