import log4js from 'log4js'
import qs from 'qs'
import {bl, genPc, genUuid, ht, ie, Ol, randint, se} from "./utils.js"
import axios from "axios";
import {encodePayload} from './encodepayload.js'
import {PxEnv} from './px.js'
// import {getPayload} from "./all.js";
import * as fs from "fs";
const plt = process.platform;

process.env.TZ = 'Asia/Shanghai';

log4js.configure({
    appenders: {
        out: {
            type: 'stdout', layout: {
                colored: true,
                type: 'pattern',
                pattern: '%[%d{yyyy-MM-dd hh:mm:ss.SSS}] [%l:%C:%M] [%p] %c - %m',
            }
        },
    },
    categories: {
        default: {appenders: ['out'], level: "trace", enableCallStack: true}
    }

});

class PxBypass {
    tag = "v8.9.6"
    ft = "330"
    appId = "PXVb73hTEg"
    ua = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
    // ua = "Mozilla/5.0 (Linux; Android 10; SM-G981B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.162 Mobile Safari/537.36";
    ua = 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.4 Mobile/15E148 Safari/604.1'
    pxUrl = `https://collector-${this.appId}.px-cloud.net/assets/js/bundle`
    tlsUrl = 'http://52.52.23.116/tls/forward'

    prox = `http://user-uni001-region-us-sessid-${randint(1000, 5000)}-sesstime-5-keep-true:q39CEBTs5A5YQXor@pr.roxlabs.cn:4600`
    // prox = `http://unfflcc:76cc14-47b8dd-1f8ace-827836-0c740e@usa.rotating.proxyrack.net:${randint(10000, 13500)}`

    prox = 'http://127.0.0.1:8890'
    // prox = 'http://192.168.101.145:1082'
    tlsUrl = 'http://127.0.0.1:58000/tls/forward'

    // tlsUrl = 'http://127.0.0.1:3000/tls/forward'

    constructor(options) {
        // if (os.platform() === 'linux') {
        //     this.tlsUrl = 'http://192.168.50.235:58000/tls/forward'
        //     this.tlsUrl = 'http://192.168.101.34:58000/tls/forward'
        // }
        this.log = log4js.getLogger('px')

        let env = fs.readFileSync('./env.json', 'utf-8')
        env = JSON.parse(env);
        let keys = Object.keys(env)
        let selectId = keys[randint(0, keys.length - 1)]
        this.log.info('select env', selectId)
        this.env = env[selectId]
        // this.ua = this.env.navigatorparams.useragent


        this.log.info('ua', this.ua)
        this.log.info(`proxy ${this.prox}`)

        this.pxHeaders = {
            "authority": "collector-pxvb73hteg.px-cloud.net",
            "accept": "*/*",
            "accept-language": "en",
            "cache-control": "no-cache",
            "content-type": "application/x-www-form-urlencoded",
            "origin": "https://booking.flyfrontier.com",
            "pragma": "no-cache",
            "referer": "https://booking.flyfrontier.com/",
            "user-agent": this.ua
        }


        this.url = 'https://booking.flyfrontier.com/Flight/InternalSelect?o1=DEN&d1=LAS&dd1=2023-12-30&ADT=1&umnr=false&mon=true';

        this.log.level = 'debug'
        this.uuid = '';
        this.ts = '';
        this.cs = ''
        // # PX15454 o111oooo
        this.num1 = 0
        // # PX11701 111o1o
        this.num2 = ''
        // # PX11701 111o1o
        this.str1 = ''
        this.vid = ''
        this.sid = ''
        this.cts = ''

        this.seq = 0
        this.rsc = 1;
        this.cookies = {}


    }

    async sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    async add_headers() {
        let cks = Object.keys(this.cookies).map((v, k) => `${v}=${this.cookies[v]}`).join('; ')

        let headers = {
            "authority": "booking.flyfrontier.com",
            "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
            "accept-language": "en-US,en;q=0.9",
            "user-agent": this.ua,
            "cookie": cks
        }
        let res = await axios.post('http://ymx-lcc.unififi.com/header/add', JSON.stringify({
            'brush_fromto': 'LAS-BOS',
            'brush_fromdate': '2023-05-26',
            'brush_header': headers,
            'brush_proxy': this.prox,
            'brush_mode': 'shopping',
            'brush_name': 'js0',
            'brush_type': 'cookieF9',
        }));
        this.log.debug(res.data)

    }

    async do_collector(data) {
        let vh = null;
        for (var m = "PX11745", M = 0; M < data["length"]; M++) {
            var g = data[M];
            g["d"]["PX11379"] = false;
            // if (cap){
            m && (g["d"]["PX12307"] = m);
            // g["d"]["PX12615"] = Bu;
            vh && (g["d"]["PX11375"] = vh);
            g["d"]["PX11668"] = 'pxhc'
            g["d"]["PX12348"] = false;
            // }

        }
        data[0] && data[0]["d"] && ((data[0] && data[0]["d"])["PX11645"] = this.url);
        try {
            // if (typeof data === 'object') {
            //     data = ht(data)
            // }
            // this.log.info(data)
            // let payload = encodePayload(data, this.uuid, this.ts)
            // let pc = genPc(data, `${this.uuid}:${this.tag}:${this.ft}`)
            // let body = {
            //     "appId": this.appId,
            //     "tag": this.tag,
            //     "uuid": this.uuid,
            //     "ft": this.ft,
            //     "seq": this.seq,
            //     "en": "NTA",
            //     "pc": pc,
            //     "rsc": this.rsc,
            //     "payload": payload,
            // }
            // body = this.updateBody(body);


            let body = this.getPayload(data)
            // this.log.info(body)
            body.push(`seq=${this.seq}`)
            body.push(`rsc=${this.rsc}`)

            let res = await axios.post(this.tlsUrl, JSON.stringify({
                url: this.pxUrl,
                method: "POST",
                // data: qs.stringify(body),
                data: body.join('&'),
                headers: this.pxHeaders,
                allow_redirects: true,
                debug: true,
                proxy: this.prox,
                id: (new Date().getTime()) + '',
                random_tls: true,
            }));
            let inRes = JSON.parse(res.data.text)
            // this.log.info(inRes)
            this.parseRes(inRes)
        } catch (err) {
            console.error(err);
        }

        this.seq++;
        this.rsc++;

    };

    getPayload(data) {

        let vh = null;
        // console.log('now', le(), JSON.stringify(t))

        // console.log('now', JSON.stringify(data))
        // var A = $u();
        let uuid = this.uuid
        var pc = se(ht(data), function (t, e) {
            return [uuid, t, e]['join'](":");
        }(this.tag, this.ft));
        var b = {
            "vid": this.vid,
            "tag": this.tag,
            "appID": this.appId,
            "cu": this.uuid,
            "cs": this.cs,
            "pc": pc
        };
        var w = bl(data, b, this.ts);
        // console.log("ts", fl())
        // console.log('res', w)
        var E = ["payload=" + w, "appId=" + this.appId, "tag=" + this.tag, "uuid=" + this.uuid, "ft=" + this.ft, "en=" + "NTA"];
        var T = null;
        T && E["push"]('xuuid=' + T);
        this.cs && E["push"]('cs=' + this.cs);
        pc && E["push"]('pc=' + pc);
        var O = this.sid;
        var U = Ol(this.ts);
        (O || U) && E["push"]('sid=' + (O || this.sid) + U);
        var I = [];
        this.vid && E["push"]('vid=' + this.vid);
        // mu && E["push"]('jcs=' + mu);
        var S = this.ci;
        S && E["push"]('ci=' + S);
        // Ru || (Ru = Df(cu));
        var C = this.pxhd;
        C && E["push"]('pxhd=' + C);
        let Qf = this.cts;
        Qf && E["push"]('cts=' + Qf);
        I["length"] >= 0 && E["push"]["apply"](E, I);
        return E;
    }


    updateBody(body) {
        if (this.vid !== "") {
            body.vid = this.vid
        }
        if (this.cs !== "") {
            body.cs = this.cs
        }
        if (this.cts !== "") {
            body.cts = this.cts
        }
        if (this.sid !== "") {
            body.sid = this.sid
        }
        if (this.ci && this.ci !== '') {
            body.ci = this.ci
        }
        if (this.pxhd && this.pxhd !== '') {
            body.pxhd = this.pxhd
        }
        return body
    }

    parseRes(inRes) {
        let result = void 0;
        if (inRes['ob']) {
            let cks = ie(atob(inRes.ob), this.version()).split('~~~~')
            if (plt === 'darwin') this.log.info(cks.length, JSON.stringify(cks, null, '\t'))
            for (var ck of cks) {
                let tmp = ck.split('|');

                // if (tmp[0] === 'o11o1ooo') {
                //     this.log.fatal('result', tmp[1] === '0')
                //     result = tmp[1] === '0'
                // }
                if (tmp[0] === 'o11o11o1') {
                    this.ts = tmp[1]

                }
                if (tmp[0] === '1oo11o') {
                    this.ci = tmp[2]
                    this.token = tmp[4].split('_')[0]
                    this.token2 = tmp[4].split('_')[1]
                }
                if (tmp[0] === 'ooo111') {
                    this.hash = tmp[2]
                    this.hash2 = tmp[3]
                    this.hashv = tmp[4]
                }

                if (tmp[0] === 'o11o11oo') {
                    this.num1 = tmp[1]

                }
                if (tmp[0] === '1o111o') {
                    this.num2 = tmp[1]
                }

                if (tmp[0] === '11o1o1') {
                    this.str1 = tmp[1]

                }
                if (tmp[0] === 'ooo11o') {
                    this.vid = tmp[1]
                    this.cookies['_pxvid'] = this.vid
                }


                if (tmp[0] === 'oo1111') {
                    this.sid = tmp[1]
                }

                if (tmp[0] === '1ooo11') {
                    this.cs = tmp[1]
                }

                if (tmp[0] === 'o11o1ooo') {
                    this.cts = tmp[1]
                    this.cookies['pxcts'] = this.cts
                }


                if (tmp.includes('zpxde')) {
                    this.cookies['pxde'] = tmp[3]
                }
                if (tmp.includes('_px2')) {
                    this.cookies['_px2'] = tmp[3]
                    this.log.debug(`px2_decode ${atob(this.cookies['_px2'])}`)
                    let parsePx2 = JSON.parse(atob(this.cookies['_px2']))
                    // if (!parsePx2.t.toString().startsWith('6202')) {
                    //     this.flag = true
                    //     this.awaitTime = parsePx2.t - Date.now()
                    // } else {
                    //     this.flag = false;
                    // }
                }
                if (tmp[1] === 'score') {
                    if (tmp[2] === '0') {
                        this.flag = true
                    } else {
                        this.flag = false;
                    }
                }

            }
        }

        if (result) {
            this.result = result;
        }
    }

    version() {
        return parseInt(this.tag.substring(1).replaceAll('.', '')) % 128
    }

    async step1() {
        // this.log.info(`proxy ${this.prox}`)

        // this.log.info('setp1')
        let t1 = new Date().getTime();
        this.startTs = t1
        let t2 = t1 + randint(5, 30)
        this.startTs2 = t2
        this.performanceNow = randint(3000, 5000)
        this.px12280 = this.startTs2
        if (this.uuid === '') {
            this.uuid = genUuid()
            // this.uuid = 'f3e85a8d-965c-11ee-ae92-08214e602596';
        }
        let data = [{
            "t": "PX12095",
            "d": {
                "PX11645": this.url, "PX12207": 0, "PX12458": "iPhone", "PX11902": 0,
                "PX11560": randint(600, 800), "PX12248": 3600, "PX11385": t1, "PX12280": t2,
                "PX11496": this.uuid, "PX12564": null, "PX12565": -1,
            }
        }]
        let res = await this.do_collector(data)


    }

    async step2() {
        // this.performanceNow += randint(1000, 2000)
        //
        let data1 = [{"t": "PX12167", "d": {"PX11648": true}}]
        let res1 = await this.do_collector(data1)


        let data = [{
            "t": "PX11940",
            "d": {
                "PX11379": false,
                "PX12307": "PX11745",
                "PX11668": "pxhc",
                "PX12348": false,
                "PX11645": "https://booking.flyfrontier.com/Flight/Select"
            }
        }]

        if (typeof data === 'object') {
            data = JSON.stringify(data)
        }
        this.log.info(data)
        let payload = encodePayload(data, this.uuid, this.ts)
        let pc = genPc(data, `${this.uuid}:${this.tag}:${this.ft}`)
        let body = {
            "appId": this.appId,
            "tag": this.tag,
            "uuid": this.uuid,
            "ft": this.ft,
            "seq": this.seq,
            "en": "NTA",
            "pc": pc,
            "rsc": this.rsc,
            "payload": payload,
        }
        body = this.updateBody(body);


        let res = await axios.post(this.tlsUrl, JSON.stringify({
            url: "https://collector-PXVb73hTEg.px-client.net/b/g" + "?" + qs.stringify(body),
            // data: ,
            method: "GET",
            headers: this.pxHeaders,
            allow_redirects: true,
            debug: true,
            proxy: this.prox,
            id: "2"
        }));
        // let inRes = JSON.parse(res.data)
        // this.log.info(res.data)
        // this.parseRes(inRes)

        this.seq++;
        this.rsc++;


    }

    async step3() {
        this.performanceNow = randint(3000, 4000)
        this.px12280 = Date.now()
        // let data = genPayload2(this.url, this.sid, this.vid, this.ts, this.num1, this.num2,
        //     this.str1, this.uuid,
        //     this.startTs, this.startTs2, this.performanceNow, this.px12280)
        this.pxenv = new PxEnv(undefined, this.env, this.url, this.sid, this.vid, this.ts, this.num1, this.num2,
            this.str1, this.uuid,
            this.startTs, this.startTs2, this.performanceNow, this.px12280,
            this.ci, this.token, this.token2, this.hash, this.hash2, this.hashv)
        this.pxenv.cap = true
        let data = [this.pxenv.get_px11590()
            // , this.pxenv.get_px11796()
        ]
        // data.push({
        //     "t": "PX11796",
        //     "d": {
        //         "PX11771": "https://collector-PXVb73hTEg.px-client.net/b/g",
        //         "PX11902": 2,
        //         "PX11560": this.performanceNow,
        //         "PX12280": this.px12280,
        //         "PX11496": this.uuid,
        //         "PX12564": null,
        //         "PX12565": -1
        //     }
        // })

        let res = await this.do_collector(data)

        // this.seq++;
        // this.rsc++;

    }

    async step4() {
        this.performanceNow = parseInt(Date.now() - this.startTs) + randint(3000,5000)
        // this.performanceNow = randint(10000, 11000)
        this.px12280 = Date.now()
        // let data = genPayload4(this.url, this.sid, this.vid, this.ts, this.num1, this.num2,
        //     this.str1, this.uuid,
        //     this.startTs, this.startTs2, this.performanceNow, this.px12280)
        this.pxenv.performanceNow = this.performanceNow
        this.pxenv.performanceNow2 = this.pxenv.performanceNow;
        this.log.info('performanceNow', this.pxenv.performanceNow)
        this.pxenv = new PxEnv(undefined,this.env, this.url, this.sid, this.vid, this.ts, this.num1, this.num2,
            this.str1, this.uuid,
            this.startTs, this.startTs2, this.performanceNow, this.px12280,
            this.ci, this.token, this.token2, this.hash, this.hash2, this.hashv)
        this.pxenv.cap = true
        let data = [this.pxenv.get_px11547(),
            this.pxenv.get_px12123(),
            this.pxenv.get_px561(),
            this.pxenv.get_px11782()
            // , this.pxenv.get_px12419()
            // , this.pxenv.get_px11782()
        ]
        // data[1].d["PX11926"] = [{"PX12343": "pointerup", "PX11652": 0, "PX11699": 55711, "PX12270": "true"}]
        // data[1].d["PX12382"] = [6379]
        // data[1].d["PX11699"] = 57358
        // data[1].d["PX1133"] = 2376.9999999999854
        // data[1].d["PX11427"] = 361
        // data[1].d["PX12208"] = 0
        // data[1].d["PX11824"] = 393
        // data[1].d["PX11631"] = 62
        // data[1].d["PX11843"] = 393
        // data[1].d["PX11781"] = 852
        // data[1].d["PX11945"] = 272
        // data[1].d["PX12174"] = 29
        // data[1].d["PX11642"] = 272
        // data[1].d["PX11313"] = 390
        // data[1].d["PX11772"] = 49326
        // data[1].d["PX12024"] = 272
        // data[1].d["PX11759"] = 29
        // data[1].d["PX11633"] = 272
        // data[1].d["PX11445"] = 390
        // data[1].d["PX12417"] = 55711
        // data[1].d["PX11360"] = 398
        // data[1].d["PX12504"] = 55731
        // data[1].d["PX11902"] = 4
        // data[1].d["PX11560"] = 186688
        // data[1].d["PX12280"] = new Date().getTime()
        // data[1].d["PX11321"] = 55726
        // data[1].d["PX12411"] = 660
        // data[1].d["PX11494"] = 393
        // data[1].d["PX12265"] = 1
        // data[1].d["PX12537"] = 4
        // data[1].d["PX12504"] = 55731
        // let px11280 = Date.now();
        // for (let i = 0; i < data.length; i++) {
        //     data[i].d['PX11280'] = px11280
        // }
        // await this.sleep(5000)
        let res = await this.do_collector(data)
    }

    async test() {
        // this.prox = 'http://127.0.0.1:8890'
        // this.tlsUrl = 'http://127.0.0.1:58000/tls/forwardios'

        let cks = Object.keys(this.cookies).map((v, k) => `${v}=${this.cookies[v]}`).join('; ')
        let res = await axios.post(this.tlsUrl, JSON.stringify({
            url: 'https://booking.flyfrontier.com/Flight/InternalSelect?o1=DEN&d1=LAS&dd1=2023-12-30&ADT=1&umnr=false&mon=true',
            headers: {
                "Host": "booking.flyfrontier.com",
                "sec-ch-ua": "\"Not_A Brand\";v=\"8\", \"Chromium\";v=\"120\", \"Google Chrome\";v=\"120\"",
                "sec-ch-ua-mobile": "?0",
                "sec-ch-ua-platform": "\"macOS\"",
                "upgrade-insecure-requests": "1",
                "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
                "sec-fetch-site": "none",
                "sec-fetch-mode": "navigate",
                "sec-fetch-user": "?1",
                "sec-fetch-dest": "document",
                "accept-language": "en",
                "user-agent": this.ua,
                "cookie": cks
            },
            allow_redirects: true,
            debug: true,
            method: "GET",
            proxy: this.prox,

        }));

        if (res.data.status_code === 200) {
            this.log.warn('success', res.data.status_code, res.data.text.includes('FlightData'))
            await this.add_headers()
        } else {
            this.log.error('error', res.data.status_code)
        }
        return res.data.status_code
    }

    async init() {

        let res = await axios.post(this.tlsUrl, JSON.stringify({
            url: 'https://booking.flyfrontier.com/Flight/InternalSelect?o1=DEN&d1=LAS&dd1=2023-12-30&ADT=1&umnr=false&mon=true',
            headers: {
                "authority": "booking.flyfrontier.com",
                "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
                "accept-language": "en-US,en;q=0.9",
                "cache-control": "no-cache",
                "pragma": "no-cache",
                "sec-ch-ua": "\"Google Chrome\";v=\"117\", \"Not;A=Brand\";v=\"8\", \"Chromium\";v=\"117\"",
                "sec-ch-ua-mobile": "?0",
                "sec-ch-ua-platform": "\"macOS\"",
                "sec-fetch-dest": "document",
                "sec-fetch-mode": "navigate",
                "sec-fetch-site": "none",
                "sec-fetch-user": "?1",
                "upgrade-insecure-requests": "1",
                "user-agent": this.ua,
                "cookie": '_px2=eyJ1IjoiOGRjYjQ3NjAt1ODljYi011xMWVlLTkwMmUtODE4MTcxMjRjOTBlIiwidiI6IjhlOGIyMGMzLTg5Y2ItMTFlZS05YWI1LTAwMjc4Njk4ZmY1ZiIsInQiOjYyMDIzMzg4MDAwNCwiaCI6Ijk4NjYzMWNkZDBmNTBjMWE5NjZjYjgwOGNlNzFjYTJkMWNkYzc2MjdjYTc4MTBlZDVhODdmN2FiMzYzOGU1OTgifQ=='
            },
            allow_redirects: true,
            debug: true,
            method: "GET",
            proxy: this.prox,
            "id": "1",

        }));
        this.log.info(res.data.cookies)
        if (res.data.cookies['_pxhd']) {
            this.pxhd = res.data.cookies['_pxhd']
        }
        let reges = /_pxUuid = '([a-z0-9\-]+)'/.exec(res.data.text);
        if (reges && reges.length > 1) {
            this.uuid = reges[1]
        }
    }

    async step5() {
        this.performanceNow = randint(10000, 11000)
        this.px12280 = Date.now()
        // let data = genPayload4(this.url, this.sid, this.vid, this.ts, this.num1, this.num2,
        //     this.str1, this.uuid,
        //     this.startTs, this.startTs2, this.performanceNow, this.px12280)
        this.pxenv.performanceNow = this.performanceNow
        this.pxenv.performanceNow2 = this.pxenv.performanceNow;
        this.log.info('performanceNow', this.pxenv.performanceNow)
        this.pxenv = new PxEnv(this.env, this.url, this.sid, this.vid, this.ts, this.num1, this.num2,
            this.str1, this.uuid,
            this.startTs, this.startTs2, this.performanceNow, this.px12280,
            this.ci, this.token, this.token2, this.hash, this.hash2, this.hashv)
        this.pxenv.cap = true
        let data = [
            this.pxenv.get_px12523()
        ]
        // let px11280 = Date.now();
        // for (let i = 0; i < data.length; i++) {
        //     data[i].d['PX11280'] = px11280
        // }
        // await this.sleep(5000)
        let res = await this.do_collector(data)
    }
}

async function run() {
    let px = new PxBypass()
    await px.init()
    await px.step1()
    await px.step2()
    await px.sleep(1500)
    await px.step3()
    let press_time = ie(px.token2, 10);
    px.log.info(`press time ${press_time}ms`)
    await px.sleep(press_time)

    await px.step4()
    // await px.step5()
    await px.sleep(3000)

    if (!px.result) {
        // await px.step1()
        // await px.step2()
        // await px.sleep(1500)
        await px.step3()
        // await px.sleep(8000)

        await px.step4()

    }
    let statusCode = await px.test()

}


run()
