import { Crypto, dayjs, jinja2, _ } from './lib/cat.js';

let key = 'kkys';
let url = 'https://api1.baibaipei.com:8899';
let device = {};
let siteKey = '';
let siteType = 0;

async function request(reqUrl, postData, agentSp, get) {
    let ts = dayjs().valueOf().toString();
    let rand = randStr(32);
    let sign = Crypto.MD5('abcdexxxdd2daklmn25129_' + ts + '_' + rand)
        .toString()
        .toLowerCase();
    let headers = {
        'user-agent': agentSp || device.ua,
    };
    if (reqUrl.includes('baibaipei')) {
        headers['device-id'] = device.id;
        headers['push-token'] = '';
        headers['sign'] = sign;
        headers['time'] = ts;
        headers['md5'] = rand;
        headers['version'] = '2.1.0';
        headers['system-model'] = device.model;
        headers['system-brand'] = device.brand;
        headers['system-version'] = device.release;
    }
    let res = await req(reqUrl, {
        method: get ? 'get' : 'post',
        headers: headers,
        data: postData || {},
        postType: get ? '' : 'form',
    });

    let content = res.content;
    // console.log(content);
    return content;
}

async function init(cfg) {
    siteKey = cfg.skey;
    siteType = cfg.stype;
    var deviceKey = 'device';
    var deviceInfo = await local.get(key, deviceKey);
    if (deviceInfo.length > 0) {
        try {
            device = JSON.parse(deviceInfo);
        } catch (error) {}
    }
    if (_.isEmpty(device)) {
        device = randDevice();
        device.id = randStr(33).toLowerCase();
        device.ua = 'okhttp/4.1.0';
        await local.set(key, deviceKey, JSON.stringify(device));
    }
}

async function home(filter) {
    // await req('https://www.facebook.com', {});
    let data = JSON.parse(await request(url + '/api.php/Index/getTopVideoCategory')).data;
    let classes = [];
    let filterObj = {};
    for (const type of data) {
        let typeName = type.nav_name;
        if (typeName == '推荐') continue;
        let typeId = type.nav_type_id.toString();
        classes.push({
            type_id: typeId,
            type_name: typeName,
        });
        if (!filter) continue;
        try {
            let filterAll = [];
            let filterData = JSON.parse(await request(url + '/api.php/Video/getFilterType', { type: typeId })).data;
            for (let key of Object.keys(filterData)) {
                let itemValues = filterData[key];
                if (key === 'plot') key = 'class';
                let typeExtendName = '';
                switch (key) {
                    case 'class':
                        typeExtendName = '类型';
                        break;
                    case 'area':
                        typeExtendName = '地区';
                        break;
                    case 'lang':
                        typeExtendName = '语言';
                        break;
                    case 'year':
                        typeExtendName = '年代';
                        break;
                    case 'sort':
                        typeExtendName = '排序';
                        break;
                }
                if (typeExtendName.length === 0) continue;
                let newTypeExtend = {
                    key: key,
                    name: typeExtendName,
                };
                let newTypeExtendKV = [];
                for (let j = 0; j < itemValues.length; j++) {
                    const name = itemValues[j];
                    let value = key === 'sort' ? j + '' : name === '全部' ? '0' : name;
                    newTypeExtendKV.push({ n: name, v: value });
                }
                newTypeExtend['init'] = key === 'sort' ? '1' : newTypeExtendKV[0]['v'];
                newTypeExtend.value = newTypeExtendKV;
                filterAll.push(newTypeExtend);
            }
            if (!_.isEmpty(filterAll)) {
                filterObj[typeId] = filterAll;
            }
        } catch (e) {
            console.log(e);
        }
    }
    // console.log(await homeVod());
    // console.log(classes);
    // console.log(filterObj);
    return JSON.stringify({
        class: classes,
        filters: filterObj,
    });
}

async function homeVod() {
    let jsonArray = JSON.parse(await request(url + '/api.php/Index/getHomePage', { type: 1, p: 1 })).data.video;
    let videos = [];
    for (const item of jsonArray) {
        if (item.title.styleType !== 0) continue;
        for (const vObj of item.list) {
            videos.push({
                vod_id: vObj.vod_id,
                vod_name: vObj.vod_name,
                vod_pic: vObj.vod_pic,
                vod_remarks: vObj.vod_remarks || vObj.vod_score || '',
            });
        }
    }
    return JSON.stringify({
        list: videos,
    });
}

async function category(tid, pg, filter, extend) {
    if (pg == 0) pg = 1;
    let reqUrl = url + '/api.php/Video/getFilterVideoList';
    var formData = JSON.parse(
        jinja2(
            `{
        "type": "{{tid}}",
        "p": "{{pg}}",
        "area": "{{ext.area|default(0)}}",
        "year": "{{ext.year|default(0)}}",
        "sort": "{{ext.sort|default(0)}}",
        "class": "{{ext.class|default(0)}}"
    }`,
            { ext: extend, tid: tid, pg: pg }
        )
    );
    console.log(formData);
    let data = JSON.parse(await request(reqUrl, formData)).data;
    let videos = [];
    for (const vod of data.data) {
        videos.push({
            vod_id: vod.vod_id,
            vod_name: vod.vod_name,
            vod_pic: vod.vod_pic,
            vod_remarks: vod.vod_remarks || vod.vod_score || '',
        });
    }
    return JSON.stringify({
        page: parseInt(data.current_page),
        pagecount: parseInt(data.last_page),
        limit: parseInt(data.per_page),
        total: parseInt(data.total),
        list: videos,
    });
}

async function detail(id) {
    let data = JSON.parse(await request(url + '/api.php/Video/getVideoInfo', { video_id: id })).data.video;
    let vod = {
        vod_id: data.vod_id,
        vod_name: data.vod_name,
        vod_pic: data.vod_pic,
        type_name: data.vod_class,
        vod_year: data.vod_year,
        vod_area: data.vod_area,
        vod_remarks: data.vod_remarks || '',
        vod_actor: data.vod_actor,
        vod_director: data.vod_director,
        vod_content: data.vod_content.trim(),
    };
    let playlist = {};
    for (const item of data.vod_play) {
        let from = item.playerForm;
        if (from === 'jp') continue;
        if (from === 'xg') continue;
        let urls = [];
        for (const u of item.url) {
            urls.push(formatPlayUrl(vod.vod_name, u.title) + '$' + u.play_url);
        }
        if (!playlist.hasOwnProperty(from) && urls.length > 0) {
            playlist[from] = urls;
        }
    }
    parse = data.parse || [];
    vod.vod_play_from = _.keys(playlist).join('$$$');
    let urls = _.values(playlist);
    let vod_play_url = [];
    for (const urlist of urls) {
        vod_play_url.push(urlist.join('#'));
    }
    vod.vod_play_url = vod_play_url.join('$$$');
    return JSON.stringify({
        list: [vod],
    });
}

var parse = [];

async function play(flag, id, flags) {
    try {
        if (id.indexOf('youku') >= 0 || id.indexOf('iqiyi') >= 0 || id.indexOf('v.qq.com') >= 0 || id.indexOf('pptv') >= 0 || id.indexOf('le.com') >= 0 || id.indexOf('1905.com') >= 0 || id.indexOf('mgtv') >= 0) {
            if (parse.length > 0) {
                for (let index = 0; index < parse.length; index++) {
                    try {
                        const p = parse[index];
                        let res = await req(p + id, {
                            headers: { 'user-agent': 'okhttp/4.1.0' },
                        });
                        var result = jsonParse(id, JSON.parse(res.content));
                        if (result.url) {
                            result.parse = 0;
                            return JSON.stringify(result);
                        }
                    } catch (error) {}
                }
            }
        }
        if (id.indexOf('jqq-') >= 0) {
            var jqqHeader = await request(url + '/jqqheader.json', null, null, true);
            var jqqHeaders = JSON.parse(jqqHeader);
            var ids = id.split('-');
            var jxJqq = await req('https://api.juquanquanapp.com/app/drama/detail?dramaId=' + ids[1] + '&episodeSid=' + ids[2] + '&quality=LD', { headers: jqqHeaders });
            var jqqInfo = JSON.parse(jxJqq.content);
            if (jqqInfo.data.playInfo.url) {
                return JSON.stringify({
                    parse: 0,
                    playUrl: '',
                    url: jqqInfo.data.playInfo.url,
                });
            }
        }
        let res = await request(url + '/video.php', { url: id });
        var result = jsonParse(id, JSON.parse(res).data);
        if (result.url) {
            result.parse = 0;
            // demo of block hls ads
            if (/vip\.lz|hd\.lz/.test(result.url)) {
                result.url = await js2Proxy(true, siteType, siteKey, 'lzm3u8/' + base64Encode(result.url), {});
            }
            return JSON.stringify(result);
        }
        return JSON.stringify({
            parse: 0,
            playUrl: '',
            url: id,
        });
    } catch (e) {
        console.log(e);
        return JSON.stringify({
            parse: 0,
            url: id,
        });
    }
}

async function proxy(segments, headers) {
    let what = segments[0];
    let url = base64Decode(segments[1]);
    if (what == 'lzm3u8') {
        const resp = await req(url, {});
        let hls = resp.content;
        const jsBase = await js2Proxy(false, siteType, siteKey, 'lzm3u8/', {});
        const baseUrl = url.substr(0, url.lastIndexOf('/') + 1);
        console.log(hls.length);
        hls = hls.replace(/#EXT-X-DISCONTINUITY\r*\n*#EXTINF:6.433333,[\s\S]*?#EXT-X-DISCONTINUITY/, '');
        console.log(hls.length);
        hls = hls.replace(/(#EXT-X-KEY\S+URI=")(\S+)("\S+)/g, function (match, p1, p2, p3) {
            let up = (!p2.startsWith('http') ? baseUrl : '') + p2;
            return p1 + up + p3;
        });
        hls = hls.replace(/(#EXT-X-STREAM-INF:.*\n)(.*)/g, function (match, p1, p2) {
            let up = (!p2.startsWith('http') ? baseUrl : '') + p2;
            return p1 + jsBase + base64Encode(up);
        });
        hls = hls.replace(/(#EXTINF:.*\n)(.*)/g, function (match, p1, p2) {
            let up = (!p2.startsWith('http') ? baseUrl : '') + p2;
            return p1 + up;
        });
        return JSON.stringify({
            code: resp.code,
            content: hls,
            headers: resp.headers,
        });
    }
    return JSON.stringify({
        code: 500,
        content: '',
    });
}

async function search(wd, quick) {
    let data = JSON.parse(await request(url + '/api.php/Search/getSearch', { key: wd, type_id: 0, p: 1 })).data;
    let videos = [];
    for (const vod of data.data) {
        videos.push({
            vod_id: vod.vod_id,
            vod_name: vod.vod_name,
            vod_pic: vod.vod_pic,
            vod_remarks: vod.vod_remarks || vod.vod_score || '',
        });
    }
    return JSON.stringify({
        list: videos,
    });
}

function base64Encode(text) {
    return Crypto.enc.Base64.stringify(Crypto.enc.Utf8.parse(text));
}

function base64Decode(text) {
    return Crypto.enc.Utf8.stringify(Crypto.enc.Base64.parse(text));
}

const charStr = 'abacdefghjklmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789';
function randStr(len, withNum) {
    var _str = '';
    let containsNum = withNum === undefined ? true : withNum;
    for (var i = 0; i < len; i++) {
        let idx = _.random(0, containsNum ? charStr.length - 1 : charStr.length - 11);
        _str += charStr[idx];
    }
    return _str;
}

function randDevice() {
    return {
        brand: 'Huawei',
        model: 'HUAWEI Mate 20',
        release: '10',
        buildId: randStr(3, false).toUpperCase() + _.random(11, 99) + randStr(1, false).toUpperCase(),
    };
}

function formatPlayUrl(src, name) {
    return name
        .trim()
        .replaceAll(src, '')
        .replace(/<|>|《|》/g, '')
        .replace(/\$|#/g, ' ')
        .trim();
}

function jsonParse(input, json) {
    try {
        let url = json.url ?? '';
        if (url.startsWith('//')) {
            url = 'https:' + url;
        }
        if (!url.startsWith('http')) {
            return {};
        }
        let headers = json['headers'] || {};
        let ua = (json['user-agent'] || '').trim();
        if (ua.length > 0) {
            headers['User-Agent'] = ua;
        }
        let referer = (json['referer'] || '').trim();
        if (referer.length > 0) {
            headers['Referer'] = referer;
        }
        _.keys(headers).forEach((hk) => {
            if (!headers[hk]) delete headers[hk];
        });
        return {
            header: headers,
            url: url,
        };
    } catch (error) {
        console.log(error);
    }
    return {};
}

export function __jsEvalReturn() {
    return {
        init: init,
        home: home,
        homeVod: homeVod,
        category: category,
        detail: detail,
        play: play,
        proxy: proxy,
        search: search,
    };
}