/*
 * Copyright (c) Huawei Device Co., Ltd. 2024-2025. All rights reserved.
 * 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 osAccount from '@ohos.account.osAccount';
import util from '@ohos.util';
import { CheckEmptyUtils, LogDomain, LogHelper, ObjUtil, Trace } from '@ohos/basicutils';
import { DeviceHelper, EvtBus, HiDfxEventUtil, OuterHomeCallbackEvent } from '@ohos/frameworkwrapper';
import { AbstractInitialAble } from '../base/AbstractInitialAble';
import { AbstractObserverManager } from '../base/AbstractObserverManager';
import { KeyGuardCacheKey, KeyGuardMode } from '../bean/KeyGuardStatusEnum';
import { KeyguardStatusService } from '../manager/KeyguardStatusService';
import {
  LockState,
  LockStateInfo,
  ScreenLockStateChangeListener,
  ScreenLockStateManager
} from '../manager/ScreenLockStateManager';
import { StrongAuthStateManager } from '../manager/StrongAuthStateManager';
import {
  VerifyDataChangeListener,
  VerifyDataManager,
  VerifyInfo
} from '../manager/VerifyDataManager';
import { SimCardStateManager } from '../manager/SimCardStateManager';
import { CameraStateManager } from '../manager/CameraStateManager';
import { CacheValue, GlobalStatusCache } from '../base/GlobalStatusCache';
import { SLFaultTag } from '../record/report/ReportTag';
import { AccountHelper, AuthTrustLevel, AuthType, IAMAuthResult, SwitchEventData } from '../utils/AccountHelper';
import { FingerAuthReportHelper } from '../utils/FingerAuthReportHelper';
import { HiKGReportTimeout, HiKGReportBase, TIMEOUT_PARAMS } from '../record/report/PerformanceMonitorUtil';
import { SlServerHelper } from '../utils/SlServerHelper';
import { SlUnlockReportHelper } from '../record/report/SlUnlockReportHelper';
import { UserSwitchListener, UserSwitchService } from './UserSwitchService';

const TAG = 'ScreenLockVerifyService';
const log: LogHelper = LogHelper.getLogHelper(LogDomain.KG, TAG);
const EVENT_CODE_KEYGUARD_AUTH_RESULT: number = 1;
const UNLOCK_ASSIGN_USER: number = 10001; // 仅认证指定用户
const UNLOCK_SILENCE: number = 10006; // 静默认证 | 联动认证
const UNLOCK_SILENCE_ASSIGN_USER: number = 10007; // 静默认证 | 仅认证指定用户
const INVALID_HANDLE_TOKEN = ''; // 默认无效TOKEN

/**
 * 验证结果
 */
export enum VerifyResult {
  /**
   * 验证成功
   */
  SUCCESS = 1,

  /**
   * 验证失败
   */
  FAIL = 2,

  /**
   * 其他用户验证成功
   */
  OTHER_SUCCESS = 3,
  /**
   * 用户取消
   */
  CANCEL = 4,

  /*
   * 强认证禁止跨设备解锁
  */
  FAIL_STRONG_AUTH = 1001,

  /*
   * SIM卡锁定禁止跨设备解锁
  */
  FAIL_SIM_LOCKED = 1002,

  /*
   * 锁屏已退出禁止跨设备解锁
  */
  FAIL_UNLOCK_ALREADY = 1003,
}

/**
 * 密码提示码
 */
export enum PasswordAcquireCode {
  /**
   * 密码结果
   */
  PASSWORD_ACQUIRE_RESULT = 1,
}

export enum IAMResultCode {
  SUCCESS = 0,
  FAIL = 12300101,
  CANCEL = 12300109,
}

/**
 * 提示额外信息
 */
export interface AcquireExtraInfo {
  authResult: number;
  authRemainAttempts: number;
  lockoutDuration: number;
  userId: number;
}

export interface OnAcquireInfo {
  authType: number;
  moduleId: number;
  acquire: number;
  extraInfo: Uint8Array;
}

/**
 * 验证阶段监听器
 */
export interface VerifyStateListener {
  /**
   * 验证状态变更
   *
   * @param authType 验证类型
   * @param verifyResult 验证结果
   */
  onVerifyResult?: (authType: AuthType, verifyResult: VerifyResult) => void;

  /**
   * 身份认证信息回调
   *
   * @param authType 验证类型
   * @param module 用于身份验证的执行器类型
   * @param acquire 不同身份验证执行器的tip代码
   * @param extraInfo 额外信息
   */
  onAcquireInfo?: (authType: AuthType, module: number, acquire: number, extraInfo?: AcquireExtraInfo) => void;

  /**
   * 验证状态变更
   *
   * @param authType 验证类型
   * @param isVerifying 是否验证中
   */
  onVerifyStateChange?: (authType: AuthType, isVerifying: boolean) => void;

  /**
   * 认证成功并收到result回调,代表文件解密
   *
   * @param authType 验证类型
   */
  onAuthSuccessResult?: (authType: AuthType) => void;
};

/**
 * 结果处理接口
 */
export interface ResultHandler {
  get authType(): AuthType;

  get authTypeStr(): string;

  /**
   * 设置已处理结果,阻止后续处理
   */
  setHasHandleResult(): void;

  /**
   * 设置已处理验证信息,阻止后续处理
   */
  setHasHandleAcquireInfo(): void;

  /**
   * 标记onAcquire已经认证成功
   */
  setMarkAcquireSuccess(): void;

  /**
   * 各种认证方式提前认证成功的统一回调
   */
  onPreVerifySuccess?(): void;

  /**
   * 广播验证结果
   *
   * @param result 认证结果
   */
  broadcastResult(result: number, authType?: AuthType): void;

  /**
   * 广播身份验证信息
   *
   * @param acquireInfo 身份验证信息
   * @param listener 监听器
   */
  broadcastAcquireInfo(module: number, acquire: number, extraInfo: AcquireExtraInfo): void;

  /**
   * 向OuterHome发送认证结果
   *
   * @param result 认证结果
   */
  sendAuthResultToOuterHome(result: number): void;
}

/**
 * 验证拦截器
 */
export abstract class VerifyInterceptor extends AbstractInitialAble {
  public readonly authType: AuthType;
  private _next?: VerifyInterceptor;

  constructor(authType: AuthType) {
    super();
    this.authType = authType;
  }

  public endTrace(): void {
  }

  public get next(): VerifyInterceptor | undefined {
    return this._next;
  }

  public set next(nextInterceptor: VerifyInterceptor | undefined) {
    this._next = nextInterceptor;
  }

  public get verifyInfo(): VerifyInfo {
    return VerifyDataManager.getInstance().getVerifyInfo(this.authType);
  }

  /**
   * 结果回调拦截
   *
   * @param _handler 结果处理器
   * @param _result 验证结果
   * @param _extraInfo 验证结果额外信息
   * @returns 是否中止处理
   */
  public onVerifyResult(handler: ResultHandler, result: number, extraInfo?: osAccount.AuthResult): boolean {
    return false;
  }

  /**
   * 身份认证信息回调拦截
   *
   * @param _handler 结果处理器
   * @param _module 验证器
   * @param _acquire Tips提示码
   * @param _extraInfo 额外信息
   * @returns 是否中止处理
   */
  public onAcquireInfo(handler: ResultHandler, module: number, acquire: number, extraInfo?: AcquireExtraInfo): boolean {
    return false;
  }

  protected doInit(params?: number | object | undefined): void {
  }

  protected doRelease(): void {
  }
}

/**
 * 验证状态监听管理器
 */
abstract class VerifyListenerManager extends AbstractObserverManager<VerifyStateListener> {
  private _lastSuccessAuthType: number = 0; // 记录最好验证成功的验证类型

  public set lastSuccessAuthType(lastSuccessAuthType: number) {
    this._lastSuccessAuthType = lastSuccessAuthType;
  }

  public get lastSuccessAuthType(): number {
    return this._lastSuccessAuthType;
  }

  /**
   * 触发结果回调
   *
   * @param authType 验证类型
   * @param verifyState 验证状态
   */
  public broadcastResult(authType: AuthType, verifyStep: VerifyResult): void {
    log.showInfo(`broadcastVerifyResult authType ${AuthType[authType]}, verifyStep ${VerifyResult[verifyStep]}`);
    this.broadcastDataChange(listener => listener?.onVerifyResult?.(authType, verifyStep));
  }

  /**
   * 认证成功并收到result回调,代表文件解密
   *
   * @param authType 验证类型
   */
  public broadcastAuthSuccessResult(authType: AuthType): void {
    log.showInfo(`broadcastAuthSuccessResult authType ${AuthType[authType]}`);
    this.broadcastDataChange(listener => listener?.onAuthSuccessResult?.(authType));
  }

  /**
   * 触发身份验证信息回调
   *
   * @param authType 验证类型
   * @param module 用于身份验证的执行器类型
   * @param acquire 不同身份验证执行器的tip代码
   * @param extraInfo 额外信息
   */
  public broadcastAcquireInfo(authType: AuthType, module: number, acquire: number, extraInfo?: AcquireExtraInfo): void {
    this.broadcastDataChange(listener => listener?.onAcquireInfo?.(authType, module, acquire, extraInfo));
  }

  /**
   * 触发验证状态变更通知
   *
   * @param authType 验证类型
   * @param isVerifying 是否验证中
   */
  public broadcastVerifyStateChange(authType: AuthType, isVerifying: boolean): void {
    super.broadcastDataChange(listener => listener?.onVerifyStateChange?.(authType, isVerifying));
  }
}

/**
 * 抽象结果处理器
 */
abstract class AbstractResultHandler extends AbstractInitialAble implements ResultHandler {
  public readonly authType: AuthType;
  protected readonly _listenerManager: VerifyListenerManager;
  protected _hasHandleResult: boolean = false; // 是否已处理结果
  protected _hasHandleAcquireInfo: boolean = false; // 是否已处理acquireInfo
  protected _isAcquireSuccess: boolean; // 标记onAcquire是否已经认证成功

  constructor(authType: AuthType, listenerManager: VerifyListenerManager) {
    super();
    this.authType = authType;
    this._listenerManager = listenerManager;
    this._isAcquireSuccess = false;
  }

  public get authTypeStr(): string {
    return AuthType[this.authType];
  }

  public setHasHandleResult(): void {
    this._hasHandleResult = true;
  }

  public setHasHandleAcquireInfo(): void {
    this._hasHandleAcquireInfo = true;
  }

  public setMarkAcquireSuccess(): void {
    this._isAcquireSuccess = true;
  }

  public broadcastResult(result: number, authType: AuthType = this.authType): void {
    let verifyResult: VerifyResult = VerifyResult.FAIL;
    switch (result) {
      case IAMResultCode.SUCCESS:
        verifyResult = VerifyResult.SUCCESS;
        break;
      case IAMResultCode.CANCEL:
        verifyResult = VerifyResult.CANCEL;
        break;
      default:
        verifyResult = VerifyResult.FAIL;
    }
    if (verifyResult === VerifyResult.SUCCESS) {
      this._listenerManager.lastSuccessAuthType = authType;
      VerifyDataManager.getInstance().updateVerifyData();
    }
    this._listenerManager.broadcastResult(authType, verifyResult);
  }

  public broadcastAcquireInfo(module: number, acquire: number, extraInfo?: AcquireExtraInfo): void {
    this._listenerManager.broadcastAcquireInfo(this.authType, module, acquire, extraInfo);
  }

  public broadcastStateChange(isVerifying: boolean): void {
    this._listenerManager.broadcastVerifyStateChange(this.authType, isVerifying);
  }

  public sendAuthResultToOuterHome(result: number): void {
    if (DeviceHelper.isSmallFoldProduct()) {
      const eventData = JSON.stringify({
        authType: this.authType, result: result
      });
      let outerHomeCallbackEvent = new OuterHomeCallbackEvent(EVENT_CODE_KEYGUARD_AUTH_RESULT, eventData);
      EvtBus.post(OuterHomeCallbackEvent, outerHomeCallbackEvent);
    }
  }
}

/**
 * 认证的识别上下文对象
 */
interface VerifyContextId {
  contextId: Uint8Array;
  verifySuccess: boolean;
}

/**
 * 抽象监听器
 */
abstract class AbstractVerifier extends AbstractResultHandler {
  protected readonly _isAutoOpen: boolean;
  protected _authLevel: AuthTrustLevel;
  protected _isVerifying: boolean = false;

  private readonly _cancelContextIds: Map<String, VerifyContextId> = new Map();
  private readonly _interceptors: VerifyInterceptor[] = [];
  private _isPageStateOpen: boolean = true; // 页面状态是否可解锁,由根页控制
  private _isOperateOpen: boolean = true; // 叠加在页面状态上的交互状态,例如解锁页被覆盖时,此时操作状态为false
  private _handleResultToken: string = INVALID_HANDLE_TOKEN; // 标记可处理结果的令牌

  constructor(authType: AuthType, authLevel: AuthTrustLevel, isAutoOpen: boolean,
    listenerManager: VerifyListenerManager) {
    super(authType, listenerManager);
    this._authLevel = authLevel;
    this._isAutoOpen = isAutoOpen;
  }

  /**
   * 注册拦截器
   *
   * @param authType 验证类型
   * @param observer 拦截器
   */
  public registerInterceptor(interceptor: VerifyInterceptor): void {
    log.showInfo(`add ${this.authTypeStr} verify interceptor.`);
    if (!this._interceptors.includes(interceptor)) {
      this._interceptors.push(interceptor);
    }
  }

  /**
   * 注销拦截器
   *
   * @param authType 验证类型
   * @param observer 拦截器
   */
  public unRegisterInterceptor(interceptor: VerifyInterceptor): void {
    log.showInfo(`delete ${this.authTypeStr} verify interceptor.`);
    let index = this._interceptors.indexOf(interceptor);
    if (index >= 0) {
      this._interceptors.slice(index, 1);
    }
  }

  /**
   * 页面状态是否开启解锁
   *
   * @param isPageStateOpen 页面状态
   * @param isAutoVerify isPageStateOpen为true时是否自动认证
   */
  public setIsPageStateOpen(isPageStateOpen: boolean, isAutoVerify: boolean = true): void {
    if (this._isPageStateOpen !== isPageStateOpen) {
      this._isPageStateOpen = isPageStateOpen;
      if (!isPageStateOpen || isAutoVerify) {
        this.autoUpdateState();
      }
    }
  }

  /**
   * 更新交互状态
   *
   * @param isOperateOpen 交互状态
   * @param isAutoVerify isOperateOpen为true时是否自动认证
   */
  public setIsOperateOpen(isOperateOpen: boolean, isAutoVerify: boolean = true): void {
    if (this._isOperateOpen !== isOperateOpen) {
      this._isOperateOpen = isOperateOpen;
    }
    if (isOperateOpen && !isAutoVerify) {
      return;
    }
    this.autoUpdateState();
  }

  /**
   * 是否正在验证中
   *
   * @returns true验证中/false不在验证中
   */
  public get isVerifying(): boolean {
    return this._isVerifying;
  }

  /**
   * 自动更新验证状态
   */
  public autoUpdateState(): void {
    if (this.verifyInfo.isSupportUnlock) {
      if (!this.hasInit()) {
        this.init();
      }
      if (this._isAutoOpen) {
        this.isCanVerify() ? this.verify() : this.cancelVerify();
      }
    } else {
      this.release();
    }
  }

  /**
   * 验证密码接口
   *
   * @param pwd 密码
   * @param isAddPwd 是否追加密码
   * @returns true下发成功/false下发失败
   */
  public verify(_pwd?: string, isAddPwd: boolean = false): boolean {
    log.showInfo(`${this.authTypeStr} verify isAddPwd ${isAddPwd}.`);
    return !!this.authCurrentUser();
  }

  /**
   * 取消验证
   */
  public cancelVerify(isFinish: boolean = false): void {
    this.cancelAuth(this._handleResultToken, isFinish);
    if (this.isVerifying !== false) {
      log.showInfo(`cancelVerify ${this.authTypeStr} isVerifying false`);
    }
    this.isVerifying = false;
  }

  /**
   * 重置认证次数
   */
  public resetAuthRemainCount(): void {
  }

  private cancelAuth(handleToken?: string, isFinish: boolean = false): void {
    let deleteText = handleToken ?? this._handleResultToken;
    let verifyContextId: VerifyContextId | undefined = this._cancelContextIds.get(deleteText);
    if (deleteText && deleteText.length !== 0) {
      log.showInfo(`cancelVerify ${this.authTypeStr} ${deleteText}` + (verifyContextId ? ` skip` : ``));
    }
    if (!verifyContextId) {
      return;
    }
    if (isFinish || !verifyContextId.verifySuccess) {
      let isCancelCurrent = handleToken === this._handleResultToken;
      log.showInfo(`already success, cancel auth, isCancelCurrent: ${isCancelCurrent}`);
      AccountHelper.getInstance().cancelAuth(verifyContextId.contextId);
      this._cancelContextIds.delete(deleteText);
      if (isCancelCurrent) {
        this._handleResultToken = INVALID_HANDLE_TOKEN;
      }
    }
  }

  protected doInit(): void {
    log.showInfo(`doInit verifier authType ${this.authTypeStr}`);
  }

  protected doRelease(): void {
    log.showInfo(`doRelease verifier authType ${this.authTypeStr}`);
    this.cancelVerify();
  }

  /**
   * 获取验证信息
   *
   * @returns 验证信息
   */
  protected get verifyInfo(): VerifyInfo {
    return VerifyDataManager.getInstance().getVerifyInfo(this.authType);
  }

  /**
   * 更新验证状态
   *
   * @param isVerifying 是否验证中
   */
  protected set isVerifying(isVerifying: boolean) {
    if (this._isVerifying !== isVerifying) {
      this._isVerifying = isVerifying;
      this.broadcastStateChange(isVerifying);
    }
  }

  public isCanVerify(): boolean {
    if (!UserSwitchService.getInstance().isCurrentUserActive) {
      log.showInfo(`auth ${this.authTypeStr} encounter user inactive.`);
      return false;
    }
    if (this._isAutoOpen && !(this._isPageStateOpen && this._isOperateOpen)) {
      log.showInfo(`auth ${this.authTypeStr} pageState: ${this._isPageStateOpen}, Operate: ${this._isOperateOpen}`);
      return false;
    }

    let isCanVerify: boolean = this.verifyInfo.isSupportUnlock;
    if (!isCanVerify) {
      log.showInfo(`auth ${this.authTypeStr} encounter not support unlock.`);
    }
    return this.verifyInfo.isSupportUnlock;
  }

  /**
   * 验证当前用户
   *
   * @param verifyParam 验证参数
   * @returns 取消的上下文ID
   */
  protected authCurrentUser(): boolean {
    if (!this.isCanVerify()) {
      return false;
    }
    if (this._isAutoOpen && this.isVerifying) {
      log.showWarn(`${this.authTypeStr} verifying`);
      return false;
    }
    this._hasHandleResult = false;
    let handleToken: string = util.generateRandomUUID();
    log.showWarn(`auth start: ${this.authType}`);
    let cancelContextId: Uint8Array | undefined = AccountHelper.getInstance().authUser(this.authType, this._authLevel,
      this.getAuthOptions(), this.generateOnResultHandler(handleToken));
    this.isVerifying = !!cancelContextId;
    if (this.isVerifying && cancelContextId) {
      log.showInfo(`authUser ${this.authTypeStr} isVerifying ${this.isVerifying}.`);
      let verifyContextId: VerifyContextId = {
        contextId: cancelContextId,
        verifySuccess: false
      };
      this._cancelContextIds.set(handleToken, verifyContextId);
      this._handleResultToken = handleToken;
    } else {
      log.showError(`authUser ${this.authTypeStr} failed.`);
    }
    return this.isVerifying;
  }

  private generateOnResultHandler(handleNote: string): osAccount.IUserAuthCallback {
    return {
      onResult: (result: number, extraInfo: osAccount.AuthResult): void => {
        // Token发生变化,如果是解锁结果是成功或者是抢占导致,不需要处理
        log.showWarn(`onResult: ${result} of ${this.authTypeStr}`);
        if (this._handleResultToken !== handleNote &&
          (result === IAMResultCode.SUCCESS || this._handleResultToken !== INVALID_HANDLE_TOKEN)) {
          log.showInfo(`onResult: ${result} of ${this.authTypeStr} --> invalid handleToken ${handleNote}.`);
          this.cancelAuth(handleNote, false);
          return;
        }
        this.handleOnResult(result, extraInfo);
      },
      onAcquireInfo: (module: number, acquire: number, extraInfo: Uint8Array): void => {
        if (this._handleResultToken !== handleNote) {
          log.showInfo(`onAcquireInfo invalid handleToken ${handleNote}.`);
          return;
        }
        this.handleOnAcquireInfo(module, acquire, extraInfo);
      }
    };
  }

  private handleOnResult(result: number, extraInfo: osAccount.AuthResult): void {
    this.cancelVerify(true);
    if (this._hasHandleResult) {
      log.showWarn(`onResult: ${result} of ${this.authTypeStr} --> has handle result already.`);
      this.updateVerifyInfo(result);
      this.handleAuthSuccessAfterResult(result, extraInfo);
      return;
    }
    this.handleOnResultReal(result, extraInfo);
  }

  protected handleOnResultReal(result: number, extraInfo: osAccount.AuthResult): void {
    if (this._isAcquireSuccess && result !== IAMResultCode.SUCCESS) {
      log.showError(`${this.authTypeStr} acquire and result is different`);
      HiKGReportBase.reportFault(SLFaultTag.ACQUIRE_RESULT_DIFF, Object({
        TYPE: this.authType,
        CODE: result,
      }));
    }
    if (result === IAMResultCode.SUCCESS && this.isNeedSwitchUser(extraInfo?.accountId)) {
      Trace.end(Trace.CORE_METHOD_PSD_AUTH);
      log.showInfo(`onResult: ${result} of ${this.authTypeStr} --> needSwitchUser.`);
      this.switchUser(extraInfo?.accountId);
    } else {
      log.showInfo(`onResult: ${result} of ${this.authTypeStr} --> handleOnResult`);
      this.updateVerifyInfo(result, extraInfo);
      this.onResult(result, extraInfo);
      this.handleAuthSuccessAfterResult(result, extraInfo);
    }
  }

  // onVerifyResult之后处理,确保在锁头和锁屏状态后执行
  private handleAuthSuccessAfterResult(result: number, extraInfo: osAccount.AuthResult): void {
    if (result === IAMResultCode.SUCCESS && !this.isNeedSwitchUser(extraInfo?.accountId)) {
      this._listenerManager.broadcastAuthSuccessResult(this.authType);
    }
  }

  // public只可以被debugCommand使用,高危接口
  public handleOnAcquireInfo(moduleId: number, acquire: number, extraInfo: Uint8Array): void {
    if (this._hasHandleResult) {
      log.showWarn(`onAcquire: ${acquire} of ${this.authTypeStr} --> has handle result already.`);
      return;
    }
    this.handleOnAcquireInfoReal(moduleId, acquire, extraInfo);
  }

  protected handleOnAcquireInfoReal(moduleId: number, acquire: number, extraInfo: Uint8Array): void {
    log.showDebug(`onAcquire: ${acquire} of ${this.authTypeStr} --> moduleId is ${moduleId}`);
    let acquireExtraInfo: AcquireExtraInfo | undefined = this.parseAcquireExtraInfo(extraInfo);
    if (acquireExtraInfo?.authResult === 0 && this.isNeedSwitchUser(acquireExtraInfo?.userId)) {
      log.showInfo(`onAcquire: ${acquire} of ${this.authTypeStr} --> needSwitchUser.`);
      this.switchUser(acquireExtraInfo?.userId);
    } else {
      this._hasHandleAcquireInfo = false;
      this._isAcquireSuccess = false;
      this.onAcquireInfo(moduleId, acquire, acquireExtraInfo);
    }
  }

  /**
   * 标记此次提前认证成功
   */
  public onPreVerifySuccess(): void {
    let verifyContextId: VerifyContextId | undefined = this._cancelContextIds.get(this._handleResultToken);
    if (verifyContextId) {
      log.showInfo(`onPreVerifySuccess ${this.authTypeStr} acquire is success`);
      verifyContextId.verifySuccess = true;
    }
  }

  /**
   * 处理验证结果
   *
   * @param result 验证结果
   * @param extraInfo 验证额外信息
   */
  protected onResult(result: number, extraInfo: osAccount.AuthResult): void {
    // 记录验证上报
    SlUnlockReportHelper.getInstance().recordAuthEndTime(this.authType);
    if (result === IAMResultCode.SUCCESS) {
      FingerAuthReportHelper.getInstance().unlockReport(this.authType, true);
    }
    if (!this._hasHandleResult) {
      this.onInterceptorHandleResult(result, extraInfo);
    }
    // 条件可能改变,保证时序正确
    if (!this._hasHandleResult) {
      this.broadcastResult(result);
    }
  }

  /**
   * 处理验证中提示信息
   *
   * @param module
   * @param acquire
   * @param extraInfo
   */
  protected onAcquireInfo(module: number, acquire: number, extraInfo?: AcquireExtraInfo): void {
    this.onInterceptorHandleAcquireInfo(module, acquire, extraInfo);
    if (!this._hasHandleAcquireInfo) {
      this.broadcastAcquireInfo(module, acquire, extraInfo);
    }
  }

  /**
   * 更新验证信息
   *
   * @param result 验证结果
   * @param extraInfo 验证信息
   */
  protected updateVerifyInfo(result: number, extraInfo?: osAccount.AuthResult): void {
    VerifyDataManager.getInstance().updateVerifyInfo(this.authType, result, extraInfo);
  }

  protected getAuthOptions(): osAccount.AuthOptions {
    // 丢失模式、孩童模式、远程锁定模式、QXS PC模式不能进入隐私空间
    let isAuthCurrentOnly = (AppStorage.get<boolean>('childModule') ?? false) ||
    KeyguardStatusService.isOnlyCurrentUser() ||
    DeviceHelper.is2In1DevicePcType();
    let authIntent: number = isAuthCurrentOnly ? UNLOCK_ASSIGN_USER : osAccount.AuthIntent.UNLOCK;
    log.showInfo(`getAuthOptions authIntent: ${authIntent}.`);
    return {
      accountId: AccountHelper.getInstance().currentLocalId,
      authIntent: authIntent,
    };
  }

  private isNeedSwitchUser(user: number | undefined): boolean {
    if (!user) {
      log.showError(`invalid userId.`);
      return false;
    }
    let currentUser = AccountHelper.getInstance().currentLocalId;
    log.showWarn(`receive auth ${user} currentUser ${currentUser}`);
    return user !== currentUser;
  }

  private switchUser(user?: number): void {
    if (user === undefined) {
      log.showError('switchUser failed, user is undefined');
      return;
    }
    log.showInfo(`authUser ${this.authTypeStr} needSwitchUser. start to active other user ${user}`);

    // 处理用户切换事件
    AccountHelper.getInstance().activateOsAccount(user);
    // 上报其他用户验证成功
    this._hasHandleResult = true;
    this.onPreVerifySuccess();
    SlServerHelper.getInstance().setScreenLockAuthState(this.authType, user, true);
    this._listenerManager.broadcastResult(this.authType, VerifyResult.OTHER_SUCCESS);
  }

  private parseAcquireExtraInfo(originalExtraInfo: Uint8Array): AcquireExtraInfo | undefined {
    if (!originalExtraInfo || originalExtraInfo.length === 0) {
      log.showDebug('parseAcquireExtraInfo invalid param.');
      return undefined;
    }

    let extraInfo: AcquireExtraInfo | undefined = undefined;
    try {
      let originalExtraInfoStr: string = String.fromCharCode(...originalExtraInfo);
      if (CheckEmptyUtils.isEmpty(originalExtraInfoStr)) {
        log.showInfo('parseAcquireExtraInfo originalExtraInfo is empty.');
        return undefined;
      }
      extraInfo = JSON.parse(originalExtraInfoStr) as AcquireExtraInfo;
    } catch (error) {
      log.showError(`parseAcquireExtraInfo failed. code: ${error.code}`);
    }

    if (ObjUtil.isInvalid(extraInfo) || ObjUtil.isInvalid(extraInfo?.authResult)) {
      log.showDebug('parseAcquireExtraInfo not meet the requirements.');
      return undefined;
    }
    return extraInfo;
  }

  private onInterceptorHandleResult(result: number, extraInfo: osAccount.AuthResult): boolean {
    for (let interceptor of this._interceptors) {
      let current: VerifyInterceptor | undefined = interceptor;
      while (current) {
        current.endTrace();
        if (current.onVerifyResult(this, result, extraInfo)) {
          log.showInfo(`Interceptor ${this.authTypeStr} onVerifyResult stop. handled: ${this._hasHandleResult}`);
          return true;
        } else {
          log.showInfo(`Interceptor ${this.authTypeStr} onVerifyResult continue. handled: ${this._hasHandleResult}`);
        }
        current = current.next;
      }
    }
    return false;
  }

  private onInterceptorHandleAcquireInfo(module: number, acquire: number, extraInfo?: AcquireExtraInfo): boolean {
    for (let interceptor of this._interceptors) {
      let current: VerifyInterceptor | undefined = interceptor;
      while (current) {
        this._isAcquireSuccess = false;
        if (current.onAcquireInfo(this, module, acquire, extraInfo)) {
          log.showDebug(`${this.authTypeStr} onAcquireInfo stop. handled: ${this._hasHandleResult}`);
          return true;
        } else {
          log.showDebug(`${this.authTypeStr} onAcquireInfo continue. handled: ${this._hasHandleResult}`);
        }
        current = current.next;
      }
    }
    return false;
  }
}

/**
 * 密码验证器
 */
class PwdVerifier extends AbstractVerifier {
  private _pwd?: string;
  private _authSubType: number = 0;
  private _pinInputData?: osAccount.IInputData;
  protected _setTimeOutId: number = -1; // 监控认证耗时打点

  constructor(listenerManager: VerifyListenerManager) {
    super(AuthType.PIN, AuthTrustLevel.ATL3, false, listenerManager);
  }

  public isCanVerify(): boolean {
    if (!ScreenLockStateManager.getInstance().isLocked) {
      log.showInfo(`auth ${this.authTypeStr} encounter unlock scene.`);
      return false;
    }
    return super.isCanVerify();
  }

  public verify(pwd?: string, isAddPwd: boolean = false): boolean {
    if (isAddPwd && this._pinInputData) {
      log.showInfo('PwdVerifier addPwd.');
      return this.submitPwd(pwd, this._authSubType, this._pinInputData);
    }

    AccountHelper.getInstance().unregisterInputer();
    this._pwd = pwd;
    if (!AccountHelper.getInstance().registerInputer(this.onGetData.bind(this))) {
      log.showError('PwdVerifier registerInputer failed.');
      return false;
    }

    let isSuccess: boolean = !!super.verify();
    return isSuccess;
  }

  protected getAuthOptions(): osAccount.AuthOptions {
    // 主空间和隐私空间密码长度不一致时,不开启静默认证
    if (!VerifyDataManager.getInstance().isUnfixedPwdType) {
      return super.getAuthOptions();
    }
    // 丢失模式、孩童模式、QXS PC模式不能进入隐私空间
    let isAuthCurrentOnly = (AppStorage.get<boolean>('childModule') ?? false) ||
    KeyguardStatusService.isOnlyCurrentUser() || DeviceHelper.is2In1DevicePcType();
    let authIntent: number = isAuthCurrentOnly ? UNLOCK_SILENCE_ASSIGN_USER : UNLOCK_SILENCE;
    log.showInfo(`getAuthOptions authIntent: ${authIntent}.`);
    return {
      accountId: AccountHelper.getInstance().currentLocalId,
      authIntent: authIntent
    };
  }

  public cancelVerify(): void {
    super.cancelVerify();
    this._pinInputData = undefined;
    this._authSubType = 0;
    this._pwd = undefined;
    AccountHelper.getInstance().unregisterInputer();
  }

  public autoUpdateState(): void {
    if (this._isVerifying && !ScreenLockStateManager.getInstance().isLocked) {
      this.cancelVerify();
    }
  }

  protected handleOnAcquireInfoReal(moduleId: number, acquire: number, extraInfo: Uint8Array): void {
    HiKGReportTimeout.getInstance().rollbackTimeout(TIMEOUT_PARAMS.PSD_AUTH.NAME);
    super.handleOnAcquireInfoReal(moduleId, acquire, extraInfo);
  }

  protected handleOnResultReal(result: number, extraInfo: osAccount.AuthResult): void {
    HiKGReportTimeout.getInstance().rollbackTimeout(TIMEOUT_PARAMS.PSD_AUTH.NAME);
    super.handleOnResultReal(result, extraInfo);
  }

  private onGetData(passType: number, inputData: osAccount.IInputData): void {
    // 注意:多用户场景,此处会多次调用,因此需要保存密码
    if (this._pwd) {
      this.submitPwd(this._pwd, passType, inputData);
    } else {
      log.showInfo(`registerInputer tmp save passType: ${passType}`);
      this._pinInputData = inputData;
      this._authSubType = passType;
    }
  }

  /**
   * 主动提交密码
   */
  private submitPwd(pwd: string | undefined, authSubType: number, inputData: osAccount.IInputData): boolean {
    // 锁屏打点记录开始认证时间
    SlUnlockReportHelper.getInstance().recordAuthStartTime(AuthType.PIN);
    // 输入完离手打点
    HiDfxEventUtil.reportStartUnlockEvent();
    // 锁屏打点记录解锁认证时间
    SlUnlockReportHelper.getInstance().recordUnlockStartTime(AuthType.PIN);
    // 超时打点计时起点
    HiKGReportTimeout.getInstance().logTimeout(TIMEOUT_PARAMS.PSD_AUTH.NAME, TIMEOUT_PARAMS.PSD_AUTH.TIME_OUT);

    this._pwd = pwd;
    return AccountHelper.getInstance().submitInputData(new util.TextEncoder().encodeInto(pwd), authSubType, inputData);
  }
}

/**
 * 锁屏验证服务
 */
export class ScreenLockVerifyService extends VerifyListenerManager {
  private static sInstance: ScreenLockVerifyService;

  public static getInstance(): ScreenLockVerifyService {
    if (ScreenLockVerifyService.sInstance == null) {
      ScreenLockVerifyService.sInstance = new ScreenLockVerifyService();
    }
    return ScreenLockVerifyService.sInstance;
  }

  private readonly _verifiers: Map<AuthType, AbstractVerifier> = new Map();

  private readonly _verifyDataChangeListener: VerifyDataChangeListener = {
    onVerifyStateChange: (authType: AuthType, _verifyInfo: VerifyInfo): void => {
      log.showInfo(`receive VerifyState change authType ${authType}`);
      this._verifiers.get(authType)?.autoUpdateState();
      if (authType === AuthType.PIN && _verifyInfo.isStateLocked) {
        VerifyDataManager.getInstance().updateVerifyData();
      }
    }
  };

  private readonly _lockStateChangeListener: ScreenLockStateChangeListener = {
    onLockStateChange: (lockStateInfo: LockStateInfo): void => {
      log.showInfo(`lockStateInfo change. ${lockStateInfo.toString()}`);
      this._verifiers.forEach((verifier) => verifier.autoUpdateState());
      if (lockStateInfo.lockState === LockState.UNLOCKED) {
        this._verifiers.forEach((verifier) => verifier.resetAuthRemainCount());
      }
    }
  };

  private readonly _userActiveChangeListener: UserSwitchListener = {
    onSwitched: (switchEventData: SwitchEventData): void => {
      log.showInfo(`receive user switched. isCurrentUserActive: ${UserSwitchService.getInstance().isCurrentUserActive}`);
      this._verifiers.forEach((verifier) => verifier.autoUpdateState());
    }
  };

  private readonly _specialModelListener = (isSpecialModel?: CacheValue): void => {
    log.showWarn(`receive isSpecialModel is. ${isSpecialModel}`);
    this._verifiers.forEach((verifier) => verifier.autoUpdateState());
  };

  private readonly _coverModelListener = (isCoverModel?: CacheValue): void => {
    log.showInfo(`receive coverMode is. ${isCoverModel}`);
    this._verifiers.forEach((verifier) => verifier.autoUpdateState());
  };

  private constructor() {
    super();
    this._verifiers.set(AuthType.PIN, new PwdVerifier(this));
  }

  /**
   * 验证密码
   *
   * @param pwd 密码
   * @param isAddPwd 是否追加密码
   * @param listener 验证状态监听
   * @returns true下发成功/false下发失败
   */
  public verifyPwd(pwd?: string, isAddPwd: boolean = false, authType: AuthType = AuthType.PIN): boolean {
    return this._verifiers.get(authType)?.verify(pwd, isAddPwd) ?? false;
  }

  /**
   * 主动取消验证
   *
   * @param authType 验证类型
   */
  public cancelVerify(authType: AuthType = AuthType.PIN): void {
    return this._verifiers.get(authType)?.cancelVerify();
  }

  // 锁屏自动化测试 -> public只可以被debugCommand使用,高危接口
  public launchAcquire(onAcquireInfo: OnAcquireInfo): void {
    if (!onAcquireInfo) {
      log.showError('launchAcquire params is null');
      return;
    }
    this._verifiers.get(onAcquireInfo.authType)?.handleOnAcquireInfo(onAcquireInfo.moduleId,
      onAcquireInfo.acquire, onAcquireInfo.extraInfo);
    this._verifiers.get(onAcquireInfo.authType)?.cancelVerify(true);
  }

  /**
   * 判断指定验证类型是否正在验证中
   *
   * @param authType 验证类型
   * @returns 是否在验证中
   */
  public isVerifying(authType: AuthType): boolean {
    return this._verifiers.get(authType)?.isVerifying ?? false;
  }

  /**
   * 判断当前是否支持认证
   *
   * @param authType 验证类型
   * @returns 是否支持认证
   */
  public isCanVerify(authType: AuthType): boolean {
    return this._verifiers.get(authType)?.isCanVerify() ?? false;
  }

  /**
   * [根页接口]设置页面开启状态
   *
   * @param isOpen 是否打开
   * @param isAutoVerify isOpen为true时是否自动认证
   */
  public setPageOpenState(authType: AuthType, isOpen: boolean, isAutoVerify: boolean = true,
    reason: string = 'Unknown'): void {
    let verifier: AbstractVerifier | undefined = this._verifiers.get(authType);
    if (verifier) {
      log.showInfo(`setPageOpenState ${AuthType[authType]}, isoepn ${isOpen}, verify ${isAutoVerify}` +
        (reason === 'Unknown' ? `` : `, reason: ${reason}`));
      verifier.setIsPageStateOpen(isOpen, isAutoVerify);
    } else {
      log.showError(`setPageOpenState invalid authType ${authType}`);
    }
  }

  /**
   * [子页接口]设置交互开启状态
   *
   * @param isOpen 是否打开
   * @param isAutoVerify isOpen为true时是否自动认证
   */
  public setOperateOpenState(authType: AuthType, isOpen: boolean, isAutoVerify: boolean = true,
    reason: string = 'NoConfig'): void {
    let verifier: AbstractVerifier | undefined = this._verifiers.get(authType);
    if (verifier) {
      log.showInfo(`setOperateOpenState ${AuthType[authType]}, isoepn: ${isOpen}, verify: ${isAutoVerify}` +
        (reason === 'NoConfig' ? `` : `, reason: ${reason}`));
      verifier.setIsOperateOpen(isOpen, isAutoVerify);
    } else {
      log.showError(`setOperateOpenState invalid authType ${authType}`);
    }
  }

  /**
   * 注册验证拦截器
   *
   * @param interceptor 验证拦截器
   */
  public registerInterceptor(interceptor: VerifyInterceptor): void {
    this._verifiers.get(interceptor?.authType)?.registerInterceptor(interceptor);
  }

  /**
   * 注销验证拦截器
   *
   * @param interceptor 验证拦截器
   */
  public unRegisterInterceptor(interceptor: VerifyInterceptor): void {
    this._verifiers.get(interceptor?.authType)?.unRegisterInterceptor(interceptor);
  }

  protected doInit(): void {
    log.showInfo('doInit');
    StrongAuthStateManager.getInstance().updateStrongAuth();
    VerifyDataManager.getInstance().init();
    VerifyDataManager.getInstance().registerObserver(this._verifyDataChangeListener);
    ScreenLockStateManager.getInstance().registerObserver(this._lockStateChangeListener);
    UserSwitchService.getInstance().registerObserver(this._userActiveChangeListener);
    GlobalStatusCache.getInstance().subscribe(KeyGuardCacheKey.COVER_MODE, this._coverModelListener);
    GlobalStatusCache.getInstance().subscribe(KeyGuardCacheKey.SPECIAL_MODE, this._specialModelListener);
  }

  protected doRelease(): void {
    log.showInfo('doRelease');
    VerifyDataManager.getInstance().release();
    VerifyDataManager.getInstance().unRegisterObserver(this._verifyDataChangeListener);
    ScreenLockStateManager.getInstance().unRegisterObserver(this._lockStateChangeListener);
    UserSwitchService.getInstance().unRegisterObserver(this._userActiveChangeListener);
    GlobalStatusCache.getInstance().unsubscribe(KeyGuardCacheKey.COVER_MODE, this._coverModelListener);
    GlobalStatusCache.getInstance().unsubscribe(KeyGuardCacheKey.SPECIAL_MODE, this._specialModelListener);
  }
}