/*
 *
 *  Copyright (c) 2025 Huawei Device Co., Ltd.
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

import { abilityAccessCtrl, bundleManager } from '@kit.AbilityKit';
import { rpc } from '@kit.IPCKit';
import { curves } from '@kit.ArkUI';
import hiboardIPCService from '../idlService/HiboardRemoteService';
import { CommonUtil } from '../util/CommonUtil';
import { feedbackLogger as log } from '../util/FeedBackLogUtil';
import { AgentServiceAssistantView } from '../pages/base/AgentServiceAssistantView';
import { AgentServiceAssistantData, IAgentCardFunctionElement, FunctionType } from '../common/bean/AgentServiceInfo';
import { HaModule } from '../common/constants/HaReportConstants';
import { PreferenceStore } from '../dao/PreferenceStore';
import { CloudConfigDao } from '../dao/CloudConfigDao';
import { CommonContants } from '../common/constants/CommonContants';
import { JumpInfo } from '../common/bean/IIntelligentCommonData';
import JumpController from './JumpController';
import RemoteCallbackManager from '../idlService/RemoteCallbackManager';
import { Module, ModuleParams } from '../idlService/IpcCommon';
import IntelligentCompatibilityChecker from './IntelligentCompatibilityChecker';

const TAG: string = 'AgentServiceAssistantController';

// 开关开启标识。
const SWITCH_OPEN_TAG: string = 'true';
// 跳转信息标识。
const JUMP_INFO_LIST_TAG: string = 'jumpInfoList';
// 智能体服务助手 FormItemID
const FORM_ITEM_ID = 'agentCard';
// 引导语轮播间隔
const GUIDES_SWIPE_TIME_INTERVAL: number = 3000; // 3s

// 智能体查询数据标识。
export const AGENT_QUERY_INFO_TAG: string = 'agentQueryInfo';

/**
 * 智能体服务助手开关标识。
 */
export const enum AgentServiceAssistantSwitch {
  // 智能体服务助手总开关标识。
  GENERAL_SWITCH = 'serviceAssistantSwitchStatus',
  // 智能体服务助手云控开关标识。
  CLOUD_SWITCH = 'isEnableAgentServiceAssistant',
}

/**
 * 智能体服务助手版本标识。
 */
const enum AgentServiceAssistantVersion {
  /**
   * 修改点:
   * 1. 初始版本,添加了智能体服务助手的基本代码。
   */
  VERSION_ZERO = 0,
}

/**
 * 智能体服务助手公共事件请求参数标识。
 */
const enum AgentServiceAssistantRequestParam {
  // 能力支持标识
  IS_SERVICE_ASSISTANT_SUPPORTED = 'isServiceAssistantSupported',
  // 版本标识
  VERSION = 'version',
}

/**
 * 智能体服务助手公共事件消息命令。
 */
const enum AgentServiceAssistantCommend {
  REFRESH = 'refresh',
  CLEAR = 'clear',
}

/**
 * 智能体服务助手Controller类,用于控制数据刷新和处理业务逻辑。
 */
export class AgentServiceAssistantController {
  private static instance: AgentServiceAssistantController;
  private view?: AgentServiceAssistantView;
  private isHomeOnFocus: boolean = false;

  private isSwitchOn: boolean = true;
  private isCloudSwitchOn: boolean = false;

  private currentGuideExposeTime: number = 0;
  private guidesTimeoutId: number | undefined = undefined;
  private guidesSwipeInterval: number = GUIDES_SWIPE_TIME_INTERVAL;

  /**
   * 私有构造函数,单例模式。
   */
  private constructor() {
  }

  /**
   * 获取单例。
   *
   * @returns 单例。
   */
  public static getInstance(): AgentServiceAssistantController {
    if (!AgentServiceAssistantController.instance) {
      AgentServiceAssistantController.instance = new AgentServiceAssistantController();
      // 注册通信回调
      RemoteCallbackManager.registerCallback(Module.AGENT_SERVICE_ASSISTANT,
        (command: string, result: Record<string, string | object>, data: rpc.MessageSequence, code: number):
          Promise<void> => AgentServiceAssistantController.instance.onRemoteMessage(command, result));
    }
    return AgentServiceAssistantController.instance;
  }

  /**
   * 智能体服务助手组件AboutToAppear事件处理回调。
   *
   * @param view 智能体服务助手组件。
   */
  public async onViewAboutToAppear(view: AgentServiceAssistantView): Promise<void> {
    this.view = view;
    await this.switchInit();
  }

  /**
   * 检查当前是否使能智能体服务助手。
   *
   * @returns true,使能;false,不使能。
   */
  private isEnabled() {
    if (!IntelligentCompatibilityChecker.isSupportServiceAssistant()) {
      log.showWarn(TAG, `isEnabled, intelligent does not support yet`);
      return false;
    }
    if (!this.isCloudSwitchOn) {
      log.showWarn(TAG, `isEnabled, cloud switch is off`);
      return false;
    }
    if (!this.isSwitchOn) {
      log.showWarn(TAG, `isEnabled, switch is off`);
      return false;
    }
    return true;
  }

  /**
   * 开关初始化。
   * 包含用户设置开关和运营云控开关。
   */
  private async switchInit() {
    try {
      this.isSwitchOn =
        (await PreferenceStore.getInstance()
          .get(CommonContants.SERVICE_ASSISTANT_SWITCH, true, HaModule.SETTING) as boolean) ?? true;
      this.isCloudSwitchOn =
        (await CloudConfigDao.get4HCloudConfigByKey(AgentServiceAssistantSwitch.CLOUD_SWITCH) === SWITCH_OPEN_TAG);
      AppStorage.setOrCreate<boolean>(AgentServiceAssistantSwitch.GENERAL_SWITCH, this.isEnabled());

      IntelligentCompatibilityChecker.registerVersionChangeCallBack(TAG, () => {
        this.updateCloudSwitch();
      });

      log.showInfo(TAG, `switchInit, isSwitchOn: ${this.isSwitchOn}, isCloudSwitchOn: ${this.isCloudSwitchOn}`);
    } catch (e) {
      log.showError(TAG, `switchInit failed, code: ${e?.code}, message: ${e?.message}`);
      return;
    }
  }

  /**
   * 获取智能体服务助手公共事件请求参数。
   *
   * @returns 公共事件请求参数。
   */
  public getRequestModuleParams(): ModuleParams {
    let moduleParams = new ModuleParams();
    moduleParams.module = Module.AGENT_SERVICE_ASSISTANT;
    moduleParams.params = {} as Record<string, string | number | boolean | string[]>;

    moduleParams.params[AgentServiceAssistantRequestParam.IS_SERVICE_ASSISTANT_SUPPORTED] = true;
    moduleParams.params[AgentServiceAssistantRequestParam.VERSION] = AgentServiceAssistantVersion.VERSION_ZERO;

    return moduleParams;
  }

  /**
   * 负一屏消息处理回调。
   *
   * @param result 消息数据。
   */
  public async onRemoteMessage(command: string, result: Record<string, string | object>): Promise<void> {
    if (!this.view) {
      log.showError(TAG, `onRemoteMessage, thie view is empty`);
      return;
    }

    if (!command) {
      log.showError(TAG, `commend is empty`);
      return;
    }

    switch (command) {
      case AgentServiceAssistantCommend.REFRESH:
        let dataStr: string = result.assistantDataStr as string;
        this.refreshAssistantData(dataStr);
        return;
      case AgentServiceAssistantCommend.CLEAR:
        this.clearAssistantData();
        return;
      default:
        log.showError(TAG, `onRemoteMessage, invalide commend ${command}`);
        return;
    }
  }

  /**
   * 更新智能体服务助手云控开关。
   */
  public async updateCloudSwitch() {
    this.isCloudSwitchOn =
      (await CloudConfigDao.get4HCloudConfigByKey(AgentServiceAssistantSwitch.CLOUD_SWITCH) === SWITCH_OPEN_TAG);
    log.showInfo(TAG, `updateCloudSwitch, cloud switch: ${this.isCloudSwitchOn}`);
    AppStorage.setOrCreate<boolean>(AgentServiceAssistantSwitch.GENERAL_SWITCH, this.isEnabled());
  }

  /**
   * 更新智能体服务助手常驻卡开关。
   */
  public updateSwitch(isOn: string | undefined): void {
    this.isSwitchOn = isOn === SWITCH_OPEN_TAG;
    log.showInfo(TAG, `updateSwitch, isOn: ${this.isSwitchOn}`);
    if (this.view && !this.isSwitchOn) {
      this.view.isMenuOpen = false;
    }
    animateTo({
      delay: 300,
      curve: curves.springMotion(0.416, 1)
    }, () => {
      AppStorage.setOrCreate<boolean>(AgentServiceAssistantSwitch.GENERAL_SWITCH, this.isEnabled());
    });
    PreferenceStore.getInstance().put(CommonContants.SERVICE_ASSISTANT_SWITCH, this.isSwitchOn, HaModule.SETTING);
  }

  /**
   * 设置焦点状态.
   *
   * @param status 首页是否展示
   * */
  public setFocus(status: boolean) {
    if (!this.view) {
      log.showWarn(TAG, 'setFocus view is not ready');
      return;
    }
    this.isHomeOnFocus = status;
    this.homeFocusChange();
  }

  /**
   * 引导语变化处理回调。
   */
  private queryGuideChange() {
    log.showInfo(TAG, `queryGuideChange start`);
    if (!this.view || !this.isEnabled()) {
      log.showWarn(TAG, `queryGuideChange, the view: ${!!this.view}, isEnabled: ${this.isEnabled()}`);
      this.clearGuidesSwipe();
      return;
    }
    if (this.guidesTimeoutId !== undefined) {
      this.clearGuidesSwipe();
    }
    if (!this.isHomeOnFocus) {
      log.showError(TAG, 'queryGuideChange, intelligent is not on focus');
      // 数据请求回来,但是负一屏已被划出的场景,下一次划入重置轮播
      this.view.exposeGuideIndex = 0;
      this.currentGuideExposeTime = 0;
      return;
    }
    this.swipeGuides2Idx(0);
  }

  /**
   * 主页聚焦状态变化处理回调。
   */
  private homeFocusChange() {
    if (!this.view || !this.isEnabled()) {
      log.showWarn(TAG, `homeFocusChange, the view: ${!!this.view}, isEnabled: ${this.isEnabled()}`);
      this.clearGuidesSwipe();
      return;
    }
    // 离开负一屏时,若存在轮播任务,则取消轮播。
    if (!this.isHomeOnFocus && this.guidesTimeoutId !== undefined) {
      this.clearGuidesSwipe();
      return;
    }
    // 进入负一屏,若不存在引导语,直接返回。
    if (!this.view.asaCard?.guides) {
      log.showInfo(TAG, 'homeFocusChange, did not get guides yet');
      return;
    }
    // 如果当前没有开始轮播引导语,则从第一个开始。
    if (!this.currentGuideExposeTime) {
      this.swipeGuides2Idx(0);
      return;
    }
    // 若当前轮播引导语展示时间已到,则切换到下一个。
    if ((Date.now() - this.currentGuideExposeTime) > this.guidesSwipeInterval) {
      this.swipeGuides2Idx(this.view.exposeGuideIndex + 1);
    } else {
      this.swipeGuides2Idx(this.view.exposeGuideIndex);
    }
  }

  /**
   * 切换到目标下标的引导语。
   *
   * @param index 目标引导语的下标。
   */
  private swipeGuides2Idx(index: number): void {
    if (!this.view) {
      log.showWarn(TAG, `swipeGuides2Idx, the view is empty`);
      return;
    }
    // 若负一屏未聚焦,则直接返回。
    if (!this.isHomeOnFocus) {
      log.showInfo(TAG, 'swipeGuides2Idx, home is not on focus');
      return;
    }
    // 若无引导语,则直接返回
    if (!this.view.asaCard?.guides || this.view.asaCard?.guides?.length === 0) {
      log.showInfo(TAG, 'swipeGuides2Idx, guides is empty');
      return;
    }
    // 若index超出引导语数量,则从头开始。
    if (index >= this.view.asaCard.guides.length) {
      index = 0;
    }
    log.showInfo(TAG, `swipeGuides2Idx index: ${index}`);
    this.view.exposeGuide = this.view.asaCard.guides[index].name;
    this.view.exposeGuideIndex = index;

    // 若仅存在一条引导语,则创建轮播
    if (this.view.asaCard.guides.length === 1) {
      log.showInfo(TAG, `swipeGuides2Idx, only one guide, no need to swipe`);
      return;
    }
    this.currentGuideExposeTime = Date.now();
    this.guidesTimeoutId = setTimeout(() => {
      this.swipeGuides2Idx(index + 1);
    }, this.guidesSwipeInterval);
  }

  /**
   * 关闭引导语轮播。
   */
  private clearGuidesSwipe() {
    if (this.guidesTimeoutId) {
      log.showInfo(TAG, `clearGuidesSwipe, start`);
      clearTimeout(this.guidesTimeoutId);
      this.guidesTimeoutId = undefined;
    }
  }

  /**
   * 将给定的数据更新至智能体服务助手。
   *
   * @param dataStr 给定数据的JsonString。
   */
  public refreshAssistantData(dataStr: string) {
    try {
      if (!this.view) {
        log.showError(TAG, `refreshAssistantData, the view is empty`);
        return;
      }

      if (!dataStr) {
        log.showError(TAG, `refreshAssistantData, dataStr is empty.`);
        return;
      }

      let data: AgentServiceAssistantData = CommonUtil.securedJsonParse(dataStr) as AgentServiceAssistantData;
      let refreshTime: number = new Date().getTime();
      log.showInfo(TAG, `refreshAssistantData, data: ${!!dataStr}`);

      this.view.asaCard = data.asaCard;
      this.view.refreshTime = refreshTime;
      this.queryGuideChange();
      return;
    } catch (e) {
      log.showError(TAG, `refreshAssistantData failed, code: ${e?.code}, message: ${e?.message}`);
      return;
    }
  }

  /**
   * 清除智能体服务助手数据。
   */
  public clearAssistantData() {
    try {
      if (!this.view) {
        log.showError(TAG, `clearAssistantData, the view is empty`);
        return;
      }

      let refreshTime: number = new Date().getTime();
      log.showInfo(TAG, `clearAssistantData start`);

      this.view.asaCard = undefined;
      this.view.refreshTime = refreshTime;
    } catch (e) {
      log.showError(TAG, `clearAssistantData failed, code: ${e?.code}, message: ${e?.message}`);
      return;
    }
  }

  /**
   * 卡片点击处理函数。
   *
   * @param data 点击参数。
   */
  public onFuncElementClick(data: IAgentCardFunctionElement): void {
    if (!data) {
      log.showError(TAG, `data is empty.`);
      return;
    }

    try {
      const actionType: FunctionType = data.type;
      switch (actionType) {
        case FunctionType.CALL_AGENT:
          this.callAgent(data);
          break;
        case FunctionType.JUMP_TO_PAGE:
          this.jumpToPage(data);
          break;
        default:
          log.showError(TAG, `clickCard failed, invalid type: ${actionType}`);
      }
      return;
    } catch (e) {
      log.showError(TAG, `clickCard failed, code: ${e?.code}, message: ${e?.message}`);
      return;
    }
  }

  /**
   * 通知负一屏拉起智能体。
   *
   * @param data 通知数据。
   */
  private callAgent(data: IAgentCardFunctionElement): void {
    try {
      let token = bundleManager.getBundleInfoSync(CommonContants.INTELLIGENT_BUNDLENAME,
        bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION).appInfo.accessTokenId;
      let atManager = abilityAccessCtrl.createAtManager();
      let locationStatus = atManager.checkAccessTokenSync(token, 'ohos.permission.LOCATION');
      let approxLocationStatus = atManager.checkAccessTokenSync(token, 'ohos.permission.APPROXIMATELY_LOCATION');
      log.showInfo(TAG, `callAgent, locationStatus: ${locationStatus}, approxLocationStatus: ${approxLocationStatus}`);

      let dataStr: string = CommonUtil.securedStringify(data);

      if (locationStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED &&
        approxLocationStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
        log.showInfo(TAG, `callAgent, launch agent`);
        hiboardIPCService.callAgent(dataStr);
      } else {
        log.showError(TAG, `callAgent, show permission`);
        AppStorage.setOrCreate<string>(AGENT_QUERY_INFO_TAG, dataStr);
        AppStorage.setOrCreate<boolean>(CommonContants.IS_SHOW_REQUEST_PERMISSION_PAGE, true);
      }
      return;
    } catch (e) {
      log.showError(TAG, `callAgent failed, code: ${e?.code}, message: ${e?.message}`);
      return;
    }
  }

  /**
   * 跳转页面。
   *
   * @param data 跳转数据。
   */
  private jumpToPage(data: IAgentCardFunctionElement): void {
    try {
      const params: Record<string, Object> = data.extras;
      const jumpInfoList: JumpInfo[] = params[JUMP_INFO_LIST_TAG] as JumpInfo[];
      if (!jumpInfoList) {
        log.showError(TAG, `jumpToPage failed, jumpInfoList is empty`);
        return;
      }
      JumpController.jumpAction(jumpInfoList, FORM_ITEM_ID);
      return;
    } catch (e) {
      log.showError(TAG, `jumpToPage failed, code: ${e?.code}, message: ${e?.message}`);
      return;
    }
  }

  /**
   * 解绑组件
   */
  public unbindView() {
    log.showInfo(TAG, 'unbindView start');
    this.view = undefined;
    this.clearGuidesSwipe();
  }

  /**
   * 清除内存。
   */
  public releaseMemory() {
    log.showInfo(TAG, 'releaseMemory');
    if (this.view) {
      this.view = undefined;
    }
    this.clearGuidesSwipe();
  }
}