/**
 * AccountService — 微信 ⇄ QQ 双登录态切换业务编排（零业务耦合）
 *
 * 职责：
 *  - 集中管理 wx.onLaunch / wx.onShow 入口（QQ 插件初始化 / 票据回包处理）
 *  - 提供「切换 QQ 账号 / 切换微信账号」入口
 *  - 切号成功后清本地登录态 + 通知业务方重新走登录流程
 *
 * 设计原则：所有业务依赖（接口域名、post、storage、toast、玩家服务、是否 QQ
 * 账号判断等）均由调用方通过 `configure()` 注入，本目录不依赖任何外部业务包。
 *
 * 典型用法：
 * ```ts
 * import { AccountService } from 't-comm/es/qq-mp';
 *
 * AccountService.configure({
 *   qqAppId: 123456,
 *   post,
 *   getQQLoginUserInfoHost: () => isTestEnv()
 *     ? 'https://atest.igame.qq.com'
 *     : 'https://a.igame.qq.com',
 *   storage: {
 *     set: (k, v) => oops.storage.set(k, v),
 *     get:  (k)   => oops.storage.get(k),
 *     remove: (k) => oops.storage.remove(k),
 *   },
 *   loginInfoStorageKey: apiConfig.loginInfoStorageKey,
 *   isQQAccount,                                // () => boolean
 *   toast: msg => ToastTip.show(msg),
 *   clearPlayer:     () => PlayerService.ins.clear(),
 *   bootstrapPlayer: opts => PlayerService.ins.bootstrap(opts),
 * });
 *
 * // 启动期
 * AccountService.ins.handleAppOnLaunch();
 *
 * // 设置页
 * AccountService.ins.switchToQQ();
 * AccountService.ins.switchToWx();
 * ```
 */
import { checkIsQQEnv } from './qq-mini-plugin';
import { QQPostFn, QQStorageLike, QQTicketInfo } from './types';
/**
 * AccountService 运行所需的所有外部依赖
 *
 * 全部由业务方在启动期通过 `AccountService.configure(deps)` 一次性注入。
 */
export interface AccountServiceDeps {
    /** QQ 互联 AppId（业务方常量） */
    qqAppId: string | number;
    /** 通用 post 方法（用于调 QueryUserInfo 接口） */
    post: QQPostFn;
    /**
     * QueryUserInfo 接口域名
     *
     * 支持函数形式以便在测试/正式环境间动态切换。
     */
    getQQLoginUserInfoHost: string | (() => string);
    /**
     * storage 适配器
     *
     * 用于读写 loginInfo / QQ 票据缓存。
     * 一般直接桥接到业务方的 oops.storage 即可。
     */
    storage: QQStorageLike;
    /** loginInfo 在 storage 中的 key（业务方决定） */
    loginInfoStorageKey: string;
    /**
     * QQ 票据在 storage 中的 key（可选）
     *
     * **不传时默认为 `${loginInfoStorageKey}__qq_ticket`**。
     *
     * 必须与 `loginInfoStorageKey` 区分开：同一个 key 会导致 QQ 票据覆盖业务方身份的
     * loginInfo（如 cocos `loginMp` 写入的 `Logininfo` header 结果）。
     */
    qqTicketStorageKey?: string;
    /** 当前是否为 QQ 账号（业务方根据自家 loginInfo 结构判断） */
    isQQAccount: () => boolean;
    /**
     * 是否「在 QQ 环境下强制 QQ 登录态」（可选）
     *
     * 默认 `() => true`，即启动期一旦检测到「QQ 环境 + 微信登录态」就清 storage
     * 让游戏重走 QQ 登录。
     *
     * 若业务期望「QQ App 下也允许手动切到微信账号」，请传入 `() => false`，
     * 或基于「用户是否手动切到微信账号」返回动态值。
     */
    shouldForceQQ?: () => boolean;
    /**
     * QQ App 环境下【切换 QQ 账号】的后台探身入口（可选）
     *
     * 不传则 fallback 到“跳腾讯 QQ 小程序”（launchQQMP）路径。
     *
     * 实现参考 [src/cocos/login/login.ts](../cocos/login/login.ts) 中的 `loginMp`：
     * 拿到 code 后调业务后台的「_ltype=tiploginqqproc」路径换登录态。
     *
     * @example
     * code2QQLogin: code => loginMp({
     *   url: getApiHost() + '/login',
     *   appid: WX_APP_ID,
     *   _ltype: 'tiploginqqproc',
     *   storage,
     *   onLoginInfo: (info) => updateLocalLoginInfo(info),
     * }),
     *
     * 注：loginMp 内部会自己调 wx.login 拿 code；AccountService 这里会优先用
     * `qqPluginLogin()` 拿到 QQ code 传入 ，以便业务后台拿到的是 QQ 账号的 code。
     */
    code2QQLogin?: (code: string) => Promise<unknown> | unknown;
    /**
     * QQ App 环境下【切换微信账号】的后台探身入口（可选）
     *
     * 不传则 fallback 到“清 storage + bootstrapPlayer”的原路径（适用于微信宿主）。
     *
     * 实现参考 [src/cocos/login/login.ts](../cocos/login/login.ts) 中的 `loginMp`：
     * 拿到 code 后调业务后台的「_ltype=tiploginwxproc」路径换登录态。
     */
    code2WxLogin?: (code: string) => Promise<unknown> | unknown;
    /**
     * 【微信宿主下】拿到 QQ 票据后的后台探身入口（可选但强烈推荐）
     *
     * 背景：微信宿主下 QQ 登录路径是
     *   1. `launchQQMP` 跳腾讯 QQ 小程序
     *   2. QQ 小程序 navigateBack 后、`wx.onShow` 从 referrerInfo 中提取到 QQ 票据
     *   3. 依据票据走业务后台换取登录态
     *
     * 本函数负责第三步。业务侧一般会用
     * [src/cocos/login/login.ts](../cocos/login/login.ts) 的 `loginMp({
     *   _ltype: 'tiploginqqproc',
     *   code: ticket.qqAccessToken,
     *   ...
     * })` 实现，`loginMp` 会负责读 `Logininfo` 响应头并写入 storage。
     *
     * **未传时的 fallback**：内部调 `queryQQLoginUserInfo`（快路，仅 H5 等响应头
     * 能被项目统一拦截的环境可用）。
     *
     * @example
     * qqTicket2Login: ticket => loginMp({
     *   url: getApiHost() + '/login',
     *   appid: WX_APP_ID,
     *   _ltype: 'tiploginqqproc',
     *   code: ticket.qqAccessToken,
     *   storage,
     *   storageKey: loginInfoStorageKey,
     * }),
     */
    qqTicket2Login?: (ticket: QQTicketInfo) => Promise<unknown> | unknown;
    /**
     * 显示 toast 提示
     *
     * 由业务方决定使用 ToastTip / wx.showToast 等何种实现。
     */
    toast: (message: string) => void;
    /** 清空玩家本地缓存（如 PlayerService.ins.clear） */
    clearPlayer: () => void;
    /**
     * 强制重新启动玩家服务（如 PlayerService.ins.bootstrap({ force: true })）
     */
    bootstrapPlayer: (options: {
        force: boolean;
    }) => Promise<unknown> | void;
    /**
     * 登录成功后的业务回调（可选）
     *
     * 触发时机：`switchToQQ` / `switchToWx` 的所有成功路径（含「已是当前账号」的幂等分支）
     * 都会在 `bootstrapPlayer` 拿到玩家数据后调用本函数。
     *
     * 典型用途：业务方在此派发全局事件、关闭登录页、上报埋点等。
     *
     * 语义：
     *  - `platform`：当前登录态平台
     *  - `reason`：本次触发原因，业务方可用来区分「首次登录 / 切号 / 幂等重登」
     *
     * @example
     * onLoginSuccess: ({ platform, reason }) => {
     *   oops.message.dispatch(EventName.AuthAccepted, { platform, reason });
     *   oops.gui.close(UIID.Auth);
     * }
     */
    onLoginSuccess?: (info: {
        platform: 'qq' | 'wx';
        reason: LoginSuccessReason;
    }) => void;
}
/**
 * 登录成功回调的触发原因
 *
 *  - `switch`：从另一平台切换到当前平台（有实际登录动作）
 *  - `already`：调用切号入口时已经是目标平台（幂等分支，仅 bootstrap 拉最新数据）
 */
export type LoginSuccessReason = 'switch' | 'already';
/**
 * AccountService 文案配置（可选覆盖默认中文文案）
 */
export interface AccountServiceMessages {
    alreadyQQ?: string;
    alreadyWx?: string;
    switchQQFail?: string;
    switchWxSuccess?: string;
    switchWxFail?: string;
    switchQQRetry?: string;
    switchQQSuccess?: string;
}
export declare class AccountService {
    private static _ins;
    private static _deps;
    private static _messages;
    /**
     * 注入运行所需依赖（应用启动期调用一次即可）
     *
     * 多次调用会覆盖之前的依赖，便于测试时替换。
     */
    static configure(deps: AccountServiceDeps, messages?: AccountServiceMessages): void;
    /** 获取当前注入的依赖（未注入时抛错） */
    private static getDeps;
    /** 单例 */
    static get ins(): AccountService;
    /** QQ 票据存储 key（默认 `${loginInfoStorageKey}__qq_ticket`） */
    private static getQQTicketStorageKey;
    /** 防止 wx.onShow 重复绑定 */
    private _onShowBound;
    /** 防止"切号过程中再次点击"重复触发 */
    private _switching;
    private constructor();
    /** 当前是否为 QQ 账号（基于注入的 isQQAccount） */
    isQQ(): boolean;
    /** 「切换 QQ 账号 / 切换微信账号」按钮的动态文案 */
    getSwitchButtonText(): string;
    /**
     * onLaunch / Game.bootstrap 阶段调用：
     *
     *  1) 初始化 qq-wxmini-plugin（QQ 用户访问微信小游戏的插件）
     *  2) 若当前是 QQ 环境但本地仍是微信登录态，自动清空 storage 让游戏重走 QQ 登录
     *  3) 主动绑定 wx.onShow：QQ 登录小程序返回时提取票据并换登录态
     */
    handleAppOnLaunch(): void;
    /**
     * 「切换QQ账号」点击入口
     *
     * 根据运行环境自动分流：
     *  - QQ App 环境（`checkIsQQEnv() === true`）且业务传入了 `code2QQLogin`：
     *      调用 `qqPluginLogin()` 直接拿 QQ code → 交 `code2QQLogin` 探后台换登录态。
     *      业务后台路径参考 [src/cocos/login/login.ts](../cocos/login/login.ts) 的 `loginMp`（`_ltype=tiploginqqproc`）。
     *  - 微信宿主环境（或未传 `code2QQLogin`）：
     *      `launchQQMP` → 腾讯 QQ 小程序登录 → `wx.onShow` 提取票据 → `QueryUserInfo` 换登录态。
     */
    switchToQQ(): Promise<void>;
    /**
     * 「切换微信账号」点击（当前账号是 QQ 时）
     *
     * 根据运行环境自动分流：
     *  - QQ App 环境（`checkIsQQEnv() === true`）且业务传入了 `code2WxLogin`：
     *      调用 `wxLogin()` 拿微信 code → 交 `code2WxLogin` 探后台换登录态。
     *      业务后台路径参考 [src/cocos/login/login.ts](../cocos/login/login.ts) 的 `loginMp`（`_ltype=tiploginwxproc`）。
     *  - 微信宿主环境（或未传 `code2WxLogin`）：
     *      微信小游戏本身就是微信宿主，"切回微信"等价于：清掉 QQ 登录态（loginInfo + QQ 票据缓存）
     *      → 让 SDK 重新用 wx.login 走微信登录。
     */
    switchToWx(): Promise<void>;
    /**
     * QQ App 环境下「切换 QQ 账号」的直达路径：插件 login 拿 code → 交业务探后台
     */
    private _switchToQQViaPlugin;
    /**
     * QQ App 环境下「切换微信账号」的直达路径：wx.login 拿 code → 交业务探后台
     */
    private _switchToWxViaCode;
    /**
     * 绑定 wx.onShow（幂等）：
     *   - 启动时由 handleAppOnLaunch 调用一次
     *   - 业务页面再次需要可重复调用
     */
    private _bindWxOnShow;
    /** wx.onShow 回调：处理从腾讯 QQ 小程序返回的票据 */
    private _onWxShow;
    /**
     * 用 QQ 票据换取登录态 + 重启玩家服务
     *
     * 优先级：
     *  1. 业务侧注入了 `qqTicket2Login`（推荐，如 cocos `loginMp(_ltype=tiploginqqproc, code=qqAccessToken)`）→ 走它。
     *  2. 否则 fallback 到 `queryQQLoginUserInfo`（仅适用于能统一拦截 `Logininfo` 响应头的环境）。
     */
    private _consumeQQTicket;
    /**
     * 统一登录成功收尾：clearPlayer → bootstrapPlayer → toast → onLoginSuccess → 释放 _switching
     *
     * 说明：
     *  - `switching` 语义与 UI 层「登录中」loading 是同一件事，因此在 bootstrap 完成前
     *    保持为 true；bootstrap 结果 resolve 或 reject 都释放
     *  - toast 文案根据 platform 选：QQ = switchQQSuccess；WX = switchWxSuccess
     *  - onLoginSuccess 在 toast 之后调，业务侧派事件/关登录页由回调决定
     *  - bootstrapPlayer 失败仍会触发 onLoginSuccess？NO：bootstrap 抛错代表玩家数据
     *    没拉到，登录不算完整成功，跳过 toast 与 onLoginSuccess，让业务侧看到 catch
     */
    private _finishLoginOk;
}
export { checkIsQQEnv };
