/**
 * 聚合广告 SDK - 主入口
 *
 * 使用方式：
 *   import { AdSdk, AdPlatform, AdEvent } from './ad-sdk';
 *   await AdSdk.init({ platform: AdPlatform.Xiaomi });
 *   const result = await AdSdk.requestAd({ cpId: 'cp_001', rewardType: 'extra_life', triggerScene: 'game_over' });
 */

import { AdPlatform, AdEvent, AdErrorCode, AdType, DevicePlatform, KeyCode, KeyAction } from './types/enums';
import { XiaomiAdapter } from './adapters/xiaomi-adapter';
import { EventEmitter } from './event-emitter';
import { Reporter, ActionType } from './reporters/reporter';
import { Leaderboard } from './leaderboard/leaderboard';
import { UserGameData } from './user-gamedata/user-gamedata';
import {
    IAdSdk,
    IAdSdkInitConfig,
    IAdRequest,
    IAdRewardResult,
    IDeviceInfo,
    IAccountInfo,
    IEventHandler,
    IKeyEventHandler,
    IAdAdapter,
} from './types/interfaces';
const KEY_EVENT_NAME = '__key_event__';

/** 已注册自定义适配器的平台集合 */
type AdapterConstructor = new () => IAdAdapter;

// ────────────────────────────────────────
// 适配器注册表
// ────────────────────────────────────────

const BUILTIN_ADAPTERS: Record<string, AdapterConstructor> = {};
BUILTIN_ADAPTERS[AdPlatform.Xiaomi] = XiaomiAdapter;
// 后续扩展：
// BUILTIN_ADAPTERS[AdPlatform.Huawei] = HuaweiAdapter;
// BUILTIN_ADAPTERS[AdPlatform.Tencent] = TencentAdapter;

// ────────────────────────────────────────
// SDK 实现
// ────────────────────────────────────────

class AdSdkImpl implements IAdSdk {
    _initialized: boolean;
    _currentPlatform: AdPlatform;
    _adapters: Map<AdPlatform, IAdAdapter>;
    _emitter: EventEmitter;
    _globalEventHandler: IEventHandler | null;
    _keyHandlers: IKeyEventHandler[];
    _adapterKeyHandler: IKeyEventHandler | null;

    constructor() {
        this._initialized = false;
        this._currentPlatform = AdPlatform.Xiaomi;
        this._adapters = new Map();
        this._emitter = new EventEmitter();
        this._globalEventHandler = null;
        this._keyHandlers = [];
        this._adapterKeyHandler = null;
    }

    get currentPlatform(): AdPlatform {
        return this._currentPlatform;
    }

    /**
     * 初始化 SDK
     */
    async init(config: IAdSdkInitConfig): Promise<void> {
        if (this._initialized) {
            console.warn('[AdSdk] Already initialized. Call destroy() first if you need to re-init.');
            return;
        }

        this._currentPlatform = config.platform;
        this._globalEventHandler = (config as any).onEvent || null;

        // 注册自定义适配器（如提供了 customAdapters 兼容旧用法）
        const customAdapters = (config as any).customAdapters as IAdAdapter[] | undefined;
        if (customAdapters) {
            for (const adapter of customAdapters) {
                this._adapters.set(adapter.platform, adapter);
            }
        }

        // 注册内置适配器（不覆盖自定义的）
        if (!this._adapters.has(config.platform)) {
            const AdapterClass = BUILTIN_ADAPTERS[config.platform];
            if (!AdapterClass) {
                throw new Error(
                    '[AdSdk] No adapter found for platform "' + config.platform + '". ' +
                    'Available: ' + Object.keys(BUILTIN_ADAPTERS).join(', ') + '. ' +
                    'You can also provide a custom adapter via config.customAdapters.'
                );
            }
            const instance = new AdapterClass();
            this._adapters.set(config.platform, instance);
        }

        // 初始化当前平台的适配器（从 config.cpId 构建适配器配置）
        const adapter = this._adapters.get(config.platform) as IAdAdapter;
        const adapterConfig = { cpId: config.cpId };
        await adapter.init(adapterConfig);

        // 桥接适配器事件到全局
        const self = this;
        const events = Object.values(AdEvent);
        for (let i = 0; i < events.length; i++) {
            const evt = events[i];
            adapter.on(evt, function (data: any) {
                self._emitter.emit(evt, data);
                if (self._globalEventHandler) {
                    self._globalEventHandler(data);
                }
            });
        }

        // 桥接适配器的退出事件 → 调用 reporter 上报退出
        adapter.on(AdEvent.Exit, function () {
            Reporter.reportAppExit();
        });

        // 桥接适配器的按键事件
        if (adapter.onKeyEvent) {
            self._adapterKeyHandler = function (keyEvent) {
                for (let j = 0; j < self._keyHandlers.length; j++) {
                    try {
                        self._keyHandlers[j](keyEvent);
                    } catch (e) {
                        console.error('[AdSdk] Key event handler error:', e);
                    }
                }
            };
            adapter.onKeyEvent(self._adapterKeyHandler);
        }

        // 自动初始化排行榜模块（serverUrl/project/platform 由 ad-sdk 统一处理）
        Leaderboard.init({
            serverUrl: config.serverUrl,
            project: config.project,
            platform: config.gamePlatform,
        });

        // 自动初始化用户游戏数据模块（serverUrl/project/platform 由 ad-sdk 统一处理）
        UserGameData.init({
            serverUrl: config.serverUrl,
            project: config.project,
            platform: config.gamePlatform,
        });

        // 自动初始化数据上报模块（传入 reporter 配置，无配置时使用空对象默认初始化）
        Reporter.init(config.reporter || {});

        this._initialized = true;
        console.log('[AdSdk] Initialized with platform: ' + config.platform);

        // 上报「启动」事件
        Reporter.reportAppStart();

        // 尝试拉取账号信息，作为排行榜/玩家数据/数据上报的默认 userId（失败则保留默认值）
        await this._syncUserIdFromAccount();

        console.log('[AdSdk] Lifecycle reporting bound.');
    }

    /**
     * 尝试从 getAccount() 拉取账号 uid，同步为各模块默认 userId。
     * 获取失败或无 uid 时，使用本机持久化的设备 ID 作为默认 userId。
     */
    private async _syncUserIdFromAccount(): Promise<void> {
        let uid = '';
        try {
            const account = await this.getAccount();
            uid = account && account.uid ? account.uid : '';
        } catch (error) {
            console.warn('[AdSdk] getAccount failed, fallback to device id.', error);
        }

        // getAccount 失败或无 uid 时，使用本机持久化的设备 ID 作为默认 userId
        if (!uid) {
            uid = defaultUserId();
        }
        if (!uid) {
            return;
        }
        Leaderboard.setUserId(uid);
        UserGameData.setUserId(uid);
        Reporter.setCommonInfo({ uid: uid, user_id: uid });
        console.log('[AdSdk] Default userId synced:', uid);
    }

    /**
     * 获取设备信息
     */
    async getDeviceInfo(): Promise<IDeviceInfo> {
        this._ensureInit();
        const adapter = this._getAdapter();
        if (adapter.getDeviceInfo) {
            return adapter.getDeviceInfo();
        }
        throw new Error('[AdSdk] getDeviceInfo is not supported by the current adapter.');
    }

    /**
     * 获取玩家账户信息
     */
    async getAccount(): Promise<IAccountInfo> {
        this._ensureInit();
        const adapter = this._getAdapter();
        if (adapter.getAccount) {
            return adapter.getAccount();
        }
        throw new Error('[AdSdk] getAccount is not supported by the current adapter.');
    }

    /**
     * 请求播放广告
     */
    async requestAd(request: IAdRequest): Promise<IAdRewardResult> {
        this._ensureInit();
        return this._getAdapter().requestAd(request);
    }

    /**
     * 通知游戏加载完成
     */
    onGameReady(version: string): void {
        this._ensureInit();
        const adapter = this._getAdapter();
        if (adapter.onGameReady) {
            adapter.onGameReady(version);
        }
    }

    /** 通知游戏暂停（自动上报切后台） */
    onGamePause(): void {
        this._ensureInit();
        Reporter.reportSwitchBackground();
        const adapter = this._getAdapter();
        if (adapter.onGamePause) {
            adapter.onGamePause();
        }
    }

    /** 通知游戏恢复（自动上报切回） */
    onGameResume(): void {
        this._ensureInit();
        Reporter.reportSwitchBack();
        const adapter = this._getAdapter();
        if (adapter.onGameResume) {
            adapter.onGameResume();
        }
    }

    /**
     * 退出游戏（自动上报退出事件后执行实际退出）
     */
    async exitGame(): Promise<void> {
        this._ensureInit();
        // 通知适配器执行退出，适配器的 onExitConfirmed 回调会触发上报
        const adapter = this._getAdapter();
        if (adapter.exitGame) {
            return adapter.exitGame();
        }
    }

    /**
     * 监听广告事件
     */
    on(event: AdEvent, handler: IEventHandler): void {
        this._emitter.on(event, handler);
    }

    /**
     * 取消监听
     */
    off(event: AdEvent, handler?: IEventHandler): void {
        this._emitter.off(event, handler);
    }

    /**
     * 监听遥控器按键事件
     */
    onKeyEvent(handler: IKeyEventHandler): void {
        if (typeof handler === 'function' && this._keyHandlers.indexOf(handler) === -1) {
            this._keyHandlers.push(handler);
        }
    }

    /**
     * 取消监听遥控器按键事件
     */
    offKeyEvent(handler?: IKeyEventHandler): void {
        if (!handler) {
            this._keyHandlers = [];
        } else {
            const idx = this._keyHandlers.indexOf(handler);
            if (idx !== -1) {
                this._keyHandlers.splice(idx, 1);
            }
        }
    }

    /**
     * 切换广告平台
     */
    switchPlatform(platform: AdPlatform): void {
        if (platform === this._currentPlatform) return;

        const adapter = this._adapters.get(platform);
        if (!adapter) {
            throw new Error('[AdSdk] Platform "' + platform + '" not registered. Init with it first.');
        }

        this._currentPlatform = platform;
        console.log('[AdSdk] Switched to platform: ' + platform);
    }

    /** 销毁 SDK */
    destroy(): void {
        // 清理适配器的按键桥接
        const adapter = this._getAdapter();
        if (adapter && adapter.offKeyEvent && this._adapterKeyHandler) {
            adapter.offKeyEvent(this._adapterKeyHandler);
        }

        this._adapters.forEach(function (adp) {
            adp.destroy();
        });
        this._adapters.clear();
        this._emitter.removeAllListeners();
        this._globalEventHandler = null;
        this._keyHandlers = [];
        this._adapterKeyHandler = null;
        this._initialized = false;
    }

    // ────────────────────────────────────────
    // 内部
    // ────────────────────────────────────────

    _ensureInit(): void {
        if (!this._initialized) {
            throw new Error('[AdSdk] SDK not initialized. Call AdSdk.init() first.');
        }
    }

    _getAdapter(): IAdAdapter {
        return this._adapters.get(this._currentPlatform) as IAdAdapter;
    }
}

// ────────────────────────────────────────
// 导出单例
// ────────────────────────────────────────

const AdSdk: IAdSdk = new AdSdkImpl();

// 命名导出
export {
    // 单例
    AdSdk,

    // 枚举
    AdPlatform,
    AdType,
    AdEvent,
    AdErrorCode,
    DevicePlatform,
    KeyCode,
    KeyAction,

    // 数据上报
    Reporter,
    ActionType,

    // 排行榜
    Leaderboard,

    // 用户游戏数据
    UserGameData,

    // 类
    XiaomiAdapter,
    EventEmitter,
};

const DEVICE_ID_KEY = 'ad-sdk.device_id';
const MAX_USER_ID_LEN = 12;

/** 生成本机持久化的设备 ID（仅字母数字，用于访问时兜底 userId） */
function defaultUserId(): string {
    let id = '';
    try {
        if (typeof localStorage !== 'undefined') {
            id = localStorage.getItem(DEVICE_ID_KEY) || '';
        }
    } catch (e) { /* ignore */ }

    if (!id) {
        // 用时间戳 + 随机数组成 ID，去除非法字符并截断
        const raw = String(Date.now()) + Math.random().toString(36).slice(2);
        id = raw.replace(/[^a-zA-Z0-9]/g, '').slice(0, MAX_USER_ID_LEN);
        try {
            if (typeof localStorage !== 'undefined') {
                localStorage.setItem(DEVICE_ID_KEY, id);
            }
        } catch (e) { /* ignore */ }
    }

    return String(id).replace(/[^a-zA-Z0-9]/g, '').slice(0, MAX_USER_ID_LEN);
}

export default AdSdk;