// reset.js
// dependencies
const fetch = require('node-fetch');
const puppeteer = require('puppeteer');

const ROUTER_URL = 'http://192.168.178.1';
const MAX_WAIT_MS = 3 * 60 * 1000;
const INTERVAL_MS = 10000;
const BROWSER_PATH = 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe';

// Code Constanten
const Version = "Script v1.2.8"
const UserError = "\n🛑! - ! - ! - ! - ! - ! - ! - ! - ! - ! - ! - ! - ! - ! - !🛑\n\nDer Reset konnte nicht durchgeführt werden.\nTrenne die FRITZ!Box vom Strom und starte das Programm neu!\nSollte es nach zwei Versuchen nicht funktionieren,\n resette die FRITZ!Box manuell.\n\n🛑! - ! - ! - ! - ! - ! - ! - ! - ! - ! - ! - ! - ! - ! - !🛑\n\n🔴 Ursache:\n"
const jetzt = new Date().toLocaleString('de-DE');

// Folge Variablen
let resetTriggered = false;
let browser;
let resetStart = 0;
let resetStop = 0;
let resetDauer = 0;

async function isRouterOnline() {
    try {
        const response = await fetch(ROUTER_URL, { method: 'GET', timeout: 10000 });
        return response.ok;
    } catch {
        return false;
    }
}


async function waitForRouter() {
    const start = Date.now();
    while (Date.now() - start < MAX_WAIT_MS) {
        if (await isRouterOnline()) {
            // console.log('Fritzbox ist erreichbar'); // dev
            return true;
        }
        console.log('⏳ Noch keine Verbindung . . . Warte 10 Sekunden.');
        await new Promise(resolve => setTimeout(resolve, INTERVAL_MS))
     }
}

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

(async () => {
    console.log(
        `\n- - - - - - - - - - - - - - - - - - - - -\n| HaSe-Reset | | Version: ${Version} |\n- - - - - - - - - - - - - - - - - - - - -\n`
    )
    const online = await isRouterOnline();
    if (online) {
        console.log("🟢 Fritzbox ist erreichbar!\n");
        console.log("FRITZ!Box Reset wird gestartet.\nBitte warten . . . !\n");
    } else {
        console.log("🔴 Fritzbox ist NICHT erreichbar!");
    }
})();


(async () =>{
    const routerReady = await waitForRouter();
    if (!routerReady) return;
    browser = await puppeteer.launch({
        headless: false,
        executablePath: BROWSER_PATH,
        args: ['--no-sandbox', '--disable-setuid-sandbox']
        });

    const page = await browser.newPage();
    await page.goto(ROUTER_URL, { waitUntil: 'domcontentloaded'});
    // console.log("Links werden gescannt . . ."); // dev
    // Part 1
    const allLinks = await page.$$('a');
    // console.log (`Links gefunden: ${allLinks.length}`); // dev

    const linkClicked = await page.evaluate(() => {
        const links = Array.from(document.querySelectorAll('a'));
        const target = links.find(a => a.innerText.includes('Kennwort vergessen'));
        if (target) {
            target.click();
            return true;
        }
        return false;
    });
    if (linkClicked) {
        // console.log("Kennwort vergessen - geklickt"); //dev
    } else {
        console.log(`${UserError}`);
        console.log("⚠️ Kein link mit 'Kennwort vergessen' gefunden");
    }
    // Part 2
    const allLinks2 = await page.$$('a');
    // console.log(`Links gefunden: ${allLinks2.length}`); // dev
    const linkClicked2 = await page.evaluate(() => {
        const links2 = Array.from(document.querySelectorAll('button'));
        const target2 = links2.find(button => button.innerText.includes('Werkseinstellungen'));
        if (target2) {
            target2.click();
            return true;
        }
        return false;
    });
    if (linkClicked2) {
        resetStart = Date.now();
        console.log("☑️ Reset wurde ausgelöst.")
        console.log(`| Start: ${new Date(resetStart).toLocaleString('de-DE')} |`);
        resetTriggered = true;
    } else {
        console.log(`${UserError}`);
        console.log("⚠️ Kein link mit 'Werkseinstellungen' gefunden.");
    }
    })();

    // Part3 - Nach Reset Wartezeit

(async () => {
    while (!resetTriggered) {
        await sleep(5000);
    }

    console.log("☑️ Reset gesendet.\n Warte bis die FRITZ!Box wieder erreichbar ist. . .\n")
    await sleep (60000)
    const maxWait = 5 * 60 * 1000;
    const start =Date.now();

    while (Date.now() - start < maxWait) {
        const erreichbar = await isRouterOnline();
        resetStop = Date.now();
        const dauerInSek = Math.round((resetStop - resetStart) / 1000);
        const minuten = Math.floor(dauerInSek / 60);
        const sekunden = dauerInSek % 60;
        resetDauer = `${minuten}:${sekunden.toString().padStart(2, '0')} Minuten`;
        if (erreichbar) {
            console.log(`| Start: ${resetStart} |\n| Stop: ${new Date(resetStop).toLocaleString('de-DE')} |\n| Dauer: ${resetDauer}|`);
            console.log("✅ FritzBox wurde erfolgreich zurückgesetzt.");
            if (browser) await browser.close();
            return;
        }
        console.log("⏳ Reset am laufen . . . Warte 10 Sekunden.")
        await sleep(10000);
    }
    console.log(`${UserError}`);
    console.error("⛔ FRITZ!Box ist nach dem Reset für 5min nicht erreichbar gewesen!")
    if (browser) await browser.close();
})();