import Utils from "../module/Pay/Utils";
import { getProvinceName } from "../module/Position/GetPosition";
// import { getProvinceName } from "../module/Position/ProvinceLocator";

/**
 * 小游戏平台SDK工具封装，目前只支持微信和抖音平台
 */
export namespace MiniGameSdk {

    interface ISize {
        width: number;
        height: number;
    }

    export interface IPosition {
        top: number;
        left: number;
    }

    export function isWechat(): boolean {
        //@ts-ignore
        return window.wx !== null && window.wx !== undefined;
    }

    export function isBytedance(): boolean {
        //@ts-ignore
        return window.tt !== null && window.tt !== undefined;
    }


    function getSysWinSize(): ISize {
        let sys: any;
        if (isWechat()) {
            // @ts-ignore
            sys = wx.getSystemInfoSync();
        } else if (isBytedance()) {
            // @ts-ignore
            sys = tt.getSystemInfoSync();
        }

        let size: ISize = { width: 0, height: 0 };
        if (sys) {
            size.width = sys.windowWidth;
            size.height = sys.windowHeight;
        }

        return size;
    }

    /**
     * 插屏广告。微信抖音都支持！
     */
    class ADInterstitial {
        private _adUid: string;
        private _interstitial: any;

        get aduid() {
            return this._adUid;
        }

        constructor(adUid: string) {
            this._adUid = adUid;
        }

        show() {
            // @ts-ignore
            if (isWechat() && !wx.createInterstitialAd) {
                console.warn('wechat unsupport interstitial AD!');
                this._interstitial = null;
                return;
            }

            // @ts-ignore
            if (isBytedance() && !tt.createInterstitialAd) {
                console.warn('bytedance unsupport interstitial AD!');
                this._interstitial = null;
                return;
            }


            if (this._interstitial) {
                this._interstitial.load();
            } else {
                if (isWechat()) {
                    // @ts-ignore
                    this._interstitial = wx.createInterstitialAd({ adUnitId: this._adUid });
                } else if (isBytedance()) {
                    // @ts-ignore
                    this._interstitial = tt.createInterstitialAd({ adUnitId: this._adUid });
                } else {
                    this._interstitial = null;
                }

                this._interstitial?.onLoad(() => {
                    console.log('load interstitial ad success');
                    this._interstitial.show().catch((err: any) => {
                        console.log('catch interstitial ad error:', err);
                    });
                });

                this._interstitial?.onError((err: any) => {
                    console.log('interstitial ad on error:', err);
                });
            }
        }
        destory() {
            this._interstitial?.destroy();
            if (this._interstitial) {
                this._interstitial = null;
            }
        }
    }

    class ADBanner {
        private _adUid: string;
        private _banner: any;

        get aduid() {
            return this._adUid;
        }

        /**
         * 抖音和微信都支持
         * 横幅广告。预估宽度默认为300，预估高度为140。如果你不确定就按默认值来。
         * @param adUid 广告UID，后端配置
         * @param isTop 是否在屏幕顶部展示。内部会自动居中计算位置。
         * @param bannerWidth 横幅广告的预估宽度。默认300
         * @param autoShow 广告加载完成后是否立刻显示，默认为不显示
         */
        constructor(adUid: string, param: boolean | IPosition, bannerWidth: number = 300, autoShow: boolean = false) {
            this._adUid = adUid;
            this.create(autoShow, bannerWidth, param); // 默认300比较合适
        }

        private create(autoShow: boolean, bannerWidth: number, param: boolean | IPosition) {
            if (!isWechat() && !isBytedance()) {
                this._banner = null;
                return;
            }

            this.destroy();

            let winSize = getSysWinSize();

            let height = bannerWidth * 0.4;
            let top = 0, left = 0;

            if (typeof param === "boolean") {
                left = (winSize.width - bannerWidth) / 2
                top = param ? 5 : (winSize.height - height);
            } else {
                left = param.left;
                top = param.top;
            }

            let params = {
                adUnitId: this._adUid,
                adIntervals: 30,// 自动刷新频率不能小于30秒
                style: { left: left, top: top, width: bannerWidth }
            }

            if (isWechat()) {
                // @ts-ignore
                this._banner = wx.createBannerAd(params);
            } else if (isBytedance()) {
                // @ts-ignore
                this._banner = tt.createBannerAd(params);
            } else {
                this._banner = null;
            }

            this._banner?.onError((err: any) => {
                console.log('ad banner error:', err);
            });

            this._banner?.onLoad(() => {
                autoShow && this._banner.show();
            });
        }

        show() {
            this._banner?.show();
        }

        hide() {
            this._banner?.hide();
        }

        destroy() {
            this._banner?.destroy();
        }
    }

    class ADCustom {
        private _adUid: string;
        private _adCustom: any;

        get aduid() {
            return this._adUid;
        }
        /**
         * 由于原生模板广告在微信服务后端可以定制宽度大小，个数，缩放比例等，所以位置调整要根据设置的宽度来定。抖音不支持！
         * @param adUid 广告UID，后端配置
         * @param top 从左上角开始，距离屏幕顶部的距离。注意：这个数据为设备屏幕宽度width。如果需要获取屏幕的像素，需要乘以设备像素比Pixel-Ratio，例如iPhone 13 Pro的Pixel-Ratio为3，像素为Width*3。
         * @param left 从左上角开始，距离屏幕最左边的距离。注意：这个数据为设备屏幕宽度width。如果需要获取屏幕的像素，需要乘以设备像素比Pixel-Ratio，例如iPhone 13 Pro的Pixel-Ratio为3，像素为Width*3。
         * @param scale 原生模板广告的尺寸，默认为1，即100%。此值在微信服务后端广告中获得，默认为100%，目前有100%，90%，80%三种，一般情况不用修改。若有修改，记得传入值，例如90%就传入0.9。
         */
        constructor(adUid: string, top: number = 0, left: number = 0, scale: number = 1.0) {
            this._adUid = adUid;
            this.createCustomAd(top, left, scale);
        }

        private createCustomAd(top: number, left: number, scale: number) {
            if (!isWechat()) { // only wechat support custom ad
                this._adCustom = null;
                console.log('Only wechat support Custom Ad');
                return;
            }

            this.destroy();
            // 原生模板5个应用宽度为375，若设置了缩放比例，则宽度也需要设置
            // let width = 375 * this._scale;
            // let newLeft = (sys.windowWidth - width) / 2;
            // let newTop = sys.windowHeight / 2; // 120是预估高度

            // @ts-ignore
            this._adCustom = wx.createCustomAd({
                adUnitId: this._adUid,
                //@ts-ignore
                style: { left: left, top: top, fixed: true }
            });

            this._adCustom?.onError((err: any) => {
                console.log('ad custom error:', err);
            });
        }
        show() {
            this._adCustom?.show();
        }

        hide() {
            this._adCustom?.hide();
        }

        destroy() {
            this._adCustom?.destroy();
        }
    }


    /**
     * 视频广告用户点击行为结果
     */
    export enum EAdVideoResult {
        /**
         * 用户看完了广告，游戏可发放奖励。
         */
        ACCEPT,

        /**
         * 用户中途关闭了广告，即未看完状态。不可发放奖励。
         */
        REJECT,

        /**
         * 广告组件内部发生了错误。不可发放奖励。
         */
        ERROR,
    }

    class ADVideo {
        private _adUid: string;
        private _adVideo: any = null;
        private _isLoaded: boolean = false;
        private _isLoading: boolean = false;

        get aduid() {
            return this._adUid;
        }

        constructor(adUid: string) {
            this._adUid = adUid;
        }

        /**
         * 预加载广告内容
         */
        preload(): Promise<void> {
            return new Promise((resolve, reject) => {
                if (!isWechat() && !isBytedance()) {
                    resolve();
                    return;
                }

                // 每次预加载都创建新的实例
                this._cleanup();

                // 标记为正在加载
                this._isLoading = true;
                this._isLoaded = false;

                let adInstance;
                // 创建广告实例
                if (isWechat()) {
                    try {
                        // @ts-ignore
                        adInstance = wx.createRewardedVideoAd({
                            adUnitId: this._adUid
                        });
                    } catch (e) {
                        console.error('Failed to create rewarded video ad:', e);
                        this._isLoading = false;
                        reject(e);
                        return;
                    }
                } else if (isBytedance()) {
                    // @ts-ignore
                    adInstance = tt.createRewardedVideoAd({
                        adUnitId: this._adUid,
                        multiton: true,
                        multitonRewardMsg: ['多1次奖励', '再多一次奖励', '再多一次奖励'],
                        multitonRewardTimes: 3,
                    });
                } else {
                    adInstance = null;
                }

                if (!adInstance) {
                    this._isLoading = false;
                    reject(new Error('Failed to create ad video instance'));
                    return;
                }

                // 设置超时处理
                let loadTimeout: any = null;
                const clearTimer = () => {
                    if (loadTimeout) {
                        clearTimeout(loadTimeout);
                        loadTimeout = null;
                    }
                };
                loadTimeout = setTimeout(() => {
                    console.log('Ad preload timeout');
                    this._isLoaded = false;
                    this._isLoading = false;
                    try {
                        adInstance.offLoad?.(onLoadHandler);
                        adInstance.offError?.(onErrorHandler);
                    } catch (e) {
                        console.log('Error removing listeners:', e);
                    }
                    this._cleanup();
                    resolve();
                }, 5000); // 5秒加载超时

                // 设置加载监听
                const onLoadHandler = () => {
                    clearTimer();
                    console.log('Ad preload success');
                    this._adVideo = adInstance;
                    this._isLoaded = true;
                    this._isLoading = false;
                    try {
                        adInstance.offLoad?.(onLoadHandler);
                    } catch (e) {
                        console.log('Error removing load listener:', e);
                    }
                    resolve();
                };

                const onErrorHandler = (err: { errMsg: string, errCode: number }) => {
                    clearTimer();
                    console.log('Ad preload error:', err);
                    this._isLoaded = false;
                    this._isLoading = false;
                    try {
                        adInstance.offError?.(onErrorHandler);
                    } catch (e) {
                        console.log('Error removing error listener:', e);
                    }
                    this._cleanup();
                    resolve();
                };

                adInstance.onLoad(onLoadHandler);
                adInstance.onError(onErrorHandler);

                // 开始加载广告
                adInstance.load().catch((err: any) => {
                    clearTimer();
                    console.log('Ad load error:', err);
                    this._isLoaded = false;
                    this._isLoading = false;
                    this._cleanup();
                    resolve();
                });
            });
        }
        /**
         * 由于微信和抖音视频广告机制不同，微信可以看的视频广告个数只有0和1个，抖音平台则可以看0~maxVideoCount
         * @param onResult 两个参数：第一个res是EAdVideoResult定义，第二count是用户看了多少个视频广告。
         * @param target onResult的拥有者
         * @param maxVideoCount 可以连续看最大视频个数，可最大化商业效率。默认为3个。
         * @returns 
         */
        show(onResult: (res: EAdVideoResult, count: number) => void, target?: any, maxVideoCount: number = 3, video_data: any = null): void {
            console.log("调用广告显示");
            let callback = (state: EAdVideoResult, count: number) => {
                // 确保广告实例被清理
                onResult?.call(target, state, count);
            }

            if (!isWechat() && !isBytedance()) {
                callback(EAdVideoResult.ACCEPT, 1);
                this._adVideo = null;
                return;
            }

            // 每次调用都创建新的广告实例以确保可以重复调用
            this._cleanup();

            let onAdVideoClosed = (res: any) => {
                if (this._adVideo) {
                    try {
                        this._adVideo.offClose?.(onAdVideoClosed);
                    } catch (e) {
                        console.log('Error removing close listener:', e);
                    }
                }
                let result: EAdVideoResult;
                let count: number;

                if (isWechat()) {
                    if (res && res.isEnded || res === undefined) {
                        result = EAdVideoResult.ACCEPT;
                        count = 1;
                    } else {
                        result = EAdVideoResult.REJECT;
                        count = 0;
                    }
                } else if (isBytedance()) {
                    let resConverted = res as { isEnded: boolean, count: number };
                    if (resConverted && resConverted.count > 0) {
                        result = EAdVideoResult.ACCEPT;
                        count = resConverted.count;
                    } else {
                        result = EAdVideoResult.REJECT;
                        count = 0;
                    }
                }

                // 确保在回调之前清理广告实例
                this._cleanup();
                callback(result, count);
            }
            let responseData = {
                ad_type: "激励视频",  //广告类型
                ad_placement_name: video_data?.ad_placement_name || "", //内部广告位名称    //2000复活 道具 2001 2002 2003
                ad_placement_id: "adunit-aa9a28e1631bf16f", //内部广告位ID
                current_page: video_data?.current_page || "", //所在页面  
                error_detail_info: "", //错误信息
                error_detail_code: "", //错误码
                is_filled_success: false //是否完整播放
            }

            if (isWechat()) {
                try {
                    // @ts-ignore
                    this._adVideo = wx.createRewardedVideoAd({
                        adUnitId: this._adUid
                    });
                    responseData.is_filled_success = true;
                    cc.fx.GameTool.shushu_Track("ad_response", responseData);
                } catch (e) {
                    console.error('Failed to create rewarded video ad:', e);
                    responseData.is_filled_success = false;
                    responseData.error_detail_info = e.toString();
                    responseData.error_detail_code = e.errCode?.toString() || "";
                    cc.fx.GameTool.shushu_Track("ad_response", responseData);
                    this._cleanup();
                    callback(EAdVideoResult.ERROR, 0);
                    return;
                }
            } else if (isBytedance()) {
                // @ts-ignore
                this._adVideo = tt.createRewardedVideoAd({
                    adUnitId: this._adUid,
                    multiton: true,
                    multitonRewardMsg: ['多1次奖励', '再多一次奖励', '再多一次奖励'],
                    multitonRewardTimes: maxVideoCount,
                });
            } else {
                this._adVideo = null;
            }

            // 确保广告对象已创建
            if (!this._adVideo) {
                this._cleanup();
                callback(EAdVideoResult.ERROR, 0);
                return;
            }

            this._adVideo.onLoad(() => {
                console.log('Ad load success');
            });

            this._adVideo.onError((err: { errMsg: string, errCode: number }) => {
                console.log('Ad video error:', err);
                if (this._adVideo) {
                    try {
                        this._adVideo.offError?.();
                    } catch (e) {
                        console.log('Error removing error listener:', e);
                    }
                }
                responseData.is_filled_success = false;
                responseData.error_detail_info = err.toString();
                responseData.error_detail_code = err.errCode?.toString() || "";
                cc.fx.GameTool.shushu_Track("ad_response", responseData);
                if (err.errCode) {
                    console.log('Ad video error code:', err.errCode);
                }
                // 出错后清理实例
                this._cleanup();
                callback(EAdVideoResult.ERROR, 0);

            });

            this._adVideo.onClose(onAdVideoClosed);

            let showData = {
                ad_type: "激励视频",  //广告类型
                ad_placement_name: video_data?.ad_placement_name || "", //内部广告位名称    //2000复活 道具 2001 2002 2003
                ad_placement_id: "adunit-aa9a28e1631bf16f", //内部广告位ID
                current_page: video_data?.current_page || "", //所在页面  
                error_detail_info: "", //错误信息
                error_detail_code: "", //错误码
                is_show_success: false //是否完整播放
            }
            // 尝试显示广告
            this._adVideo.show().catch((err: { errMsg: string, errCode: number }) => {
                console.log('Show video ad error:', err);
                // 尝试加载广告后再显示
                if (this._adVideo) {
                    this._adVideo.load().then(() => {
                        showData.is_show_success = true;
                        cc.fx.GameTool.shushu_Track("ad_show", showData);
                        cc.fx.GameConfig.GM_INFO.videoTime = Math.floor(Date.now() / 1000);
                        return this._adVideo?.show();
                    }).catch((loadErr: { errMsg: string, errCode: number }) => {
                        showData.is_show_success = false;
                        showData.error_detail_info = loadErr.errMsg;
                        showData.error_detail_code = loadErr.errCode.toString();
                        cc.fx.GameTool.shushu_Track("ad_show", showData);
                        console.log('Load and show video ad error:', loadErr);
                        if (loadErr.errCode) {
                            console.log('Load error code:', loadErr.errCode);
                        }
                        // 出错后清理实例
                        this._cleanup();
                        callback(EAdVideoResult.ERROR, 0);

                    });
                } else {
                    this._cleanup();
                    callback(EAdVideoResult.ERROR, 0);
                }
            });
        }

        private _cleanup() {
            if (this._adVideo) {
                try {
                    // 移除所有事件监听器
                    this._adVideo.offLoad?.();
                    this._adVideo.offError?.();
                    this._adVideo.offClose?.();
                } catch (e) {
                    console.log('Error removing ad event listeners:', e);
                }
            }
            this._adVideo = null;
            this._isLoaded = false;
            this._isLoading = false;
        }

        destory() {
            this._cleanup();
        }
    }

    export enum EAdBannerLocation {
        /**
         * 屏幕顶部
         */
        TOP,

        /**
         * 屏幕底部
         */
        BOTTOM,
    }

    export class AdvertManager {

        private static _instance: AdvertManager;

        static get instance(): AdvertManager {
            if (!AdvertManager._instance) {
                AdvertManager._instance = new AdvertManager();
            }
            return AdvertManager._instance;
        }

        private _video: ADVideo;
        private _interstitial: ADInterstitial;
        private _banner: ADBanner;
        private _customs: Record<string, ADCustom> = {};
        private _preloadPromise: Promise<void> | null = null; // 用于跟踪预加载状态

        private constructor() {

        }
        /**
         * 预加载视频广告
         * @param adUid 广告ID
         * @returns Promise<void>
         */
        public preloadVideo(adUid: string): Promise<void> {
            // 如果已有相同广告ID的实例，先销毁
            if (this._video && this._video.aduid !== adUid) {
                this._video.destory();
                this._video = null;
            }

            // 创建新实例（如果需要）
            if (!this._video) {
                this._video = new ADVideo(adUid);
            }

            // 执行预加载
            this._preloadPromise = this._video.preload();
            return this._preloadPromise;
        }
        /**
         * 检查广告是否已预加载完成
         * @returns Promise<void>
         */
        public isPreloadReady(): Promise<void> {
            console.log("加载广告中...", this._preloadPromise)
            return this._preloadPromise || Promise.resolve();
        }

        /**
         * 预加载横幅广告，不会显示。只有你在调用showBanner时才会显示。
         * 可重复调用，但是会销毁上一次的实例。一般情况，全局有一个就行了，太多占用内存，而且没必要。
         * @param adUid 广告UID
         * @param location 位置有两种情况：1、可以传入枚举值，默认上方; 2、可以自定义位置传入IPosition，注意IPosition中的top和left跟平台的top,left是一致（没有乘以设备像素比ratio），需要开发者自己调试位置
         * @param scale 默认为跟屏幕一样的宽度，可以通过设置缩放比例来调整大小。当然，平台有规定最大或最小宽度，函数内部会自动计算。
         */
        public loadBanner(adUid: string, location: EAdBannerLocation | IPosition = EAdBannerLocation.TOP, scale: number = 1.0) {
            this._banner?.destroy();
            let size: ISize = getSysWinSize();
            // 当 style.width 小于 300 时，会取作 300。 当 style.width 大于屏幕宽度时，会取作屏幕宽度。
            let width = size.width * scale;
            width = width < 300 ? 300 : width; // 最小值矫正
            width = width > size.width ? size.width : width; //最大值矫正
            this._banner = typeof location === 'number' ? new ADBanner(adUid, location === EAdBannerLocation.TOP, width, false) : new ADBanner(adUid, location, width, false);
        }

        /**
         * 显示横幅广告
         */
        public showBanner() {
            if (this._banner) {
                this._banner.show();
            } else {
                console.warn('MiniGameSDK: banner is null, you must call loadBanner(...) first!');
            }
        }

        /**
         * 隐藏横幅广告
         */
        public hideBanner() {
            this._banner?.hide();
        }

        /**
         * 弹出插屏广告
         * @param adUid 广告单元id
         */
        public showInterstitial(adUid: string) {
            if (this._interstitial && this._interstitial.aduid === adUid) {
                this._interstitial.show();
            } else {
                this._interstitial?.destory();
                this._interstitial = new ADInterstitial(adUid);
                this._interstitial.show();
            }
        }

        /**
         * 加载原生模板广告，不会显示。只有你在调用showCustom时才会显示。
         * 由于原生模板广告在微信服务后端可以定制宽度大小，个数，缩放比例等，所以位置调整要根据设置的宽度来定。抖音不支持本函数，会调用无效！
         * @param adUid 广告ID
         * @param location 位置有两种情况：1、可以传入枚举值，默认上方; 2、可以自定义位置传入IPosition，注意IPosition中的top和left跟平台的top,left是一致（没有乘以设备像素比ratio），需要开发者自己调试位置
         * @param scale 缩放比例，默认是1，即不缩放。这个缩放并不是自己填，而是根据微信MP后台你配置的原生模板广告的缩放比例填，目前有100%，90%，80%三种，一般情况不用修改。若有后台修改，记得传入值，例如90%就传入0.9。
         */
        public loadCustom(adUid: string, location: IPosition = { top: 0, left: 0 }, scale: number = 1) {
            // this._custom?.destroy();
            // this._custom = new ADCustom(adUid, location.top, location.left, scale);
            if (this._customs[adUid]) {
                console.log(`${adUid} has been loaded.`);
                return;
            }

            this._customs[adUid] = new ADCustom(adUid, location.top, location.left, scale);
        }

        /**
         * 显示自定义广告。
         * @param adUid 广告的唯一标识符。使用此标识符来查找和显示特定的自定义广告。
         * 
         * 此方法尝试根据提供的adUid显示一个自定义广告。如果给定的adUid对应的自定义广告已加载，
         * 则调用该广告的显示方法。如果广告未加载，则在控制台输出警告信息。
         */
        public showCustom(adUid: string) {
            if (this._customs[adUid]) {
                this._customs[adUid].show();
            } else {
                console.warn(`You have not load ${adUid} of Custom AD, can not show!`);
            }
        }

        /**
         * 隐藏指定的自定义广告单元
         * 
         * 此方法用于隐藏通过广告单元标识符（adUid）指定的自定义广告。如果指定的广告单元已加载并显示，
         * 则将其隐藏；如果广告单元未加载，则在控制台输出警告信息。
         * 
         * @param adUid 广告单元标识符，用于唯一标识一个自定义广告单元。
         */
        public hideCustom(adUid: string) {
            if (this._customs[adUid]) {
                this._customs[adUid].hide();
            } else {
                console.warn(`You have not load ${adUid} of Custom AD, can not hide!`);
            }
        }

        /**
         * 由于微信和抖音视频广告机制不同，微信可以看的视频广告个数只有0和1个，抖音平台则可以看0~maxVideoCount
         * @param adUid 广告ID。如果与上一次UID不同，则内部会重新创建实例。开发者完全不用关心这个细节。
         * @param onVideoResult 两个参数：第一个res是EAdVideoResult定义，第二count是用户看了多少个视频广告。 
         * @param target onVideoResult的拥有者
         * @param maxVideoCount 最大视频个数。默认是3，仅对抖音平台生效。微信平台看完视频count的结果永远是1或0
         */
        public showVideo(adUid: string, video_data, onVideoResult: (res: EAdVideoResult, count: number) => void, target?: any, maxVideoCount: number = 3) {
            // 只有在广告ID不匹配时才重新创建实例
            if (this._video && this._video.aduid !== adUid) {
                this._video.destory();
                this._video = new ADVideo(adUid);
            } else if (!this._video) {
                this._video = new ADVideo(adUid);
            }

            this._video.show(onVideoResult, target, maxVideoCount, video_data);
        }

        /**
         * 销毁内部所有实例，清空内存
         */
        public destroyAll() {
            this._banner?.destroy();
            this._banner = null;

            this._interstitial?.destory();
            this._interstitial = null;

            this._video?.destory();
            this._video = null;

            if (this._customs) {
                for (let val in this._customs) {
                    this._customs[val]?.destroy();
                }
                this._customs = {};
            }
        }
    }

    export enum EGameClubIcon {
        /** 绿色图标 */
        GREEN = 'green',

        /** 红色图标 */
        WHITE = 'white',

        /** 有黑色圆角背景的白色图标 */
        DARK = 'dark',

        /** 有白色圆角背景的绿色图标 */
        LIGHT = 'light'
    }

    export class GameClub {
        private static _instance: GameClub;

        static get instance(): GameClub {
            if (!this._instance) {
                this._instance = new GameClub();
            }
            return this._instance;
        }

        private _club: any;

        private constructor() {

        }

        /**
         * 创建游戏圈按钮
         * @param icon 
         * @param position 
         * @param size 
         * @param openLink 
         */
        create(icon: EGameClubIcon = EGameClubIcon.GREEN, position: IPosition = { top: 0, left: 0 }, size: ISize = { width: 40, height: 40 }, openLink?: string) {
            if (isWechat()) {
                // @ts-ignore
                this._club = wx.createGameClubButton({
                    icon: icon,
                    style: {
                        left: position.left,
                        top: position.top,
                        width: size.width,
                        height: size.height
                    },
                    openlink: openLink
                });
            }
        }

        show() {
            this._club?.show();
        }

        hide() {
            this._club?.hide();
        }

        destory() {
            this._club?.destroy();
        }
    }


    /**
     * 振动类型
     */
    export enum EVirbrateType {
        /**
         * 短振动
         */
        SHORT,

        /**
         * 长振动
         */
        LONG
    }



    /**
 * 抖音侧边栏专属接口
 */
    export class BytedanceSidebar {
        /**
         * 本游戏在抖音环境下启动监控，需要放在全局环境中，保证能第一时间启动。因为可能监听抖音失败（抖音小游戏官方的说明）！
         * @param onResult 包含一个boolean参数的函数
         * @param target 上述函数的拥有者，如果是类的成员函数，需要传入this。普通或匿名函数忽略即可。
         */
        static listenFromSidebar(onResult: (success: boolean) => void, target?: any) {
            if (!isBytedance()) {
                onResult?.call(target, false);
                return;
            }
            // @ts-ignore
            tt.onShow((res: any) => {
                console.log('onShow launch res:', res);
                if (res.scene === '021036') {
                    onResult?.call(target, true);
                    console.log('launch from sidebar');
                } else {
                    onResult?.call(target, false);
                    console.log('NOT launch from douyin sidebar!');
                }
            });

            // @ts-ignore
            let options = tt.getLaunchOptionsSync();
            if (options && options.scene === '021036') {
                onResult?.call(target, true);
            }
        }

        /**
         * 检测抖音侧边栏是否存在
         * @param onResult 包含一个boolean参数的函数
         * @param target 上述函数的拥有者，如果是类的成员函数，需要传入this。普通或匿名函数忽略即可。
         * @returns 
         */
        static checkSideBar(onResult: (success: boolean) => void, target?: any) {
            if (!isBytedance()) {
                onResult?.call(target, false);
                return;
            }

            //@ts-ignore
            tt.checkScene({
                scene: "sidebar",
                success: (res: any) => {
                    console.log("check scene success: ", res.isExist);
                    onResult?.call(target, <boolean>res.isExist);

                },
                fail: (res: any) => {
                    console.log("check scene fail:", res);
                    onResult?.call(target, false);
                }
            });
        }

        /**
         * 跳转到抖音侧边栏
         * @param onResult 包含一个boolean参数的函数
         * @param target 上述函数的拥有者，如果是类的成员函数，需要传入this。普通或匿名函数忽略即可。
         * @returns 
         */
        static navigateToSidebar(onResult: (success: boolean) => void, target?: any) {
            if (!isBytedance()) {
                console.log("not douyin platform!");
                onResult?.call(target, false);
                return;
            }

            // @ts-ignore
            tt.navigateToScene({
                scene: "sidebar",
                success: () => {
                    console.log("navigate success");
                    onResult?.call(target, true);
                },
                fail: (res: any) => {
                    console.log("navigate failed reason:", res);
                    onResult?.call(target, false);
                },
            });
        }
    }

    /**
     * 平台常用API合集
     */
    export class API {
        private static _loginCode: string = null;
        private static _loginAnonymousCode: string = null;
        private static _hasInitWechatCloudFunction: boolean = false;
        private static _userInfo: any = null;
        private static _ta: any = null;
        private static _ge: any = null;
        /**
         * 分享app给朋友，微信小游戏分享是没有onSuccess回调的。
         * @param title 标题
         * @param description 细节描述信息 
         * @param imageUrl 图片地址
         * @param query 查询信息
         * @param onSuccess 抖音会回调，微信不会回调
         */
        static shareAppToFriends() {
            //@ts-ignore
            if ((typeof wx !== 'undefined' && wx !== null) || (typeof tt !== 'undefined' && tt !== null)) { // 判断是否在微信环境
                //@ts-ignore
                wx.setPreferredFramesPerSecond(60);
                // // 设置转发按钮点击后的回调

                let iphoneArr = [
                    "https://mmocgame.qpic.cn/wechatgame/Lf3SBqy9XpNkakoIZygRzXqww3HTibq6VyibazqmicwibjCS3YpgqbZtkdyABm4Y1wAr/0",
                    "https://mmocgame.qpic.cn/wechatgame/TWKuFxnCn7ksT3KXfhCC4yOfZeD4b0hrptDSJ2DFmwz02Yc8SppcwyPAOoS1MsMr/0",
                    "https://mmocgame.qpic.cn/wechatgame/dibaH2x79o1wSwBDymhyzXwfcyicaDb6R5icrFIO7251T4NgxIzXRXErHvAvn50vXFA/0",
                    "https://mmocgame.qpic.cn/wechatgame/Pgxad80d8ws3o69OicV3DTuTkcP81upQeJ0JBNS1xib3pzYLTF1ZqGY3niciaI7ICKlL/0",
                    "https://mmocgame.qpic.cn/wechatgame/SfB1vrRBIHKn9ffKFt5sib62yPLE31m2rCvk6DKlEicJNVZSoryEObD6ItwsQn4xibR/0",
                    "https://mmocgame.qpic.cn/wechatgame/OiaWk33I6QjgWiatrb5YVUq2p0QRmQgO6rLUWxEQDZ4ib9Ny4Pr8iaHnHI6WdxibY2nPL/0",
                    "https://mmocgame.qpic.cn/wechatgame/CG5xBibollws251aYD4msEPWCiafrcn4Fgtic4T2wME6sWmdfAUtfibgsWoxm59VadDD/0"
                ]
                let randomIphone = iphoneArr[Math.floor(Math.random() * iphoneArr.length)];
                let img = randomIphone;
                // const title =
                // 构建分享参数
                const shareParams = {
                    title: '快来一起玩这个超有趣的小游戏吧！', // 修改为默认分享标题
                    imageUrl: img // 修改为默认分享图片
                };
                //@ts-ignore
                // 仅设置分享内容，不主动触发分享
                wx.onShareAppMessage(() => shareParams);


                // 监听分享到朋友圈事件
                //@ts-ignore
                wx.onShareTimeline(() => {
                    return {
                        title: '你想玩上怎样的游戏？'
                    };
                });
                //@ts-ignore
                wx.showShareMenu(() => {
                    return {
                        title: '你想玩上怎样的游戏？',
                        imageUrl: img,
                        query: ''
                    };
                });

                setTimeout(() => {
                    //@ts-ignore
                    wx.showShareMenu({
                        menus: ['shareAppMessage', 'shareTimeline']
                    })
                }, 2000);

                setTimeout(() => {
                    //@ts-ignore
                    wx.showShareMenu({
                        menus: ['shareAppMessage', 'shareTimeline']
                    })
                }, 4000);

                // 设置分享到朋友圈
                //@ts-ignore
                // wx.updateShareMenu({
                //     withShareTicket: true,
                //     success: (data) => {
                //         console.log('更新分享菜单成功', data);
                //     },
                //     fail: (data) => {
                //         console.log('更新分享菜单失败', data);
                //     },
                //     complete: (data) => {
                //         console.log('更新分享菜单完成', data);
                //     }
                // });
                //@ts-ignore
            }
        }

        /**
         * 显示提示信息
         * @param title 标题
         * @param duration 时长（单位：秒）
         * @returns 
         */
        static showToast(title: string, duration: number = 2) {
            if (isWechat()) {
                // @ts-ignore
                wx.showToast({
                    title: title,
                    icon: 'none',
                    duration: duration * 500
                });
            }

        }

        /**
         * 设备震动效果，默认为短震动。注意：可能一些机型不会生效，具体看平台方的说明
         * @param type MiniGameSdk.API.EVirbrateType
         */
        static vibrate(type: EVirbrateType = EVirbrateType.SHORT) {
            if (isWechat()) {
                switch (type) {
                    case EVirbrateType.SHORT:
                        //@ts-ignore
                        wx.vibrateShort({
                            success(res: any) {
                                console.log('vibrate success:', res);
                            },
                            fail(res: any) {
                                console.log('vibrateShort failed', res);
                            },
                        });
                        break;
                    case EVirbrateType.LONG:
                        //@ts-ignore
                        wx.vibrateLong({
                            success(res: any) {
                                console.log('vibrate success', res);
                            },
                            fail(res: any) {
                                console.log(`vibrateLong failed`, res);
                            },
                        });
                        break;
                    default:
                        break;
                }
            }

            if (isBytedance()) {
                switch (type) {
                    case EVirbrateType.SHORT:
                        //@ts-ignore
                        tt.vibrateShort({
                            success(res: any) {
                                console.log('vibrate success:', res);
                            },
                            fail(res: any) {
                                console.log('vibrateShort failed', res);
                            },
                        });
                        break;
                    case EVirbrateType.LONG:
                        //@ts-ignore
                        tt.vibrateLong({
                            success(res: any) {
                                console.log('vibrate success', res);
                            },
                            fail(res: any) {
                                console.log(`vibrateLong failed`, res);
                            },
                        });
                        break;
                    default:
                        break;
                }
            }
        }

        /**
         * 重启小游戏
         */
        static reboot() {
            if (isWechat()) {
                //@ts-ignore
                wx.restartMiniProgram({
                    success: () => {
                        console.log('restart success');
                    },

                    fail: () => {
                        console.log('restart failed');
                    }
                })
            }

            if (isBytedance()) {
                try {
                    // @ts-ignore
                    tt.restartMiniProgramSync();
                } catch (error) {
                    console.log(`restartMiniProgramSync`, error);
                }
            }
        }

        /**
         * 退出小游戏
         */
        static exit() {
            if (isWechat()) {
                //@ts-ignore
                wx.exitMiniProgram({
                    success: () => {
                        console.log('exit success');
                    },
                    fail: () => {
                        console.log('exit failed');
                    }
                });
            }

            if (isBytedance()) {
                // @ts-ignore
                tt.exitMiniProgram({
                    success(res: any) {
                        console.log("exit success:", res?.data);
                    },
                    fail(res: any) {
                        console.log("exit fail:", res?.errMsg);
                    },
                });
            }
        }

        /**
         * 显示转发按钮。通常在刚进入游戏的时候调用。
         * 主要是打开平台“...”这个按钮里面的分享菜单，一般默认是关闭的，需要调用这个函数打开。可以让用户分享你的游戏入口。
         */
        static showShareMenu() {
            if (isWechat()) {
                //@ts-ignore
                wx.showShareMenu({
                    withShareTicket: true,
                    menus: ['shareAppMessage', 'shareTimeline'],
                    success: () => { },
                    fail: () => { },
                    complete: () => { }
                });
            }

        }

        /**
         * 微信小游戏：跳转到另外一款小游戏
         * 抖音小游戏：跳转到指定的视频界面
         * @param targetId 微信小游戏appid或者视频界面
         */
        static navigateTo(targetId: string, onSuccess?: () => void) {
            if (isWechat()) {
                // @ts-ignore
                wx.navigateToMiniProgram({
                    appId: targetId,
                    extraData: {
                        foo: 'bar'
                    },
                    envVersion: 'develop',
                    success(res: any) {
                        onSuccess?.();
                    }
                });
            }

            if (isBytedance()) {
                // @ts-ignore
                tt.navigateToVideoView({
                    videoId: targetId,
                    success: (res: any) => {
                        onSuccess?.();
                    },
                    fail: (err: any) => {
                        console.log("bytedance navigateToVideoView fail", err);
                    },
                });
            }
        }


        /**
         * 小游戏平台登录功能。微信返回code，抖音返回code和anonymousCode。用于登录的凭证，需要把这个code传回你的服务器程序中去调用code2Session
         * @param callback (code, anonymousCode) 第一个参数为code，微信和抖音都支持；第二个参数为匿名设备ID，仅抖音支持，失败都返回null
         */
        static login(callback: (code: string, anonymousCode: string) => void) {
            let loginPlatform = () => {
                if (isWechat()) {
                    //@ts-ignore
                    wx.login({
                        success: (res: { code: any; errMsg: any; }) => {
                            if (res.code) {
                                API._loginCode = res.code;
                                API._loginAnonymousCode = null;
                                callback?.(API._loginCode, API._loginAnonymousCode);
                            } else {
                                console.log('login error:', res.errMsg)
                            }
                        },

                        fail: () => {
                            API._loginCode = null;
                            API._loginAnonymousCode = null;
                            callback?.(API._loginCode, API._loginAnonymousCode);
                            console.log('login fail')
                        }
                    });
                } else if (isBytedance()) {
                    //@ts-ignore
                    tt.login({
                        force: true,
                        success(res: any) {
                            console.log(`login ${res.code} ${res.anonymousCode}`);
                            if (res.code) {
                                API._loginCode = res.code?.toString();
                                API._loginAnonymousCode = res.anonymousCode?.toString();
                                callback?.(API._loginCode, API._loginAnonymousCode);
                            } else {
                                console.log('login error:', res.errMsg)
                            }
                        },
                        fail(res: any) {
                            API._loginCode = null;
                            API._loginAnonymousCode = null;
                            callback?.(API._loginCode, API._loginAnonymousCode);
                            console.log(`login fail`, res);
                        },
                    });
                } else {
                    API._loginCode = null;
                    API._loginAnonymousCode = null;
                    callback?.(API._loginCode, API._loginAnonymousCode);
                    console.log('not mini game platform, login codes are all null');
                }
            }



            if (!API._loginCode) {
                loginPlatform();
            } else {
                if (isWechat()) {
                    //@ts-ignore
                    wx.checkSession({
                        success() {
                            console.log(`session is valid, use current code:`, API._loginCode);
                            callback?.(API._loginCode, API._loginAnonymousCode);
                        },
                        fail() {
                            console.log(`session expired`);
                            loginPlatform();
                        }
                    });
                } else if (isBytedance()) {
                    //@ts-ignore
                    tt.checkSession({
                        success() {
                            console.log(`session is valid, user current code: ${API._loginCode}, ${API._loginAnonymousCode}`);
                            callback?.(API._loginCode, API._loginAnonymousCode);
                        },
                        fail() {
                            console.log(`session expired`);
                            loginPlatform();
                        },
                    });

                } else {
                    console.log('not mini game platform, login null');
                    callback?.(null, null);
                }
            }
        }

        /**
 * 小游戏平台登录功能。微信返回code，抖音返回code和anonymousCode。用于登录的凭证，需要把这个code传回你的服务器程序中去调用code2Session
 * @param callback (code, anonymousCode) 第一个参数为code，微信和抖音都支持；第二个参数为匿名设备ID，仅抖音支持，失败都返回null
 */
        static getUserInfo(callback: (userInfo: any) => void) {
            //@ts-ignore
            tt.getUserInfo({
                withCredentials: true,
                success: (res: any) => {
                    API._userInfo = res;
                    callback(API._userInfo);
                },
                fail: (err: any) => {
                    callback(err);
                }
            });
        }

        /**
         * 存储用户信息，数据量不能大。可以考虑用于分数排行榜。用户之间可共享排行数据。
         * @param key 
         * @param value 
         */
        static setUserCloudStorage(key: string, value: string) {
            if (isWechat()) {
                // @ts-ignore
                wx.setUserCloudStorage({
                    KVDataList: [{ key: key, value: value }],
                    success: () => console.log(`set cloud storage success:${key}, value:${value}`),
                    fail: (err: any) => console.log('set cloud storage error:', err)
                });
            }

            if (isBytedance()) {
                // @ts-ignore
                tt.setUserCloudStorage({
                    KVDataList: [{ key: key, value: value, }],
                    success: () => console.log(`set cloud storage success:${key}, value:${value}`),
                    fail: (err: any) => console.log('set cloud storage error:', err)
                });
            }
        }

        /** 获取用户授权信息 */
        static getWechatUserInfo(callBack) {
            //微信平台授权
            if (isWechat()) {
                //@ts-ignore 
                wx.getSetting({
                    success: (res: { authSetting: { [key: string]: boolean } }) => {
                        if (res.authSetting['scope.WxFriendInteraction']) {
                            console.log('已经获得好友信息授权');
                            cc.fx.GameConfig.GM_INFO.wxFriend = true;
                        } else {
                            console.log('没授权好友信息', res);
                            cc.fx.GameConfig.GM_INFO.wxFriend = false;
                        }
                        if (res.authSetting['scope.userInfo']) {
                            console.log('用户已授权头像昵称');
                            cc.fx.GameConfig.GM_INFO.wxUserInfo = true;
                        } else {
                            console.log("用户未授权头像昵称");
                            cc.fx.GameConfig.GM_INFO.wxUserInfo = false;
                        }
                        if (callBack) {
                            callBack(true);
                        }
                    },
                    fail: (err: any) => {
                        if (callBack) {
                            callBack(false);
                        }
                        // console.error('获取用户授权状态失败', err);
                    }
                });
            }
            //抖音平台授权
            if (isBytedance()) {
                //@ts-ignore 
                tt.getSetting({
                    success: (res: { authSetting: { [key: string]: boolean } }) => {
                        if (res.authSetting['scope.WxFriendInteraction']) {
                            console.log('已经获得好友信息授权');
                            cc.fx.GameConfig.GM_INFO.wxFriend = true;
                        } else {
                            console.log('没授权好友信息', res);
                            cc.fx.GameConfig.GM_INFO.wxFriend = false;
                        }
                        if (res.authSetting['scope.userInfo']) {
                            console.log('用户已授权头像昵称');
                            cc.fx.GameConfig.GM_INFO.wxUserInfo = true;
                        } else {
                            console.log("用户未授权头像昵称");
                            cc.fx.GameConfig.GM_INFO.wxUserInfo = false;
                        }
                        if (callBack) {
                            callBack(true);
                        }
                    },
                    fail: (err: any) => {
                        if (callBack) {
                            callBack(false);
                        }
                        // console.error('获取用户授权状态失败', err);
                    }
                });
            }
        }

        /** 获取用户好友信息授权 */
        static getWechatFriend(callBack) {
            if (isWechat()) {
                //@ts-ignore
                wx.authorize({
                    scope: 'scope.WxFriendInteraction',
                    success: () => {
                        console.log('好友信息授权成功');
                        cc.fx.GameConfig.GM_INFO.wxFriend = true;
                        if (callBack) {
                            callBack(true);
                        }
                    },
                    fail: () => {
                        console.log('11111好友信息授权失败，引导用户手动开启');
                        //@ts-ignore
                        wx.openSetting({
                            success: (res) => {
                                // 用户在设置中开启权限后，重新显示排行榜
                                if (res.authSetting['scope.WxFriendInteraction']) {
                                    cc.fx.GameConfig.GM_INFO.wxFriend = true;
                                    if (callBack) {
                                        callBack(true);
                                    }
                                }
                            },
                            fail: (err: any) => {
                                if (callBack) {
                                    callBack(false);
                                }
                                console.error('打开设置界面失败', err);
                            }
                        });
                    }
                });
            }
        }


        /** 获取用户头像昵称授权 */
        static getWechatUserInfoAuth(callBack: Function) {
            if (isWechat()) {
                //@ts-ignore
                // 用户未授权，引导用户授权
                wx.getUserProfile({
                    desc: '用于完善会员资料', // 声明获取用户个人信息后的用途
                    success: (res) => {
                        console.log("拿到用户头像昵称");
                        cc.fx.GameConfig.GM_INFO.wxUserInfo = true;
                        const userInfo = res.userInfo;
                        cc.fx.GameConfig.GM_INFO.useravatar = userInfo.avatarUrl; // 用户头像 URL
                        cc.fx.GameConfig.GM_INFO.username = userInfo.nickName;   // 用户昵称
                        cc.fx.GameConfig.GM_INFO.useravatarIcon = userInfo.avatarUrl; // 用户头像框 URL
                        const user_Info = {
                            username: cc.fx.GameConfig.GM_INFO.username,
                            useravatar: cc.fx.GameConfig.GM_INFO.useravatar,
                        }
                        // console.log('用户头像:', cc.fx.GameConfig.GM_INFO.useravatar);
                        // console.log('用户昵称:', cc.fx.GameConfig.GM_INFO.username);
                        // console.log('用户授权拿到', res.userInfo);
                        cc.fx.StorageMessage.setStorage('user_Info', user_Info);
                        cc.fx.GameTool.setUserInfo(false, (data) => {
                            console.log("设置用户信息成功__________", data);
                        });
                        setTimeout(() => {
                            if (callBack) callBack(true);
                        }, 200);
                    },
                    fail: (err) => {
                        if (callBack) callBack(false);
                        MiniGameSdk.API.showToast('请先授权获取头像昵称，用于排行榜展示');
                    }
                });
            }
        }

        //#region  数数平台
        /*
        * 数数平台初始化以及登录
        */

        static shushu_Init() {
            //@ts-ignore
            if ((typeof wx !== 'undefined' && wx !== null) || (typeof tt !== 'undefined' && tt !== null)) {
                // console.log("开始接入数数平台");
                //getWechatGameVersion
                let appId = "121591378fc1423893deb12041413eb3";
                let test = cc.fx.GameTool.getWechatGameVersion();
                if (test == "正式版") {
                    appId = "87d18958cea145f29d3265470ecd3486";
                }
                const isProduction = test === '正式版'; // 假设使用 NODE_ENV 区分环境
                var config = {
                    appId: appId,
                    serverUrl: "https://data.nika4fun.com/sync_data", // 上报地址
                    autoTrack: {
                        appShow: true, // 自动采集 ta_mg_show
                        appHide: true // 自动采集 ta_mg_hide
                    },
                    // 根据环境变量设置 debug 模式
                    debug: !isProduction,
                    enableLog: false
                };
                // 创建 TA 实例
                API._ta = new ThinkingAnalyticsAPI(config);
                // 初始化
                API._ta.init();

                const distinctId = MiniGameSdk.API.getShushuDistinctId();
                if (distinctId) {
                    cc.fx.GameConfig.GM_INFO.shushu_DistinctId = distinctId;
                    console.log('用户的 distinct_id 是:', distinctId);
                } else {
                    console.log('未获取到用户的 distinct_id');
                }

                const accountId = MiniGameSdk.API.getShushuAccountId();
                if (accountId) {
                    cc.fx.GameConfig.GM_INFO.shushu_AccountId = accountId;
                    // console.log('用户的 account_id 是:', accountId);
                } else {
                    // console.log('未获取到用户的 account_id');
                }
            }
        }

        static shushu_Login() {
            //@ts-ignore
            if ((typeof wx !== 'undefined' && wx !== null) || (typeof tt !== 'undefined' && tt !== null)) {
                // console.log("数数登录时，获取到的openId:", cc.fx.GameConfig.GM_INFO.openid);
                API._ta.login(cc.fx.GameConfig.GM_INFO.openid);
                cc.fx.GameConfig.GM_INFO.shushu_AccountId = cc.fx.GameConfig.GM_INFO.openid;
                const result = "success";
                API.shushu_Track("login", result);
                API.shushu_SetSuperProperties(null, null);
            }
        }

        static shushu_userSet(time) {
            //@ts-ignore
            if ((typeof wx !== 'undefined' && wx !== null) || (typeof tt !== 'undefined' && tt !== null)) {
                // console.log("设置用户注册属性");
                API._ta.userSet({ register_time: time });
                API._ta.userSet({ uid: cc.fx.GameConfig.GM_INFO.userId.toString() });
            }
        }

        static updateCoinAndLevel() {
            //@ts-ignore
            if ((typeof wx !== 'undefined' && wx !== null) || (typeof tt !== 'undefined' && tt !== null)) {
                // console.log("上传金币和关卡信息给数数")
                API._ta.userSet({ current_level: (cc.fx.GameConfig.GM_INFO.level + 1) });
                API._ta.userSet({ current_coin: cc.fx.GameConfig.GM_INFO.coin });
                API._ta.userSet({ uid: cc.fx.GameConfig.GM_INFO.userId });
            }
        }

        /*
        * 数数平台设置动态公共属性
        */

        static shushu_SetSuperProperties(register_time, pay_user) {
            //@ts-ignore
            if (((typeof wx !== 'undefined' && wx !== null) || (typeof tt !== 'undefined' && tt !== null)) && API._ta) {
                var superProperties = {};
                superProperties = {
                    current_level: (cc.fx.GameConfig.GM_INFO.level + 1), //当前关卡等级  number
                    current_health: cc.fx.GameConfig.GM_INFO.hp,        //当前体力值
                    tmp_coin: cc.fx.GameConfig.GM_INFO.coin,//当前金币
                    freeze_amount: cc.fx.GameConfig.GM_INFO.freeze_amount,//当前道具
                    hammer_amount: cc.fx.GameConfig.GM_INFO.hammer_amount,//当前道具
                    magic_amount: cc.fx.GameConfig.GM_INFO.magic_amount,//当前道具
                    version: cc.fx.GameConfig.GM_INFO.version.toString(),//当前版本号
                    user_id: cc.fx.GameConfig.GM_INFO.userId //用户id
                };
                if (register_time != null) {
                    // console.log("设置用户公共属性注册：————————————", register_time);
                    superProperties = {
                        current_level: (cc.fx.GameConfig.GM_INFO.level + 1), //当前关卡等级  number
                        current_health: cc.fx.GameConfig.GM_INFO.hp,        //当前体力值
                        tmp_coin: cc.fx.GameConfig.GM_INFO.coin,//当前金币
                        freeze_amount: cc.fx.GameConfig.GM_INFO.freeze_amount,//当前道具
                        hammer_amount: cc.fx.GameConfig.GM_INFO.hammer_amount,//当前道具
                        magic_amount: cc.fx.GameConfig.GM_INFO.magic_amount,//当前道具
                        version: cc.fx.GameConfig.GM_INFO.version.toString(),
                        register_time: register_time,
                        user_id: cc.fx.GameConfig.GM_INFO.userId, //用户id
                        pay_user: pay_user
                    };
                }
                if (pay_user != null && pay_user != false) {
                    // console.log("设置用户公共属性支付：————————————", pay_user);
                    superProperties = {
                        current_level: (cc.fx.GameConfig.GM_INFO.level + 1), //当前关卡等级  number
                        current_health: cc.fx.GameConfig.GM_INFO.hp,        //当前体力值
                        tmp_coin: cc.fx.GameConfig.GM_INFO.coin,//当前金币 
                        freeze_amount: cc.fx.GameConfig.GM_INFO.freeze_amount,//当前道具
                        hammer_amount: cc.fx.GameConfig.GM_INFO.hammer_amount,//当前道具
                        magic_amount: cc.fx.GameConfig.GM_INFO.magic_amount,//当前道具
                        version: cc.fx.GameConfig.GM_INFO.version.toString(),
                        user_id: cc.fx.GameConfig.GM_INFO.userId, //用户id
                        pay_user: pay_user
                    }
                }
                // @ts-ignore
                // console.log("设置公共属性时:————————————", superProperties.uid);
                API._ta.setSuperProperties(superProperties);//设置公共事件属性
                API.updateCoinAndLevel();
            }
        }

        static getWechatGameVersion(): string | null {
            //@ts-ignore
            if ((typeof wx !== 'undefined' && wx !== null) || (typeof tt !== 'undefined' && tt !== null)) {
                // @ts-ignore
                const accountInfo = wx.getAccountInfoSync();
                return accountInfo.miniProgram.version;
            }
        }

        /*
        * 数数平台具体埋点
        */

        static shushu_Track(name, data, callback?: (success: boolean, error?: any) => void) {
            //@ts-ignore
            if ((typeof wx !== 'undefined' && wx !== null) || (typeof tt !== 'undefined' && tt !== null)) {
                if (API._ta) {
                    // 假设 track 方法返回一个 Promise
                    API._ta.track(
                        name, // 事件名称
                        data // 事件属性 
                    )
                }
            }
        }

        /**
         * 获取数数平台用户的 distinct_id
         * @returns distinct_id 或 null
         */
        static getShushuDistinctId(): string | null {
            //@ts-ignore
            if (typeof wx !== 'undefined' && wx !== null && API._ta) {
                // 假设 SDK 提供 getDistinctId 方法
                if (API._ta.getDistinctId) {
                    return API._ta.getDistinctId();
                }
            }
            return null;
        }

        /**
         * 获取数数平台用户的 account_id
         * @returns account_id 或 null
         */
        static getShushuAccountId(): string | null {
            //@ts-ignore
            if (typeof wx !== 'undefined' && wx !== null && API._ta) {
                // 假设 SDK 提供 getAccountId 方法
                if (API._ta.getAccountId) {
                    return API._ta.getAccountId();
                }
            }
            return null;
        }

        //#region  引力平台-
        static yinli_Init() {
            //@ts-ignore
            if ((typeof wx !== 'undefined' && wx !== null) || (typeof tt !== 'undefined' && tt !== null)) {
                const configYinli = {
                    accessToken: "aGws0nluotbm6Jjiv9WMuzOAbXLydxwe", // 项目通行证，在：网站后台-->设置-->应用列表中找到Access Token列 复制（首次使用可能需要先新增应用）
                    clientId: cc.fx.GameConfig.GM_INFO.openid, // 用户唯一标识，如产品为小游戏，则必须填用户openid（注意，不是小游戏的APPID！！！）
                    name: "ge", // 全局变量名称
                    debugMode: "none", // 是否开启测试模式，开启测试模式后，可以在 网站后台--设置--元数据--事件流中查看实时数据上报结果。（测试时使用，上线之后一定要关掉，改成none或者删除）
                    sendTimeout: 3000, // 网络请求超时时间，单位毫秒，默认值 3000 ms
                    maxRetries: 3, // 网络请求失败时的重试次数，1 表示不重试。默认值是 3
                    enablePersistence: true, // 是否使用本地缓存，主实例默认为 true，子实例默认为 false
                    asyncPersistence: false, // 是否使用异步存储，默认为 false
                    enable_sync_attribution: true, // 是否开启渠道归因，默认为 false
                    autoTrack: {
                        appLaunch: true, // 自动采集 $MPLaunch
                        appShow: false, // 自动采集 $MPShow
                        appHide: false, // 自动采集 $MPHide
                    },
                };
                API._ge = new GravityAnalyticsAPI(configYinli);
                API._ge.setupAndStart();

                API._ge.initialize({
                    name: cc.fx.GameConfig.GM_INFO.openid,
                    version: cc.fx.GameConfig.GM_INFO.version,
                    openid: cc.fx.GameConfig.GM_INFO.openid,
                    enable_sync_attribution: false,//渠道归因
                })
                    .then((res) => {
                        // console.log("引力引擎初始化成功", res)
                    })
                    .catch((err) => {
                        // console.log("引力引擎初始化失败 " + err);
                    });

                if (cc.fx.GameConfig.GM_INFO.shushu_AccountId == "") cc.fx.GameConfig.GM_INFO.shushu_AccountId =
                    cc.fx.GameConfig.GM_INFO.openid;

                const CURRENT_USER_TA_ACCOUNT_ID = cc.fx.GameConfig.GM_INFO.shushu_AccountId; // 用户唯一标识，如产品为小游戏，则必须填用户openid（注意，不是小游戏的APPID！！！）
                const CURRENT_USER_TA_DISTINCT_ID = cc.fx.GameConfig.GM_INFO.shushu_DistinctId; // 用户唯一标识，如产品为小游戏，则必须填用户openid（注意，不是小游戏的APPID！！！）
                API._ge.bindTAThirdPlatform(CURRENT_USER_TA_ACCOUNT_ID, CURRENT_USER_TA_DISTINCT_ID);

            }
        }

        static yinli_Register() {
            //@ts-ignore
            if ((typeof wx !== 'undefined' && wx !== null) || (typeof tt !== 'undefined' && tt !== null)) {
                API._ge.registerEvent();
            }
        }

        /**
         * 上报付费事件
         * @param payAmount     付费金额 单位为分
         * @param payType       货币类型 按照国际标准组织ISO 4217中规范的3位字母，例如CNY人民币、USD美金等
         * @param orderId       订单号
         * @param payReason     付费原因 例如：购买钻石、办理月卡
         * @param payMethod     付费方式 例如：支付宝、微信、银联等
         */
        static yinli_Pay(payAmount, orderId, payReason) {
            //@ts-ignore
            if ((typeof wx !== 'undefined' && wx !== null) || (typeof tt !== 'undefined' && tt !== null)) {
                let version = cc.fx.GameTool.getWechatGameVersion();
                if (version == "开发版" || version == "体验版") {
                }
                else {
                    API._ge.payEvent(payAmount, "CNY", orderId, payReason, "微信");
                }
                console.log("版本:", version);
            }
        }

        static yinli_Login() {
            //@ts-ignore
            if ((typeof wx !== 'undefined' && wx !== null) || (typeof tt !== 'undefined' && tt !== null)) {
                API._ge.loginEvent();
            }
        }

        static yinli_Track(name, data, callback?: (success: boolean, error?: any) => void) {
            //@ts-ignore
            if ((typeof wx !== 'undefined' && wx !== null) || (typeof tt !== 'undefined' && tt !== null)) {
                if (API._ge) {
                    // 假设 track 方法返回一个 Promise
                    API._ge.track(
                        name, // 事件名称
                        data // 事件属性 
                    )
                }
            }
        }

        static yinli_FinishiStage() {
            //@ts-ignore
            if ((typeof wx !== 'undefined' && wx !== null) || (typeof tt !== 'undefined' && tt !== null)) {
                if (API._ge) {
                    // 假设 track 方法返回一个 Promise
                    API._ge.track("$CompleteSection", {
                        $main_section_no: (cc.fx.GameConfig.GM_INFO.level),
                        $section_sum: (cc.fx.GameConfig.GM_INFO.level),
                        $section_type: "0"
                    });
                }
            }
        }

        //分享
        static shareGame() {
            //@ts-ignore
            if ((typeof wx !== 'undefined' && wx !== null) || (typeof tt !== 'undefined' && tt !== null)) {
                let helpLevel = cc.fx.GameConfig.GM_INFO.level + 1;
                if (cc.fx.GameTool.maxLevel()) {
                    helpLevel -= 1;
                }
                // 获取关卡信息和 UID
                const level = helpLevel;
                const uid = cc.fx.GameConfig.GM_INFO.uid;
                let iphoneArr = [
                    "https://mmocgame.qpic.cn/wechatgame/Lf3SBqy9XpNkakoIZygRzXqww3HTibq6VyibazqmicwibjCS3YpgqbZtkdyABm4Y1wAr/0",
                    "https://mmocgame.qpic.cn/wechatgame/TWKuFxnCn7ksT3KXfhCC4yOfZeD4b0hrptDSJ2DFmwz02Yc8SppcwyPAOoS1MsMr/0",
                    "https://mmocgame.qpic.cn/wechatgame/dibaH2x79o1wSwBDymhyzXwfcyicaDb6R5icrFIO7251T4NgxIzXRXErHvAvn50vXFA/0",
                    "https://mmocgame.qpic.cn/wechatgame/Pgxad80d8ws3o69OicV3DTuTkcP81upQeJ0JBNS1xib3pzYLTF1ZqGY3niciaI7ICKlL/0",
                    "https://mmocgame.qpic.cn/wechatgame/SfB1vrRBIHKn9ffKFt5sib62yPLE31m2rCvk6DKlEicJNVZSoryEObD6ItwsQn4xibR/0",
                    "https://mmocgame.qpic.cn/wechatgame/OiaWk33I6QjgWiatrb5YVUq2p0QRmQgO6rLUWxEQDZ4ib9Ny4Pr8iaHnHI6WdxibY2nPL/0",
                    "https://mmocgame.qpic.cn/wechatgame/CG5xBibollws251aYD4msEPWCiafrcn4Fgtic4T2wME6sWmdfAUtfibgsWoxm59VadDD/0"
                ]
                let randomIphone = iphoneArr[Math.floor(Math.random() * iphoneArr.length)];
                let img = randomIphone;
                // const title =
                // 构建分享参数
                const shareParams = {
                    title: '如果你突然打了个喷嚏，那一定是我在等你帮忙过关!', // 分享标题
                    path: `/pages/index/index?level=${level}&uid=${uid}`, // 分享路径，带上关卡信息和 UID
                    imageUrl: img // 分享图片链接
                };

                // 调用微信分享 API
                if (cc.sys.platform === cc.sys.WECHAT_GAME) {
                    //@ts-ignore
                    wx.shareAppMessage(shareParams);
                    let eventData = {
                        identity: "helped",  //发起者为helped  帮助者为helper
                        helpedId: cc.fx.GameConfig.GM_INFO.uid, //被帮助者uid
                        level: level //被帮助关卡等级
                    }
                    console.log("分享给好友", eventData);
                    cc.fx.GameTool.shushu_Track("stage_help", eventData); //帮助通关
                }
            }
        }

        //上传好友排行数据
        static setNewCloudlevel() {
            //@ts-ignore
            if ((typeof wx !== 'undefined' && wx !== null) || (typeof tt !== 'undefined' && tt !== null)) {
                console.log("往子域上传分数");
                let newKVData = { key: 'level', value: String(cc.fx.GameConfig.GM_INFO.level) }
                // 设置新云托管分数(第一次游戏时，也调用该方法设置云托管分数)
                //@ts-ignore
                wx.setUserCloudStorage({
                    KVDataList: [newKVData],
                    success: (res) => {
                        console.log('更新玩家分数成功！');
                    },
                    fail: (res) => {
                        console.log(res);
                    }
                });
            }
        }

        /**
   * 打开位置设置页面
   */
        static openLocationSetting() {
            //@ts-ignore
            if (typeof wx !== 'undefined' && wx !== null) {
                //@ts-ignore
                wx.openSetting({
                    success: (res) => {
                        console.log('打开设置成功:', res);
                    },
                    fail: (err) => {
                        console.log('打开设置失败:', err);
                    }
                });
            }
        }

        /**
         * 获取微信小游戏用户城市信息
         * @param callback 回调函数，参数为城市信息对象或错误信息
         * @param useReverseGeocoding 是否使用逆解析获取详细地址信息（需要网络请求）
         */
        static getWechatCityInfo(callback: (success: boolean, data?: any, error?: any) => void, useReverseGeocoding: boolean = false) {
            //@ts-ignore
            if (typeof wx !== 'undefined' && wx !== null) {
                // 检查是否已授权位置权限
                //@ts-ignore
                wx.getSetting({
                    success: (res) => {
                        if (res.authSetting['scope.userLocation']) {
                            // 已授权，获取位置信息
                            console.log("已授权，获取位置信息");
                            API._getCityInfo(callback, useReverseGeocoding);
                        } else {
                            console.log("未授权，先请求授权");
                            // 未授权，先请求授权
                            API._getCityInfo(callback, useReverseGeocoding);
                            //@ts-ignore
                            // wx.authorize({
                            //     scope: 'scope.userLocation',
                            //     success: () => {
                            //         console.log("授权成功，获取位置信息");
                            //         // 授权成功，获取城市信息
                            //         API._getCityInfo(callback, useReverseGeocoding);
                            //     },
                            //     fail: (err) => {
                            //         // 授权失败，提示用户手动授权
                            //         console.log('位置授权失败:', err);
                            //         callback(false, null, '位置授权失败，请手动授权');

                            //         // 引导用户去设置页面手动授权
                            //         //@ts-ignore
                            //         wx.showModal({
                            //             title: '位置权限申请',
                            //             content: '需要获取您的位置信息以确定所在城市，请在设置中开启位置权限',
                            //             confirmText: '去设置',
                            //             success: (modalRes) => {
                            //                 if (modalRes.confirm) {
                            //                     console.log("用户点击去设置");
                            //                     //@ts-ignore
                            //                     wx.openSetting({
                            //                         success: (settingRes) => {
                            //                             console.log('用户设置结果:', settingRes);

                            //                             if (settingRes.authSetting['scope.userLocation']) {
                            //                                 // 用户手动授权成功，重新获取城市信息
                            //                                 API._getCityInfo(callback, useReverseGeocoding);
                            //                             } else {
                            //                                 callback(false, null, '用户拒绝授权位置权限');
                            //                                 Utils.setFailCityInfo();
                            //                             }
                            //                         },
                            //                         fail: (err) => {
                            //                             console.log('打开设置失败:', err);
                            //                             callback(false, null, '用户拒绝授权位置权限');
                            //                             Utils.setFailCityInfo();
                            //                         }
                            //                     });
                            //                 }
                            //             }
                            //         });
                            //     }
                            // });
                        }
                    },
                    fail: (err) => {
                        console.log('获取设置失败:', err);
                        callback(false, null, '获取设置失败');
                    }
                });
            } else {
                callback(false, null, '非微信环境');
            }
        }

        /**
         * 内部方法：实际获取城市信息
         */
        private static _getCityInfo(callback: (success: boolean, data?: any, error?: any) => void, useReverseGeocoding: boolean) {
            console.log("获取经纬度坐标");
            //@ts-ignore
            wx.getFuzzyLocation({
                type: 'wgs84', // 使用国测局坐标系，更适合中国地图
                success: (res) => {
                    console.log('111111获取位置成功:', res);
                    if (useReverseGeocoding) {
                        // 使用逆解析获取详细地址信息
                        cc.fx.GameConfig.GM_INFO.longitude = res.latitude.toString() + "," + res.longitude.toString();
                        API._reverseGeocoding(res.latitude, res.longitude, callback);
                    } else {
                        // 直接返回基本位置信息，包含经纬度
                        const cityInfo = "其他";
                        callback(true, cityInfo);
                    }
                },
                fail: (err) => {
                    console.log('获取位置失败:', err);
                    callback(false, null, '用户拒绝授权位置权限');
                    Utils.setFailCityInfo();
                    // 处理错误码102：位置服务不可用
                    if (err.errCode === 102) {
                        // 错误码102的常见原因和解决方案：
                        // 1. 设备定位服务未开启
                        // 2. 网络问题导致定位失败
                        // 3. 权限问题

                        // 提供更友好的错误信息
                        let errorMsg = '位置服务不可用';
                        if (err.errMsg.includes('auth deny')) {
                            errorMsg = '位置权限被拒绝，请检查系统设置';
                        } else if (err.errMsg.includes('network')) {
                            errorMsg = '网络连接失败，请检查网络设置';
                        } else {
                            errorMsg = '定位服务不可用，请检查设备定位功能是否开启';
                        }

                        // 提供用户友好的提示
                        //@ts-ignore
                        wx.showModal({
                            title: '定位失败',
                            content: errorMsg,
                            showCancel: false,
                            confirmText: '知道了'
                        });

                        callback(false, null, errorMsg);
                    } else {
                        callback(false, null, err.errMsg || '获取位置失败');
                    }
                }
            });
        }



        /**
         * 逆解析经纬度获取详细地址信息
         */
        private static _reverseGeocoding(latitude: number, longitude: number, callback: (success: boolean, data?: any, error?: any) => void) {
            //@ts-ignore
            if (typeof wx !== "undefined" && wx.getLocation) {

                let lat = latitude;
                let lng = longitude;
                const province = getProvinceName(lat, lng);

                console.log("玩家省份1：", province);
                let cityInfo = this.getCityChange(province);
                callback(true, cityInfo);
                // TODO: 这里写你的逻辑：埋点、排行榜、活动分组等

            } else {
                // 非微信环境（比如 Cocos 预览），用个测试坐标
                const province = getProvinceName(39.9, 116.4);
                console.log("测试坐标所在省份：", province);
                let cityInfo = this.getCityChange(province);
                callback(true, cityInfo);
            }


            // const key = '6PPBZ-VBEHW-XE3RU-3XNC5-TQH6H-KLBTF'; // 需要替换为实际的key
            // const url = `https://apis.map.qq.com/ws/geocoder/v1/?location=${latitude},${longitude}&key=${key}&get_poi=0`;
            // // 注意：微信小游戏本身不提供逆解析API，需要调用第三方服务或自己的服务器
            // // 这里提供一个示例，实际使用时需要替换为你的服务器接口
            // //@ts-ignore
            // wx.request({
            //     url: url,
            //     method: 'GET',
            //     success: (res) => {
            //         if (res.statusCode === 200 && res.data.status === 0) {
            //             const result = res.data.result;
            //             const cityInfo = {
            //                 latitude: latitude,
            //                 longitude: longitude,
            //                 province: result.address_component.province,    // 省份
            //                 city: result.address_component.city,           // 城市
            //                 district: result.address_component.district,   // 区县
            //                 address: result.address,                       // 详细地址
            //                 formatted_address: result.formatted_addresses?.recommend || result.address // 格式化地址
            //             };
            //             console.log('逆解析成功:', cityInfo);
            //             callback(true, cityInfo);
            //         } else {
            //             console.log('逆解析失败:', res.data);
            //             callback(true, null, '逆解析失败');
            //         }
            //     },
            //     fail: (err) => {
            //         console.log('逆解析请求失败:', err);
            //         callback(true, null, '逆解析请求失败');
            //     }
            // });
        }

        /**
         * 使用微信城市选择器获取城市信息（用户手动选择）
         * @param callback 回调函数
         */
        static chooseWechatCity(callback: (success: boolean, data?: any, error?: any) => void) {
            //@ts-ignore
            if (typeof wx !== 'undefined' && wx !== null) {
                //@ts-ignore
                wx.chooseLocation({
                    success: (res) => {
                        console.log('选择位置成功:', res);
                        const cityInfo = {
                            name: res.name,           // 位置名称
                            address: res.address,     // 详细地址
                            latitude: res.latitude,   // 纬度
                            longitude: res.longitude, // 经度
                            // 从地址中提取城市信息（简单处理）
                            province: API._extractProvinceFromAddress(res.address),
                            city: API._extractCityFromAddress(res.address)
                        };
                        callback(true, cityInfo);
                    },
                    fail: (err) => {
                        console.log('选择位置失败:', err);
                        callback(false, null, err.errMsg || '选择位置失败');
                    }
                });
            } else {
                callback(false, null, '非微信环境');
            }
        }

        /**
         * 从地址字符串中提取省份信息
         */
        private static _extractProvinceFromAddress(address: string): string {
            // 简单的省份提取逻辑，实际使用时可能需要更复杂的处理
            const provinces = ['北京', '天津', '上海', '重庆', '河北', '山西', '辽宁', '吉林', '黑龙江', '江苏', '浙江',
                '安徽', '福建', '江西', '山东', '河南', '湖北', '湖南', '广东', '海南', '四川', '贵州',
                '云南', '陕西', '甘肃', '青海', '台湾', '内蒙古', '广西', '西藏', '宁夏', '新疆', '香港', '澳门'];

            for (const province of provinces) {
                if (address.includes(province)) {
                    return province;
                }
            }
            return '';
        }

        /**
         * 从地址字符串中提取城市信息
         */
        private static _extractCityFromAddress(address: string): string {
            // 简单的城市提取逻辑
            const cities = ['北京', '上海', '天津', '重庆', '石家庄', '太原', '呼和浩特', '沈阳', '长春', '哈尔滨',
                '南京', '杭州', '合肥', '福州', '南昌', '济南', '郑州', '武汉', '长沙', '广州', '南宁',
                '海口', '成都', '贵阳', '昆明', '拉萨', '西安', '兰州', '西宁', '银川', '乌鲁木齐'];

            for (const city of cities) {
                if (address.includes(city)) {
                    return city;
                }
            }
            return '';
        }

        private static getCityChange(city) {
            if (city == "未知") {
                city = "其他";
            }
            else if (city == "北京市" || city == "天津市" || city == "上海市" || city == "重庆市" || city == "广西壮族自治区" || city == "西藏自治区"
                || city == "宁夏回族自治区" || city == "新疆维吾尔自治区"
            ) {
                city = city.substring(0, 2);
            }
            else if (city == "内蒙古自治区") {
                city = "内蒙古";
            }
            else if (city == "台湾省" || city == "香港特别行政区" || city == "澳门特别行政区") {
                city = "港澳台";
            }
            else if (city == "未知或境外") {
                city = "其他";
            }

            if (city.length >= 5) {
                city = "其他";
            }
            return city;
        }

        /**
         * 获取用户IP地址对应的城市信息（不需要位置权限）
         * @param callback 回调函数
         */
        static getCityByIP(callback: (success: boolean, data?: any, error?: any) => void) {
            // 调用IP定位服务获取城市信息
            // 示例：使用第三方IP定位服务
            const url = 'https://restapi.amap.com/v3/ip?key=YOUR_AMAP_KEY'; // 需要替换为实际的高德地图key

            //@ts-ignore
            wx.request({
                url: url,
                method: 'GET',
                success: (res) => {
                    if (res.statusCode === 200 && res.data.status === '1') {
                        const ipInfo = res.data;
                        const cityInfo = {
                            province: ipInfo.province,    // 省份
                            city: ipInfo.city,           // 城市
                            adcode: ipInfo.adcode,        // 区域编码
                            rectangle: ipInfo.rectangle   // 城市范围坐标
                        };
                        console.log('IP定位成功:', cityInfo);
                        callback(true, cityInfo);
                    } else {
                        console.log('IP定位失败:', res.data);
                        callback(false, null, 'IP定位失败');
                    }
                },
                fail: (err) => {
                    console.log('IP定位请求失败:', err);
                    callback(false, null, 'IP定位请求失败');
                }
            });
        }
    }

}