import { password as passwordPrompt } from '@inquirer/prompts';
import { Args, Flags } from '@oclif/core';
import { FILE_FLAGS, FileUpload, fromRandom, getFileSharingCode, getFileSharingLink, toBasedString, } from '@trebuchet/sdk-nodejs';
import { SingleBar } from 'cli-progress';
import { DateTime } from 'luxon';
import { open } from 'node:fs/promises';
import { basename } from 'node:path';
import { BaseCommand } from '../../base.js';
import { FLAG_ADD_PASSWORD, FLAG_GENERATE_PASSWORD, FLAG_RECIPIENTS, FLAG_VERIFY } from '../../flags.js';
export default class Files extends BaseCommand {
    static aliases = ['send:file'];
    static args = {
        files: Args.file(),
    };
    static description = 'Send one or more files.';
    static enableJsonFlag = true;
    static flags = {
        count: Flags.integer({
            char: 'c',
            summary: 'Maximum download count',
        }),
        desc: Flags.string({
            char: 'd',
            default: `Secure Files ${DateTime.now().toFormat('dd/MM/yyyy')}`,
            summary: 'Transfer description',
        }),
        exp: Flags.integer({
            char: 'e',
            summary: 'Expiry duration (days)',
        }),
        'add-password': FLAG_ADD_PASSWORD,
        'generate-password': FLAG_GENERATE_PASSWORD,
        recipient: FLAG_RECIPIENTS,
        verify: FLAG_VERIFY,
    };
    static strict = false;
    async run() {
        let bar;
        if (!this.flags.json) {
            bar = new SingleBar({
                clearOnComplete: true,
                format: '[{bar}] {percentage}% | ETA: {eta}s',
            });
        }
        let flags = FILE_FLAGS.URL_FRAGMENT;
        let password;
        if (this.flags['add-password']) {
            password = await passwordPrompt({ message: 'Enter password:', mask: true });
            flags |= FILE_FLAGS.PASSWORD;
        }
        else if (this.flags['generate-password']) {
            const c = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
            password = [...crypto.getRandomValues(new Uint32Array(24))].map((x) => c[x % c.length]).join('');
            flags |= FILE_FLAGS.PASSWORD;
        }
        if (this.flags.verify || this.flags.recipient) {
            flags |= FILE_FLAGS.VERIFY_RECIPIENT;
        }
        const upload = await FileUpload.createNew(this.sdk, {
            fileCreateRequest: {
                description: this.flags.desc,
                exp: 86_400 * (this.flags.exp || this.userConfig.defaultExpiryDays),
                flags,
                max: this.flags.count || this.userConfig.defaultDownloads,
                recipients: this.flags.recipient,
            },
        }, (done, total) => {
            if (bar) {
                if (bar.isActive) {
                    bar.update(done);
                }
                else {
                    bar.start(total, done);
                }
            }
        });
        for (const path of this.parsedArgv) {
            const fd = await open(path);
            upload.addFile({
                data: fd,
                name: basename(path),
                size: (await fd.stat()).size,
                type: 'application/octet-string',
            });
        }
        const fragment = toBasedString('base64-url', fromRandom(32));
        upload.setFragment(fragment);
        if (password) {
            upload.setPassword(password);
        }
        await upload.upload();
        if (bar) {
            bar.stop();
        }
        const link = getFileSharingLink(this.userConfig.baseUrl, upload.file, fragment);
        const code = getFileSharingCode(upload.file, fragment);
        this.log(`Link:         ${link}`);
        this.log(`Sharing code: ${code}`);
        if (password) {
            if (this.flags['generate-password']) {
                this.log(`Password:     ${password}`);
            }
            else {
                this.log(`Password:     ${'*'.repeat(password.length)}`);
            }
        }
        return {
            code,
            link,
            metadata: upload.metadata,
            password,
        };
    }
}
