import {jsonp} from "./web/jsonp";
import {getUrlParams} from "./web/webTools";
import {showToast} from "../../../Module/UIFast";
import {PREVIEW} from 'cc/env';

// import { isFromShare, newUser } from 'duiba-utils';

// let mergeData = {
//     user_type: newUser ? '0' : '1',
//     is_from_share: isFromShare ? '0' : '1',
// }
export const DEFAULF_ERROR = '网络异常，请稍后重试';

//////////////星速台接口方法集成
/**
 * web接口枚举
 */
export enum WebNetName {

    getFrontVariable = 'coop_frontVariable.query',
    buriedPoint = 'buriedPoint',


    index = "home/index.do",

    startGame = "game/startGame.do",
    submitOne = "game/submitOne.do",
    submitTwo = "game/submitTwo.do",
    finalSubmit = "game/finalSubmit.do",
    queryReviveData = "game/queryReviveData.do",
    reviveGame = "game/reviveGame.do",

    /**
     * 获取QrCode
     */
    genQrCode = "/customActivity/lshm/generateSunCode",

    /**
     * 排行榜
     */
    // 省份榜
    shengRank = "rank/provinceRank.do",
    // 个人榜
    singleRank = "rank/personRank.do",
    // 好友榜
    friendRank = "rank/friendRank.do",

    /**
     * 我的背包
     */
    // 我的背包-查询游戏道具明细
    queryGameItem = "myBackpack/getSp.do",
    // 我的背包-装扮接口
    doDress = "myBackpack/exchangeDecoration.do",
    /**
    * 奖品页面
    */
    prizeDetail = "records.query",

    /**
     * 签到
     */
     /** 签到信息接口 */
    querySignInfo = "checkin_1/query.do",
    /** 查询签到奖品 */
    querySignPrize = "checkin_1/queryOptions.do",
    /** 签到 */
    doSign = 'checkin_1/doSign.do',

    /**
     * 积分明细
     */
    queryCredits = "home/queryCredits.do",

    /**
     * 获取规则
     */
    projectRule = "projectRule.query",

    /**
     * 预扣积分
     */
    creditsCost = "credits/creditsCost.do",
    /**
     * 检查扣积分状态
     */
    queryStatus = "credits/queryStatus.do",
    /**
     * 邀请助力
     */
    getInviteCode = "inviteAssist_1/getInviteCode.do",
    doAssist = "inviteAssist_1/doAssist.do",

    /**
     * 完成行方浏览任务
     */
    finishBrowseTask = "task_1/finishBrowseTask.do",

    /**
     * 领取行方浏览任务
     */
    claimThirdTask = "task_1/claimThirdTask.do",

    /**
     * 我的奖品
     */
    records = "records.query",

    /**
     * 福袋首页
     */
    bagPag = "bag/index.do",

    /**
     * 福袋_抽奖
     */
    bagExchange = "bag/draw.do",

    /**
     * 道具首页
     */
    propPag = "exchang_1/listExchangeLimit.do",

    /**
     * 道具_兑换
     */
    propExchange = "exchang_1/doExchange.do",

    /**
     * 任务列表
     */
    taskList = "task_1/queryTasks.do",

    /**
     * 完成任务
     */
    finishTask = "task_1/doCompleted.do",
}

export const ERR_MESSAGE = {
    "100001": "登录过期啦，请重新登录哦～",
    "5001033": "该局使用该道具次数已达上限",
    "200303": "助力失败，您的助力次数已用完",
    "200306": "助力失败，不能给自己助力哦~",
    "200304": "助力失败，好友被助力次数已达上限~",
    "5001041": "网络异常，请稍后再试",
    // "300001": "您的积分不足\n快去获取积分参与游戏吧～",
    // "400001": "系统维护中，请稍后尝试",
    // "400004": "您的积分不足\n快去获取积分参与游戏吧～",
    // "300003": "今日复活次数已经达到上限\n明天再来吧！",
}


//返回数据类型
interface dataOut {
    success: boolean,
    data?: any
    code?: string | number,
    message?: string,
    timeStamp?: number,
}

//记录数据
let dataRecord: {
    [name: string]: any
} = {};


interface IWebConfig {
    token?: string;
    callback?: (success: boolean, res?: dataOut) => void,
    hideMsg?: boolean,
    isGet?: boolean,//这两个参数基本不设置，放后面吧
    headers?: any,
}

/**
 * 发送接口
 * @param netName
 * @param parameter
 * @param config
 */
export function sendWebNet(
    netName: WebNetName | string,
    parameter: any = {},
    config: IWebConfig = {}
): Promise<dataOut> {

    let {
        callback,
        hideMsg = false,
        isGet = true,//这两个参数基本不设置，放后面吧
        headers = {},
    } = config;

    // 统一加上渠道参数
    // const channel = getUrlParams("channel");
    // parameter.channel = channel;

    return new Promise(async (resolve, reject) => {

        const success = (res) => {
            //发现有些接口成功了，但是response为空
            res = res || {}
            //记录数据
            dataRecord[netName] = res;
            //统一错误信息提示，

            res.success = res.success || res.ok;

            if (!res.success) {
                if (!hideMsg) {
                    showToast(ERR_MESSAGE[res.code] || res.message || "网络异常，请稍后再试～");
                }
            }

            callback && callback(res.success, res);
            resolve(res);
            console.log(
                `\n%c[ request ]\n`
                + `NAME  : ${netName} \n`
                + `STATE : %o \n`
                + `TIME  : %o \n`
                + `PARAM : %o \n`
                + `%cDATA  : %o \n`
                , `${res.success ? 'color:green' : 'color:red'}`
                , res.success
                , res.timeStamp || res.timestamp
                , parameter
                , `${res.success ? 'color:green' : 'color:red'}`
                , res
            );
        }

        const fail = () => {
            if (!hideMsg) showToast("网络异常，请稍后再试～");
            callback && callback(false);
            resolve({success: false});
            console.log("接口" + netName + "：网络超时");
            return {success: false};
        }

        let url = netName;

        if (PREVIEW) {
            // let path = netName.split('/')[1];//后缀名字之前的是文件夹,mock里结构
            // if (netName.indexOf('/') <= -1) path = `projectX/${netName}`;
            // else path = netName
            // const url = "mock/" + path + ".json";
            isGet = true;   // post请求不到mock文件
            url = "mock/" + netName + ".json";
        }

        let data = parameter || {};
        if (data.token) {
            url += "?token=" + data.token;
            delete data.token;
        }

        if (!isGet) {
            data = JSON.stringify(data);
            headers['content-type'] = "application/json;";
        }

        //网络请求
        $.ajax({
            url, //请求地址
            type: isGet ? 'GET' : "POST",   //请求方式
            data: data, //请求参数
            dataType: "json",     // 返回值类型的设定,暂时只有json
            async: true,   //是否异步
            headers: headers,
            success: success,
            error: fail,
        })
    })
}

export function sendWebNetWithToken(
    netName: WebNetName,
    parameter?: any,
    config?: IWebConfig,
): Promise<dataOut> {
    return new Promise(async r => {
        try {
            const token = await getPxTokenSave();
            if (!token) {
                showToast('网络异常，请稍后重试');
                r({success: false})
                return;
            }
            const res = await sendWebNet(
                netName,
                {token, ...parameter},
                config,
            );
            r(res);
        } catch (e) {
            showToast('网络异常，请稍后重试');
            r({success: false});
        }
    });
}

/**
 * 获取数据
 * @param netName
 */
export function getWebData(netName: WebNetName): dataOut {
    return dataRecord[netName] || {};
}

//销毁数据
export function destroyWebNetData() {
    dataRecord = {}
}


async function fetchAsync(url: string): Promise<any> {
    const res = await fetch(url);
    return await res.json();
}

const projectxString = "projectx/";
let projectId: string;

/**
 * 获取链接上的projectId
 */
export function getProjectId(): string {
    if (projectId) return projectId;

    let windowUrl = window.location.href;
    let splitArr = windowUrl.split(projectxString);
    if (splitArr.length != 2) {
        return projectId = "projectId"
    }
    let start = windowUrl.indexOf(projectxString) + projectxString.length;
    let end = splitArr[1].indexOf("/");
    return projectId = windowUrl.substr(start, end);
}

//这个临时，如星速台链接有变，注意
const isProd = location.href.indexOf(".com.cn/projectx") >= 0;

/**
 * 刷新星速台tokenkey,注意多活动跳转手动执行一边
 * @param callback
 */
export function refreshPxTokenKey(callback?: (success: boolean) => void) {
    if (isProd) {//线上
        const head = document.getElementsByTagName("head")[0];
        const scriptEl = document.createElement('script');
        scriptEl.src = "getTokenKey?_=" + Date.now();
        scriptEl.onload = function () {
            head.removeChild(scriptEl);
            callback && callback(true)
        };
        scriptEl.onerror = function () {
            head.removeChild(scriptEl);
            callback && callback(false)
        };
        head.appendChild(scriptEl);
    } else {//本地环境
        callback && callback(true)
    }
}

//执行一次
refreshPxTokenKey();

/**
 * 带重刷tokenkey功能的获取token，返回token字符串或null
 * @returns
 */
export function getPxTokenSave() {
    return new Promise<string>((reslove, reject) => {
        getPxToken(async (msg, token) => {
            if (token) {
                reslove(token);
                return
            }
            //只重试一次，刷新tokenKey
            const suc = await new Promise((r) => {
                refreshPxTokenKey(r);
            });
            //刷新失败，返回空
            if (!suc) {
                reslove(null);
                return;
            }
            //再次获取
            getPxToken((msg, token) => {
                reslove(token)
            })
        })
    })
}

/**
 * 获取星速台token
 * @param callback
 */
export function getPxToken(callback: (msg: string, token?: string) => void) {
    if (!isProd) {//本地环境
        callback(null, "token")
        return
    }
    if (!window["ohjaiohdf"]) {
        callback("need reload")
        return
    }
    var xml = new XMLHttpRequest;
    xml.open("get", "getToken?_t=" + Date.now(), true);
    xml.onreadystatechange = function () {
        if (xml.readyState === 4 && xml.status === 200) {
            var e = JSON.parse(xml.response);
            if (e.success) {
                window.eval(e.data);
                callback(null, window["ohjaiohdf"]());
            } else {
                var msg = (() => {
                    switch (e.code) {
                        case "100001":
                            return "need login"
                        case "100024":
                            return "state invalid"
                        default:
                            return e.code
                    }
                })();
                callback(msg);
            }
        }
    }
    xml.onerror = function () {
        callback("net error")
    };
    xml.onloadend = function () {
        xml.status === 404 && callback("net error")
    };
    xml.send()
}

export enum LOG_TYPE {
    EXPOSURE = 'exposure',
    CLICK = 'click',
}

/**
 * 埋点  sendLog(LOG_TYPE.EXPOSURE,"4")
 * 注意点击埋点前必有曝光埋点
 * @param type
 * @param data
 */
export function sendLog(type: LOG_TYPE | 'exposure' | 'click', area: number, dpm_d: number = 1, dcm_c: number | string = 0, dcm_d: number | string = 0) {
    const projectID = getProjectId();
    const appID = getUrlParams("appID");
    //给个提示
    if (!appID) console.error("appID不存在，检查链接")
    const dpm = `${appID || 'appID'}.110.${area}.${dpm_d}`;// TODO appID注意默认写死一个，已防链接没有
    const dcm = `202.${projectID || 'projectID'}.${dcm_c}.0`;
    //看需求
    // var dom = `${isWxClient() ? '2' : '1'}.0.0.0`;
    let params: any = {
        dpm,
        dcm,
        appId: appID
    };
    //看需求
    // if (dom) params.dom = dom;
    let isExposure = (type == LOG_TYPE.EXPOSURE);
    if (isExposure) {
        //曝光
        jsonp('//embedlog.duiba.com.cn/exposure/standard', params);
    } else {
        //点击
        jsonp('/log/click', params);
    }
    // console.log('try log', {type, ...params});
}

export const sendLogList = (type: LOG_TYPE | 'exposure' | 'click', areaList: (number | {
    area: number,
    dpm_d: number,
    dcm_c: number
})[]) => {
    areaList.forEach(v => {
        if (typeof v === "object") {
            sendLog(type, v.area, v.dpm_d, v?.dcm_c || 0)
        } else {
            sendLog(type, v);
        }
    })
}


/**
 * 扣积分流程，带轮询
 * @param toPlaywayId
 * @param toActionId
 * @param desc
 * @param credits
 * @return {Promise<{ success: boolean, ticket?: any,pollingData }>}
 */
export async function creditsCost(toPlaywayId, toActionId, desc, credits = "") {
    // 预扣积分
    const param = {
        toPlaywayId,
        toActionId,
        credits,
    };
    //@ts-ignore
    desc && (param.desc = desc);
    const {success, data: ticket} = await sendWebNet(WebNetName.creditsCost, param);

    if (!success) return {success: false};

    // 轮询
    const pollingData = await pollingWebNet(
        {ticketNum: ticket},
        (success, res) => {
            return res?.data != 0; // 0 是处理中
        }
    );

    return {success: pollingData.data == 1, ticket, pollingData};
}

/**
 * 封装一个轮询
 * @param param
 * @param {(success: boolean, res?: dataOut) => boolean} progress 这个函数必须返回一个bool值 用于是否结束轮询的标志 true则会结束轮询
 * @param { (res) => void} complete
 * @param {number} count
 * @param {number} timeOut
 * @return {Promise<{success: boolean, data: any}>}
 */
export async function pollingWebNet(param, progress, complete?, count = 10, timeOut = 200) {
    return new Promise<dataOut>(async (resolve, reject) => {
        // Loading.show();
        let _count = 0;

        async function pollingOnce() {
            const res = await sendWebNet(WebNetName.queryStatus, param)

            // 如果是true则结束轮询
            if (progress(res.success, res)) {
                // Loading.hide();
                resolve(res);
                complete && complete(res);
                return;
            }

            _count++;

            // 到达次数上限结束轮询
            if (_count >= count) {
                // Loading.hide();
                resolve(res);
                complete && complete(res);
                return;
            }

            setTimeout(() => {
                pollingOnce();
            }, timeOut);
        }

        await pollingOnce();
    });
}
