const {SolveCaptcha, TWO_CAPTCHA_CONNECTION_FAILED} = require("./SolveCaptcha");
const BlackListContactPojo = require("../models/BlackListContactPojo");
const appointmentLogger = require("../utiles/LoggerUtils")
const PublishType = require("../models/PublishType");
const {
    shell
} = require('electron')
const GeoCaptchaSolver = require("./GeoCaptchaSolver");
// const RDV_URL = "http://192.168.0.41:8000/test_appointment.html"
BLANK_URL = "about:blank"
const ERROR_CAPTCHA_UNSOLVABLE = "ERROR_CAPTCHA_UNSOLVABLE";

const TIME_OUT = 60 * 1000 * 2//2 mins

const CONFIRMED_MESSAGE = "Your request for a Leather Goods appointment has been registered"
const CONFIRMED_MESSAGE_FR = "Votre demande de rendez-vous Maroquinerie a bien été enregistrée et nous vous en remercions."
const CONFIRMED_MESSAGE_CN = "您的皮具预约申请已登记"
const DOUBLE_REQUEST_ERROR_MESSAGE_FR = "Une demande avec les données saisies a déjà été validée aujourd’hui."
const EMPTY_RESPONSE_ERROR = "ERR_EMPTY_RESPONSE"
const DOUBLE_REQUEST_ERROR_MESSAGE = "A request with the same data has already been validated today."

const TOO_MANY_REQUEST_ERROR_MESSAGE = "Due to a large number of requests"
const TOO_MANY_REQUEST_ERROR_MESSAGE_FR = "Suite à un trop grand nombre de demandes"
const CAPTCHA_ERROR_MESSAGE = "Error verifying captcha, please try again"
const CAPTCHA_ERROR_MESSAGE_FR = "La vérification du captcha a échoué"
REGEX_RDV_URL = "https:\/\/rendezvousparis\.hermes\.com\/client\/register\/[A-Z0-9]+"
const PLAY_AUDIO_BTN_ID = ".audio-captcha-play-button"
const homedir = require('os').homedir();
const CAPTCHA_CONTAINER = "#captcha-container";

function delay(delayInMs) {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(2);
        }, delayInMs);
    });
}

function getRandom() {
    return Math.floor(Math.random() * 3);
}

function log(message) {
    appointmentLogger.log({level: "info", message: message})
}

class LinkValidator {
    constructor(device, urlToValidate, mongoManager) {
        this.device = device;
        this.mongoManager = mongoManager;
        this.isTerminated = false;
        this.urlToValidate = urlToValidate;
    }

    async loadPage() {
        // Connect to the device.
        log("loadPage() called for url " + this.urlToValidate);
        // await this.device.shell('am force-stop com.android.chrome');
        try {
            const context = await this.device.launchBrowser();
            // await context.clearCookies()

            // Use BrowserContext as usual.
            this.page = await context.newPage();
            this.page.on("load", (loadedPage) => {
                this.onPageLoad(loadedPage)
            })

            this.page.on("response", (response) => {
                this.onResponse(response)
            })
            try {
                await this.page.goto(this.urlToValidate, {timeout: 90 * 1000});
            } catch (e) {
                log(e)
                this.isTerminated = true
            }

            let cancel
            const intervalTask = setInterval(() => {
                if (this.isTerminated) {
                    log(this.device.model() + ":request terminated, will close device")
                    context.close()
                    // this.page.close()
                    this.device.close()
                    clearInterval(intervalTask)
                    cancel()
                    return context
                }
            }, 5 * 1000)//interval of 10 seconds

            await new Promise(function (fulfill, reject) {
                cancel = function () {
                    fulfill(Promise.resolve())
                }
                setTimeout(fulfill, TIME_OUT, 5)
            }).then(log)
        } catch (e) {
            console.log(e)
        }

    }

    async onPageLoad(currentPage) {
        try {
            let content = await currentPage.content();
            let captcha_url = "geo.captcha-delivery.com/captcha";
            if (content.toString().includes(captcha_url)) {
                log(this.device.model() + ":发现datadome");
                await this.checkAudioBtn();
            } else {
                if (content.includes(CONFIRMED_MESSAGE) || content.includes(CONFIRMED_MESSAGE_FR) || content.includes(CONFIRMED_MESSAGE_CN)) {
                    log("successful");
                    await this.push_message_to_queue(PublishType.SUCCESS);
                } else if (content.includes(EMPTY_RESPONSE_ERROR)) {
                    log("EMPTY_RESPONSE_ERROR error received, will quit")
                    this.isTerminated = true
                } else {
                    //    try to get errors
                    await this.getErrors()
                }
            }
        } catch (e) {
            log(e)
        }
    }

    async checkAudioBtn() {
        let audioBtn = await this.page.frameLocator("iframe").locator("#captcha__audio__button");
        let isBlocked = await this.isBlocked()
        if (!isBlocked) {
            log(this.device.model() + ":audioBtn found")
            if (!this.isTerminated) {
                try {
                    await audioBtn.click()
                    let captchaSolver = new GeoCaptchaSolver(this.page, this.device, this.isTerminated)
                    await captchaSolver.solve((isSuccessful) => {
                        if (!isSuccessful) {
                            this.isTerminated = true
                        }
                    })
                } catch (e) {
                    this.isTerminated = true
                    log(e)
                }
            }
        } else {
            log("audioBtn not found")
            console.log("audioBtn not found")
            console.log("we are blocked")
            await this.resetBrowser()
        }
    }

    async isBlocked() {
        let iframeHandler = await this.page.frameLocator("body > iframe");
        let captcha_container = await iframeHandler.locator(CAPTCHA_CONTAINER)
        let html = await captcha_container.innerHTML()
        console.log("audio_tag: " + html);
        return html.includes("You have been blocked")
    }

    async onResponse(response) {
        // let rex = new RegExp(REGEX_RDV_URL)
        log(this.device.model() + ":onResponse url:" + response.url())
        log(this.device.model() + ":onResponse with statusCode:" + response.statusCode)
        log(this.device.model() + ":onResponse with message:" + response.statusMessage)
        // if (rex.test(response.url())) {
        //     log("rdv url found:" + response.url())
        //     await this.push_message_to_db(PublishType.SUCCESS, response.url())
        // }
    }

    async push_message_to_queue(publishType) {
        let url = this.page.url();
        if (url === "https://rendezvousparis.hermes.com/client/welcome") {
            return
        }
        //    save to mongoDb
        await this.mongoManager.linkValidatedFor(url)
        await this.mongoManager.removeFromToValidateList(this.urlToValidate)
        // await this.resetBrowser()
        this.isTerminated = true
    }

    async getErrors() {
        if (this.page.url() === BLANK_URL) {
            this.isTerminated = true;
        } else {
            try {
                let errorItem = this.page.locator("div.alert");
                if (errorItem) {
                    let errorContent = await errorItem.innerHTML();
                    await this.handleError(errorContent);
                }
            } catch (e) {
                log(e);
            }
        }
    }

    async handleError(errorContent) {
        log(this.device.model() + ":handle error:" + errorContent);
        if (errorContent.includes(DOUBLE_REQUEST_ERROR_MESSAGE) || errorContent.includes(DOUBLE_REQUEST_ERROR_MESSAGE_FR)) {
            this.isTerminated = true;
        } else if (errorContent.includes(TOO_MANY_REQUEST_ERROR_MESSAGE) || errorContent.includes(TOO_MANY_REQUEST_ERROR_MESSAGE_FR)) {
            //add contact to black list and set terminated the task
            log(this.device.model() + ":handle error: will save to black list db");
        } else if (errorContent.includes(CAPTCHA_ERROR_MESSAGE) || errorContent.includes(CAPTCHA_ERROR_MESSAGE_FR)) {
            this.isTerminated = true;
        }

    }

    async resetBrowser() {
        console.log(this.device.model() + ":will reset browser")
        await this.device.shell("pm clear com.android.chrome")
        await delay(1000)
        await this.device.shell("am set-debug-app --persistent com.android.chrome")
        await delay(1000)
        await this.device.shell("pm am start -n com.android.chrome/com.google.android.apps.chrome.Main")
        await delay(1000)
        this.isTerminated = true
    }
}

module.exports = LinkValidator