/**
 * ./src/commands/update.ts
 * penguins-eggs v.25.7.x / ecmascript 2020
 * author: Piero Proietti
 * email: piero.proietti@gmail.com
 * license: MIT
 */
import { Command, Flags } from '@oclif/core';
import { select } from '@inquirer/prompts';
import axios from 'axios';
import https from 'node:https';
import Distro from '../classes/distro.js';
import Diversions from '../classes/diversions.js';
import Tools from '../classes/tools.js';
import Utils from '../classes/utils.js';
import { exec, spawn } from '../lib/utils.js';
const agent = new https.Agent({
    rejectUnauthorized: false
});
/**
 *
 */
export default class Update extends Command {
    static description = "update the Penguins' eggs tool";
    static examples = ['eggs update'];
    static flags = {
        help: Flags.help({ char: 'h' }),
        verbose: Flags.boolean({ char: 'v', description: 'verbose' })
    };
    distro = new Distro();
    /**
     *
     */
    async choosePkg() {
        const choices = [
            { name: 'Abort', value: 'Abort' },
            { name: 'LAN', value: 'LAN' },
            { name: 'Internet', value: 'Internet' },
            { name: 'Source', value: 'Source' },
        ];
        const selected = await select({
            message: 'Select update method',
            choices,
        });
        if (selected === 'Abort') {
            process.exit(0);
        }
        return selected;
    }
    async chooseUpdate() {
        console.log();
        const choose = await this.choosePkg();
        Utils.titles(`updating via ${choose}`);
        switch (choose) {
            case 'Internet': {
                if (Utils.isAppImage()) {
                    await this.getLatestAppImage();
                }
                else {
                    await this.getPkgFromPackageManager();
                }
                break;
            }
            case 'LAN': {
                await this.getPkgFromLan();
                break;
            }
            case 'Source': {
                this.getFromSource();
                break;
            }
            // No default
        }
    }
    /**
     *
     * @param url
     * @param outputFilename
     * @returns
     */
    async downloadWithCurl(url, outputFilename) {
        return new Promise((resolve, reject) => {
            console.log(`Avvio download di: ${outputFilename}...`);
            // Spawniamo il processo curl
            // -L: segue i redirect (fondamentale per GitHub)
            // -o: specifica il file di output
            const curl = spawn('curl', ['-L', '-o', outputFilename, url], {
                stdio: 'inherit' // Questo mostra la progress bar di curl direttamente nel tuo terminale!
            });
            curl.on('close', (code) => {
                if (code === 0) {
                    console.log('\nDownload completato con successo!');
                    resolve();
                }
                else {
                    reject(new Error(`Curl è uscito con codice errore: ${code}`));
                }
            });
            curl.on('error', (err) => {
                reject(new Error(`Impossibile avviare curl. È installato? ${err.message}`));
            });
        });
    }
    /**
     *
     */
    getFromSource() {
        console.log('Use the following commands to use penguins-eggs from source:');
        console.log('');
        console.log('cd ~');
        console.log('git clone https://github.com/pieroproietti/penguins-eggs');
        console.log('cd penguins-eggs');
        console.log('pnpm install');
        console.log('pnpm build');
        console.log('./eggs');
        console.log('');
        console.log('NOTE: requires nodejs>18 and pnpm installed');
    }
    /**
     *
     */
    async getLatestAppImage() {
        const url = await this.getLatestAppImageUrl();
        console.log(`Downloading AppImage from ${url}`);
        const AppFile = '/tmp/eggs.AppImage';
        if (url !== null) {
            await this.downloadWithCurl(url, AppFile);
        }
        await exec(`mv ${AppFile} /usr/bin/eggs`);
        await exec(`chmod +x /usr/bin/eggs`);
    }
    /**
     *
     */
    async getLatestAppImageUrl() {
        const repo = 'pieroproietti/penguins-eggs';
        const apiUrl = `https://api.github.com/repos/${repo}/releases/latest`;
        try {
            const response = await fetch(apiUrl);
            if (!response.ok)
                throw new Error(`Errore API GitHub: ${response.statusText}`);
            const data = (await response.json());
            // Cerchiamo l'asset che finisce per .AppImage
            const asset = data.assets.find((a) => a.name.endsWith('.AppImage'));
            return asset ? asset.browser_download_url : null;
        }
        catch (error) {
            console.error(' :', error);
            return null;
        }
    }
    /**
     * download da LAN
     */
    async getPkgFromLan() {
        const Tu = new Tools();
        await Tu.loadSettings();
        Utils.warning('Update penguins-eggs from LAN');
        let filter = '';
        let copy = '';
        let install = '';
        let repo = '';
        if (Utils.isAppImage()) {
            console.log('AppImage: penguins-eggs-*-x86_64.AppImage will be installed as /usr/bin/eggs');
            filter = `penguins-eggs-*-x86_64.AppImage`;
            copy = `scp ${Tu.config.remoteUser}@${Tu.config.remoteHost}:${Tu.config.remotePathPackages}/${filter} /tmp`;
            install = `mv /tmp/${filter} /usr/bin/eggs`;
        }
        else {
            /**
             * Alpine
             */
            switch (this.distro.familyId) {
                case 'alpine': {
                    repo = `alpine/x86_64`;
                    filter = `penguins-eggs-*-*.*.?-r?.apk`;
                    copy = `scp ${Tu.config.remoteUser}@${Tu.config.remoteHost}:${Tu.config.remotePathPackages}/${repo}/${filter} /tmp`;
                    install = `apk add /tmp/${filter}`;
                    /**
                     * Arch
                     */
                    break;
                }
                case 'archlinux': {
                    repo = 'aur';
                    filter = `penguins-eggs-??.*.*-?-any.pkg.tar.zst`;
                    if (Diversions.isManjaroBased(this.distro.distroId)) {
                        repo = 'manjaro';
                        filter = `penguins-eggs-??.*.*-?-any.pkg.tar.*`;
                    }
                    copy = `scp ${Tu.config.remoteUser}@${Tu.config.remoteHost}:${Tu.config.remotePathPackages}/${repo}/${filter} /tmp`;
                    install = `pacman -U /tmp/${filter}`;
                    /**
                     * Devuan/Debian/Ubuntu
                     */
                    break;
                }
                case 'debian': {
                    repo = 'debs';
                    filter = `penguins-eggs_??.*.*-?_${Utils.uefiArch()}.deb`;
                    copy = `scp ${Tu.config.remoteUser}@${Tu.config.remoteHost}:${Tu.config.remotePathPackages}/${repo}/${filter} /tmp`;
                    install = `apt reinstall /tmp/${filter}`;
                    /**
                     * fedora/el9
                     */
                    break;
                }
                case 'fedora': {
                    repo = 'fedora';
                    let ftype = 'fc??';
                    if (this.distro.distroId !== 'Fedora') {
                        repo = 'el9';
                        ftype = 'el?';
                    }
                    filter = `penguins-eggs-??.*.*-?.${ftype}.x86_64.rpm`;
                    copy = `scp ${Tu.config.remoteUser}@${Tu.config.remoteHost}:${Tu.config.remotePathPackages}/${repo}/${filter} /tmp`;
                    install = `dnf reinstall /tmp/${filter} || dnf install /tmp/${filter}`;
                    /**
                     * openmamba
                     */
                    break;
                }
                case 'openmamba': {
                    repo = 'openmamba';
                    filter = `penguins-eggs-??.*.*-?mamba.x86_64.rpm`;
                    copy = `scp ${Tu.config.remoteUser}@${Tu.config.remoteHost}:${Tu.config.remotePathPackages}/${repo}/${filter} /tmp`;
                    install = `dnf reinstall /tmp/${filter} || dnf install /tmp/${filter}`;
                    /**
                     * opensuse
                     */
                    break;
                }
                case 'opensuse': {
                    repo = 'opensuse';
                    filter = `penguins-eggs-*.*.*-?.opensuse.x86_64.rpm`;
                    copy = `scp ${Tu.config.remoteUser}@${Tu.config.remoteHost}:${Tu.config.remotePathPackages}/${repo}/${filter} /tmp`;
                    install = `zypper install --force /tmp/${filter} || zypper install /tmp/${filter}`;
                    break;
                }
                // No default
            }
        }
        /**
         * copy and install
         */
        if (await Utils.customConfirm(`Want to update/reinstall penguins-eggs`)) {
            await exec(copy, { capture: true, echo: true });
            await exec(install);
        }
    }
    /**
     *
     */
    async getPkgFromPackageManager() {
        Utils.titles(`update from package Manager`);
        let cmd = '';
        switch (this.distro.familyId) {
            case 'alpine': {
                cmd = `doas apk add penguins-egga`;
                break;
            }
            case 'archlinux': {
                cmd = 'sudo pacman -S penguins-eggs';
                break;
            }
            case 'debian': {
                cmd = 'sudo apt install penguins-eggs\nsudo apt reinstall penguins-eggs';
                break;
            }
            case 'fedora': {
                cmd = 'sudo dnf install penguins-eggs\nsudo dnf reinstall penguins-eggs';
                break;
            }
            case 'openmamba': {
                cmd = 'sudo dnf install penguins-eggs\nsudo dnf reinstall penguins-eggs';
                break;
            }
            case 'opensuse': {
                cmd = String.raw `sudo zypper install penguins-eggs\zypper install --force penguins-eggs`;
                break;
            }
            // No default
        }
        Utils.warning(`To install/update penguins-eggs cut and copy one of the follow commands`);
        console.log();
        console.log(cmd);
        console.log();
    }
    /**
     * run
     */
    async run() {
        Utils.titles(this.id + ' ' + this.argv);
        const { flags } = await this.parse(Update);
        Utils.titles(this.id + ' ' + this.argv);
        if (Utils.isRoot()) {
            if (Utils.isSources()) {
                Utils.warning(`You are on penguins-eggs v. ${Utils.getPackageVersion()} from sources`);
            }
            else if (Utils.isPackage()) {
                Utils.warning(`You are on eggs-${Utils.getPackageVersion()} installed as package`);
            }
            await this.chooseUpdate();
        }
        else {
            Utils.useRoot(this.id);
        }
    }
    /**
     * show
     */
    async show(url) {
        url += `/stats/json`;
        const yesterday = new Date();
        yesterday.setDate(yesterday.getDate() - 1);
        // adjust 0 before single digit date
        const day = ('0' + yesterday.getDate()).slice(-2);
        const month = ('0' + (yesterday.getMonth() + 1)).slice(-2);
        const year = yesterday.getFullYear();
        const end = year + '-' + month + '-' + day;
        const start = year + '-' + month + '-' + day;
        const request = '?start_date=' + start + '&end_date=' + end;
        url += request;
        const res = await axios.get(url, { httpsAgent: agent });
        console.log('\nStatistics to get an idea: yesterday downloads');
        console.log();
        for (const country of res.data.countries) {
            console.log('- ' + country[0] + ': ' + country[1]);
        }
    }
}
