import type { AxiosInstance } from 'axios';
import type { EventEmitter } from 'eventemitter3';
import { DEFAULT_TIMEOUT } from './constant';
import type { ReactNode } from 'react';

export type ConnectMessages = {
  title: string;
  scan: string;
  success: ReactNode;
  confirm?: string; // 貌似没有地方使用，先设置为非必填
  error?: string;
};

// FIXME: @zhanghan 将来需要改成 ts，直接从常量值 LOGIN_PROVIDER 中提取类型，目前只能写成这样
export type WalletProvider = 'wallet' | 'auth0' | 'apple' | 'github' | 'google' | 'passkey';

export type WalletOS = 'web' | 'android' | 'ios' | '';
export type UserRole = 'guest' | 'member' | 'admin' | 'owner' | string;
export type BaseLocale = 'en' | 'zh';
export type UserLocale = BaseLocale | string;

export type ConnectProps = {
  /**
   * @example login
   */
  action: string;
  containerEl?: Element;
  /**
   * @default "/api/did"
   */
  prefix?: string;
  /**
   * @default "en"
   */
  locale?: 'en' | 'zh';
  /**
   * @default false
   */
  popup?: boolean;
  /**
   * @default 2*1000
   */
  checkInterval?: number;
  /**
   * @default 5*60*1000
   */
  checkTimeout?: number;
  /**
   * @default 2*1000
   */
  closeTimeout?: number;
  /**
   * @default {}
   */
  extraParams?: object;
  /**
   * @default "_t_"
   */
  tokenKey?: string;
  /**
   * @default "_ek_"
   */
  encKey?: string;
  /**
   * @default "''"
   */
  baseUrl?: string;
  /**
   * @default {
        title: 'DID Connect',
        scan: 'Scan QR code to complete this action',
        confirm: 'Confirm on your DID Wallet',
        success: 'Success!'
      }
   */
  messages?: ConnectMessages;
  /**
   * @default true
   */
  autoConnect?: boolean;
  /**
   * @default true
   */
  forceConnected?: boolean | string;
  /**
   * @default true
   */
  saveConnect?: boolean;
  /**
   * @default true
   */
  useSocket?: boolean;
  /**
   * @default true
   */
  allowWallet?: boolean;
  /**
   * @default true
   */
  passkeyBehavior?: 'none' | 'both' | 'only-existing' | 'only-new';
  /**
   * @default "wallet"
   */
  provider?: 'wallet' | 'auth0' | '';
  /**
   * @default 160
   */
  qrcodeSize?: number;
  /**
   * @default true
   */
  showDownload?: boolean;
  /**
   * @default "https://web.abtwallet.io"
   */
  webWalletUrl?: string;
  /**
   * @default ["web", "mobile", "github", "apple", "google", "auth0", "passkey"]
   */
  enabledConnectTypes?: Array<'web' | 'mobile' | 'auth0', 'github' | 'apple' | 'google' | 'passkey'>;
  extraContent?: any;
  loadingEle?: any;
  /**
   * @default false
   */
  disableSwitchApp?: boolean;
  /**
   * @default false
   */
  hideCloseButton?: boolean;
  /**
   * @default {}
   */
  options?: {
    /**
     * @default true
     */
    showQuickConnect?: boolean;
  };
  onRecreateSession?: Function;
  checkFn?: () => boolean;
  onSuccess?: (result: object) => void;
  onError?: (error: any) => void;
  onClose?: Function;
};

export type OpenConnect = (params: ConnectProps) => void;
export type OpenConnectPopup = (
  params: ConnectProps,
  options?: {
    baseUrl?: string;
    locale?: BaseLocale;
  }
) => void;

export type OpenDidConnect = (
  params: ConnectProps,
  options?: {
    /**
     * 打开 DID Connect 的模式
     * @default 'popup'
     */
    openMode?: 'redirect' | 'window' | 'popup';
    requirements?: {
      /**
       * 是否要求登录
       * @default true
       */
      login?: boolean;
      /**
       * 是否要求绑定 DID Wallet 账户
       * @default true
       */
      bindWallet?: boolean;
      /**
       * 是否要求绑定 DID Spaces
       * @default false
       */
      bindDidSpaces?: false | 'read' | 'full';
      // bindOAuth?: boolea // 暂不支持，这里要配置的情况会稍微复杂一些
    };
    baseUrl?: string;
    locale?: BaseLocale;
  }
) => void;

export type CloseConnect = Function;

export type CommonSessionFn = (done?: Function, params?: object) => void;

export type LoginSessionFn = (
  done?: Function,
  params?: {
    openMode: 'redirect' | 'window'; // iframe: 暂未启用
    provider?: 'wallet';
    redirect?: string;
    forceConnected?: string;
    sourceAppPid?: string;
    passkeyBehavior?: string;
    [key: string]: any;
  },
  origin?: string
) => any;

export type LogoutSessionFn = (done?: Function) => void;

export type Passport = {
  id: string;
  name: string;
  title: string;
  role: UserRole;
};
export type ConnectAccount = {
  provider: WalletProvider;
  did: string;
  pk: string;
  id?: string;
  firstLoginAt?: string;
  lastLoginAt?: string;
  lastLoginIp?: string;
};

export type SessionUser = {
  avatar: string;
  did: string;
  email: string;
  fullName: string;
  remark?: string;
  role?: UserRole;
  sourceAppPid: null | string;
  sourceProvider: WalletProvider;
};

export type UserSession = {
  id: string;
  appName: string;
  appPid: string;
  updatedAt: string;
  userDid: string;
  visitorId: string;
  extra: object;
  user: SessionUser;
  passportId?: string;
};

export type User = {
  approved: boolean;
  avatar: string;
  connectedAccounts: ConnectAccount[];
  did: string;
  pk: string;
  email: string;
  fullName: string;
  role: UserRole;
  locale: UserLocale;
  passports: Passport[];
  permissions: any[];
  sourceAppPid?: string;
  sourceProvider?: WalletProvider;
  didSpace?: object;
  remark?: string;
  createdAt: string;
  updatedAt: string;
  firstLoginAt?: string;
  lastLoginAt?: string;
  lastLoginIp?: string;
};

export type SessionProps = {
  action: string;
  error: string;
  initialized: boolean;
  loading: boolean;
  open: boolean;
  walletOS: WalletOS;
  user?: User;
  locale: UserLocale;
  provider?: WalletProvider;
  baseUrl?: string;
  federatedMaster?: object;
  login: LoginSessionFn;
  logout: LogoutSessionFn;
  switch: Function;
  switchDid: CommonSessionFn;
  autoSwitchDid: Function;
  switchProfile: CommonSessionFn;
  switchPassport: CommonSessionFn;
  bindWallet: CommonSessionFn;
  refresh: Function;
  updateConnectedInfo: (data: object) => void;
  openDidConnect: OpenDidConnect;

  useOAuth: Function;
  OAuthProvider: Function;
  OAuthConsumer: Function;
  OAuthContext: object;

  usePasskey: Function;
  PasskeyProvider: Function;
  PasskeyConsumer: Function;
  PasskeyContext: object;

  useDid: (options: { session: Session }) => void;
  WrapDid: Function;
  getUserSessions: () => Promise<UserSession[]>;
};

export type SessionStorageProps = {
  getToken: Function;
  setToken: Function;
  removeToken: Function;
};

export type SessionContext = {
  api: AxiosInstance; // api 实例(axios)
  events: EventEmitter; // session 事件订阅器
  storage: SessionStorageProps; // sessionToken 的存储实例
  session: SessionProps; // session 实例
  connectApi: {
    open: OpenConnect;
    close: CloseConnect;
  }; // use-connect 的 connectApi
};

export interface TokenState {
  checking: boolean;
  loading: boolean;
  token: string;
  url: string;
  store: object;
  status: 'created' | 'scanned' | 'succeed' | 'error' | 'timeout' | 'busy' | 'forbidden';
  error: string;
  checkCount: number;
  mfaCode?: number;
  appInfo: object;
  memberAppInfo: object;
  connectedDid: string;
  saveConnect: boolean;
  inExistingSession: boolean;
  nextWorkflow?: string;
  baseUrl: string;
  prefix: string;
  extraParams: object;
  checkFn: Function;
  results: object;
  action: string;
  provider: 'wallet' | 'auth0' | 'apple' | 'github' | 'google';
}

export type SwitchBehavior = 'auto' | 'disabled' | 'required';
export type DIDConnectUrlOptions = {
  switchBehavior: SwitchBehavior;
  sourceAppPid: string;
  forceConnected: boolean | string;
};
