// ==UserScript==
// @name         Tencent MTA
// @namespace    http://tampermonkey.net/
// @version      0.1
// @author       You
// @match        https://mta.qq.com/*
// @require      http://libs.baidu.com/jquery/1.9.0/jquery.js
// @require      https://cdn.bootcss.com/lodash.js/4.17.4/lodash.min.js
// @require      https://unpkg.com/sweetalert@2.1.2/dist/sweetalert.min.js
// @require      https://unpkg.com/mousetrap@1.6.2/mousetrap.js
// @grant        GM_setClipboard
// @run-at       document-start
// ==/UserScript==


function assert(condition, msg) {
    if (!condition) throw new Error(msg);
}

/**
 * @typedef {number} swal
 */

//see https://sweetalert.js.org/docs/#configuration
const timedAlert = (msg, icon) => swal({ title: "Tencent", text: msg, icon: icon, timer: (icon === "success") ? 300 : 1000, closeOnEsc: true, closeOnClickOutside: true, button: false });
const successAlert = msg => timedAlert(msg, "success");
const warningAlert = msg => timedAlert(msg, "warning");
const errorAlert = msg => timedAlert(msg, "error");

async function getJson(url) {
    const res = await fetch(url);
    return await res.json();
}

function rand() {
    return new Date().getTime() + "";
}

function getParameterByName(name, url) {
    name = name.replace(/[\[\]]/g, '\\$&');
    var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
        results = regex.exec(url);
    if (!results) return null;
    if (!results[2]) return '';
    return decodeURIComponent(results[2].replace(/\+/g, ' '));
}

function download(filename, text) {
    var pom = document.createElement('a');
    pom.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
    pom.setAttribute('download', filename);

    if (document.createEvent) {
        var event = document.createEvent('MouseEvents');
        event.initEvent('click', true, true);
        pom.dispatchEvent(event);
    }
    else {
        pom.click();
    }
}

function eventIsEqual(event1, event2) {
    if (!event1 || !event2) {
        return false;
    }

    const { EventId: EventId1, EventName: EventName1, EventType: EventType1, parameters: parameters1 } = event1;
    const { EventId: EventId2, EventName: EventName2, EventType: EventType2, parameters: parameters2 } = event2;

    if (EventId1 !== EventId2) {
        return false;
    }

    if (EventName1 !== EventName2) {
        return false;
    }

    if (EventType1 !== EventType2) {
        return false;
    }

    if (parameters1.length !== parameters2.length) {
        return false;
    }

    const diffParams = parameters1.filter((param1) => {
        for (const param2 of parameters2) {
            if (paramIsEqual(param1, param2)) {
                return false;
            }
        }

        return true;
    });

    if (diffParams.length !== 0) {
        return false;
    }

    return true;
}

function paramIsEqual(param1, param2) {
    const { EventKey: EventKey1, EventKeyName: EventKeyName1 } = param1;
    const { EventKey: EventKey2, EventKeyName: EventKeyName2 } = param2;

    if (EventKey1 !== EventKey2) {
        return false;
    }

    if (EventKeyName1 !== EventKeyName2) {
        return false;
    }

    return true;
}

async function getAppCustomEvents(appId) {
    if (!appId) {
        return null;
    }

    const customEventListUrl = `https://mta.qq.com/mta/api/ctr_event_api/get_table_data/?start_date=&end_date=&need_compare=0&start_compare_date=&end_compare_date=&pageSize=100&app_id=${appId}&tab_id=&rnd=${rand()}&ajax=1`;
    const events = await getJson(customEventListUrl);
    const newEvents = [];
    for (const event of events.data) {
        const { EventId, EventName, EventType } = event;
        // 去除其他标签
        const newEventName = EventName.replace(/&nbsp;.*<\/span>/g, '');
        const customDetailUrl = `https://mta.qq.com/mta/custom/ctr_key_conf/get_table_data/?rnd=${rand()}&pageSize=50&ajax=1&app_id=${appId}&event_id=${EventId}`
        const param = await getJson(customDetailUrl);
        const newParam = param.data.map((value) => {
            const { EventKey, EventKeyName } = value;
            return {
                EventKey,
                EventKeyName,
            };
        });
        newEvents.push({
            EventId,
            EventName: newEventName,
            EventType,
            parameters: newParam,
        });
    }

    return newEvents;
}

async function exportH5() {
    const H5_APPID = "500700486";
    async function exportFunnels() {
        const funnelListUrl = `https://mta.qq.com/h5/visitor/ctr_custom_funnel_config/get_config_data?start_date=&end_date=&need_compare=0&start_compare_date=&end_compare_date=&app_id=${H5_APPID}&rnd=${rand()}&ajax=1`;
        const funnels = await getJson(funnelListUrl);
        const res = {};
        for (const funnel of funnels.data) {
            const url = $(funnel.control).attr("href");
            assert(url, "href is falsy");
            const funnel_id = getParameterByName("funnel_id", url);
            const funnelDetailUrl = `https://mta.qq.com/h5/visitor/ctr_custom_funnel_config/get_event?app_id=${H5_APPID}&funnel_id=${funnel_id}&start_date=&end_date=&need_compare=0&rnd=${rand()}&ajax=1`
            const funnelDetail = await getJson(funnelDetailUrl);
            res[funnel_id] = funnelDetail;
            // const funnelName = funnelDetail.funnel_name;
            // for (const event of funnelDetail.data) {
            //     const { event_id, event_name, event_code } = event;
            // }
        }
        return res;
    }

    async function exportCustomEvents() {
        const customEventListUrl = `https://mta.qq.com/h5/visitor/ctr_button_stat/get_config_data?start_date=&end_date=&need_compare=0&start_compare_date=&end_compare_date=&app_id=${H5_APPID}&rnd=${rand()}&ajax=1`;
        const events = await getJson(customEventListUrl);
        const res = {};
        for (const custom of events.data) {
            const { custom_id, custom_name } = custom;
            const numberId = $(custom.control).data("id");
            assert(numberId, "numberId is falsy");
            const customDetailUrl = `https://mta.qq.com/h5/visitor/ctr_custom_param_config/get_config_data?start_date=&end_date=&need_compare=0&start_compare_date=&end_compare_date=&app_id=${H5_APPID}&custom_id=${numberId}&rnd=${rand()}&ajax=1`
            const customDetail = await getJson(customDetailUrl);
            res[numberId] = {
                custom_id,
                custom_name,
                detail: customDetail,
            }
        }
        return res;
    }
    const funnel = await exportFunnels();
    const custom = await exportCustomEvents();
    download('mta_h5_exports.json', JSON.stringify({ funnel, custom }, null, 4));
}

async function exportApp() {
    const APP_APPID = "3104092528";
    const events = await getAppCustomEvents(APP_APPID);
    const jsonString = JSON.stringify(events, null, 4);
    download('mta_app_exports.json', jsonString);
}

async function diffApp() {
    const ANDROID_APPID = "3104092528";
    const androidEvents = await getAppCustomEvents(ANDROID_APPID);

    const IOS_APPID = "3204092528";
    const iosEvents = await getAppCustomEvents(IOS_APPID);

    // 以android为准，找出iOS中与android中不同的事件
    const diffEvents = iosEvents.filter((iosEvent) => {
        for (const androidEvent of androidEvents) {
            if (eventIsEqual(iosEvent, androidEvent)) {
                return false;
            }
        }

        return true;
    });

    if (diffEvents.length === 0) {
        await swal('iOS和android配置相同', {
            buttons: {
                ok: "好的"
            }
        });
    }
    else {
        const choice = await swal(`iOS和android有${diffEvents.length}处配置不同，是否导出差异配置`, {
            buttons: {
                yes: "导出",
                no: "不导出"
            }
        });

        if (!choice) {
            return;
        }

        if (choice === "yes") {
            const jsonString = JSON.stringify(diffEvents, null, 4);
            download('mta_diff_exports.json', jsonString);
        }
    }
}


$(() => {
    Mousetrap.bind("ctrl+shift+alt+u", async () => {
        'use strict';
        let buttons = {
            h5: "导出H5配置",
            app: "导出App配置",
            diff: "比较App配置",
        }
        const choice = await swal("Export自定义事件和漏斗", {
            buttons: buttons
        });
        if (!choice) return;
        if (choice === "h5") {
            await exportH5();
        } else if (choice === "app") {
            await exportApp();
        } else if (choice === "diff") {
            await diffApp();
        }
    });
});
