import {
  isCustomerServiceMessage,
  isThinkingMessage,
  isMessageInvisible,
  clearChatStorage,
} from './utils/index';
import TUIChatEngine, {
  TUIChatService,
  TUIConversationService,
  IMessageModel,
  TUITranslateService,
  SendMessageParams,
  SendMessageOptions,
  TUIUserService,
  TUIStore,
  StoreName,
  func,
} from './@aidesk/uikit-engine';
import Log from './utils/logger';
import { version } from './package.json'
import { Toast, TOAST_TYPE } from "./components/common/Toast/index-uniapp";
import { vueVersion } from "./adapter-vue-uniapp";
import { switchReadStatus, transferToTaskFlow, transferToHuman, validateUserID } from "./utils/utils";
import state from "./utils/state";
import { ITransferToTaskFlowModel, ITransferToHumanModel } from "./interface";

interface IInitWithProfile {
  SDKAppID: number,
  userID: string,
  userSig: string,
  nickName?: string,
  avatar?: string,
  customerServiceID?: string,
  scene?: string;
  clientCustomData?: string,
}

interface IProfile {
  nick?: string,
  avatar?: string,
}

export default class TUICustomerServer {
  private isLoggedIn: boolean;
  static instance: TUICustomerServer;
  private customerServiceIDList: any[];
  private currentCustomerServiceID: string;
  private loggedInUserID: string;
  private myProfile: IProfile;
  private bindOnActionConversation: func;
  private paramsForActiveAgain: any;
  private _scene: string;
  private clientCustomData: string;
  constructor() {
    this.customerServiceIDList = ['@customer_service_account'];
    this.currentCustomerServiceID = this.customerServiceIDList[0];
    this.isLoggedIn = false;
    this.loggedInUserID = '';
    this.myProfile = {};
    this.bindOnActionConversation = this.onActiveConversation.bind(this);
    this._scene = '';
    this.clientCustomData = '';
  }

  static getInstance(): TUICustomerServer {
    if (!TUICustomerServer.instance) {
      TUICustomerServer.instance = new TUICustomerServer();
    }
    return TUICustomerServer.instance;
  }

  private async loginCustomerUIKit(SDKAppID:number, userID:string, userSig:string) {
    clearChatStorage(SDKAppID, userID);
    return TUIChatEngine.login({
      SDKAppID,
      userID,
      userSig,
      useUploadPlugin: true,
      scene: this._scene,
    }).then(() => {
      Log.i(`login success. userID:${userID}`);
      this.isLoggedIn = true;
      this.loggedInUserID = userID;

      TUIStore.watch(StoreName.CUSTOM, {
        'activeConversation': this.bindOnActionConversation,
      });

      this.switchConversation(`C2C${this.currentCustomerServiceID}`);
      switchReadStatus(state.get('showReadStatus'));
      TUIChatEngine.chat.callExperimentalAPI('isFeatureEnabledForStat', Math.pow(2, 42));
    })
    .catch((error) => {
      Toast({
        message: TUITranslateService.t('TUIChat.登录失败'),
        type: TOAST_TYPE.ERROR,
        duration: 30000,
      });
      Log.l(error);
    })
  }

  public async init(SDKAppID:number, userID:string, userSig:string) {
    Log.l(`TUICustomerServer.init vue:${vueVersion} version:${version} SDKAppID:${SDKAppID} userID:${userID}` +
      ` isLoggedIn:${this.isLoggedIn} loggedInUserID:${this.loggedInUserID} currentCustomerServiceID:${this.currentCustomerServiceID}`);

    if (userID) {
      const ret = validateUserID(userID);
      if (ret > 0) {
        // Ensure i18n is configured first.
        setTimeout(() => {
          let reason = '';
          if (ret === 1) {
            reason = TUITranslateService.t("AIDesk.userID 只能包含可打印 ASCII 字符");
          } else if (ret === 2) {
            reason = TUITranslateService.t("AIDesk.userID 不能包含'administrator'");
          } else if (ret === 3) {
            reason = TUITranslateService.t("AIDesk.userID 长度不能超过45字节");
          }
          Toast({
            message: reason,
            type: TOAST_TYPE.ERROR,
            duration: 30000,
          });
        }, 500);
        return;
      }
    }

    if (this.isLoggedIn) {
      if (this.loggedInUserID === userID) {
        await this.switchConversation(`C2C${this.currentCustomerServiceID}`);
        return;
      }
      return this.unInit().finally(() => {
        this.isLoggedIn = false;
        this.loginCustomerUIKit(SDKAppID, userID, userSig);
      });
    } else {
      return this.loginCustomerUIKit(SDKAppID, userID, userSig);
    }
  }

  public async initWithProfile(options: IInitWithProfile) {
    const { SDKAppID, userID, userSig, nickName, avatar, customerServiceID, scene, clientCustomData } = options;
    Log.l(`TUICustomerServer.initWithProfile version:${version} scene:${scene}`);

    if (nickName) {
      // chat 个人资料的昵称是 nick
      this.myProfile.nick = nickName;
    }

    if (avatar) {
      this.myProfile.avatar = avatar;
    }

    if (customerServiceID) {
      this.currentCustomerServiceID = customerServiceID;
      if (!this.customerServiceIDList.includes(this.currentCustomerServiceID)) {
        this.customerServiceIDList.push(this.currentCustomerServiceID);
      }
    }

    if (scene) {
      this._scene = scene;
    } else {
      if (vueVersion === 2) {
        this._scene = 'aidesk-customer-uni-vue2';
      } else if (vueVersion === 3) {
        this._scene = 'aidesk-customer-uni-vue3';
      }
    }

    if (clientCustomData) {
      this.clientCustomData = clientCustomData;
    } else {
      this.clientCustomData = '';
    }

    return this.init(SDKAppID, userID, userSig);
  }

  public async unInit() {
    Log.l(`TUICustomerServer.unInit`);
    TUIStore.unwatch(StoreName.CUSTOM, {
      'activeConversation': this.bindOnActionConversation,
    });
    this.isLoggedIn = false;
    // 清理预加载缓存
    let preloadedEmojiMap = state.get('preloadedEmojiMap');
    if (preloadedEmojiMap) {
      preloadedEmojiMap.clear();
    }
    return TUIChatEngine.logout();
  }

  public sendTextMessage(options: SendMessageParams, sendMessageOptions?: SendMessageOptions) {
    return TUIChatService.sendTextMessage(options, sendMessageOptions);
  }

  public sendCustomMessage(options: SendMessageParams, sendMessageOptions?: SendMessageOptions) {
    return TUIChatService.sendCustomMessage(options, sendMessageOptions);
  };

  public changeLanguage(language: string) {
    return TUITranslateService.changeLanguage(language).then(() => {
      Log.i(`language changed to ${language}`);
    });
  }

  public getLoggedInUserID() {
    return this.loggedInUserID;
  }

  // Determine if the current session is a customer service session
  public isCustomerConversation(conversationID: string) {
    const userID = (conversationID && conversationID.slice(3)) || '';
    return this.customerServiceIDList.indexOf(userID) > -1;
  }

  // Determine if the current message is a customer service message
  public isCustomerServicePluginMessage(message: IMessageModel) {
    if (!message || !this.isCustomerConversation(message.conversationID)) {
      return false;
    }
    if (isThinkingMessage(message)) {
      return false;
    }
    return isCustomerServiceMessage(message) || isMessageInvisible(message);
  }

  public onGetExtension(extensionID: string) {
    if (extensionID === TUIConstants.TUIContact.EXTENSION.CONTACT_LIST.EXT_ID) {
      return [
        {
          weight: 0,
          icon: '',
          text: '智能客服',
          data: {
            name: 'customer',
            accountList: this.customerServiceIDList,
          },
        },
      ];
    }
  }

  /**
   * Set up multiple customer service ID
   * @param list
   */
  public setCustomerServiceIDList(list: Array<string>) {
    if (!Array.isArray(list) || list.length === 0) {
      return;
    }
    this.customerServiceIDList = list;
    this.currentCustomerServiceID = list[0];
    Log.i(`TUICustomerServer.setCustomerServiceIDList`, this.customerServiceIDList);
  }

  public transferToTaskFlow(options: ITransferToTaskFlowModel) {
    transferToTaskFlow(this.currentCustomerServiceID, options.taskFlowID, options.description);
  }

  public transferToHuman(options: ITransferToHumanModel) {
    transferToHuman(this.currentCustomerServiceID, options.groupID, options.specificMemberList, options.description);
  }

  /**
   * Clear conversation unread count
   * @param conversationID
   */
  public clearConversationUnreadCount(conversationID?: string) {
    Log.l(`TUICustomerServer.clearConversationUnreadCount conversationID:${conversationID}`);
    if (conversationID) {
      TUIConversationService.setMessageRead(conversationID);
    } else {
      TUIConversationService.setMessageRead('C2C@customer_service_account');
    }
  }

  private onActiveConversation(params: any) {
    if (!params) {
      return;
    }
    Log.l(`TUICustomerServer.onActiveConversation options:`, params);
    if (this.isCustomerConversation(params.conversationID)) {
      // 如果有资料，确保资料更新完成（或失败）后再激活会话服务流
      if (Object.keys(this.myProfile).length > 0) {
        Log.l(`TUICustomerServer.onActiveConversation updateMyProfile:${JSON.stringify(this.myProfile)}`);
        TUIUserService.updateMyProfile({...this.myProfile}).finally(() => {
          this.activeServiceFlow(params);
        });
      } else {
        this.activeServiceFlow(params);
      }
    }
  }

  private async switchConversation(conversationID: string) {
    const ret = await TUIConversationService.switchConversation(conversationID);
    // -100002 即要切换的会话 ID 跟当前已打开的会话 ID 相同，这个时候我们重发 src 7，确保服务流状态正确
    if (ret.code === -100002) {
      this.activeServiceFlow(this.paramsForActiveAgain);
    }
  }

  // 激活会话服务流
  private activeServiceFlow(params: any) {
    Log.l(`TUICustomerServer.activeServiceFlow params:`, params, `clientCustomData:${this.clientCustomData}`);
    this.paramsForActiveAgain = { ...params };
    TUIChatService.sendCustomMessage({
      to: params.conversationID.slice(3),
      conversationType: TUIChatEngine.TYPES.CONV_C2C,
      payload: {
        data: JSON.stringify({
          src: '7',
          customerServicePlugin: 0,
          triggeredContent: {
            language: params.robotLang || '',
            clientCustomData: this.clientCustomData,
          },
        }),
      },
    }, { onlineUserOnly: true });
    Log.w(`TUICustomerServer.activeServiceFlow src 7 sent`);
  }
}
