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 { DateTime } from 'luxon';
import { stdin } from 'node:process';
import { BaseCommand } from '../../base.js';
import { FLAG_ADD_PASSWORD, FLAG_GENERATE_PASSWORD, FLAG_RECIPIENTS, FLAG_VERIFY } from '../../flags.js';
export default class Message extends BaseCommand {
    static aliases = ['send:msg'];
    static args = {
        message: Args.string({
            description: 'Message body (will be read from stdin if empty)',
            required: false,
            ignoreStdin: true,
        }),
    };
    static description = 'Send a secure message, either by specifying the message as a command argument or reading data from stdin.';
    static enableJsonFlag = true;
    static flags = {
        count: Flags.integer({
            char: 'c',
            summary: 'Maximum download count',
        }),
        desc: Flags.string({
            char: 'd',
            default: `Secure Message ${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,
        subject: Flags.string({
            char: 's',
            default: 'Secure Message',
            summary: 'Message subject',
        }),
        format: Flags.string({
            options: ['plain', 'markdown'],
            default: 'plain',
            summary: 'Message format',
        }),
    };
    async run() {
        let flags = FILE_FLAGS.URL_FRAGMENT | FILE_FLAGS.MESSAGE;
        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;
        }
        let message = this.args.message;
        if (!message) {
            message = '';
            stdin.setEncoding('utf8');
            for await (const chunk of stdin) {
                message += chunk;
            }
        }
        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,
            },
        });
        if (this.flags.format === 'markdown') {
            upload.addMessage(this.flags.subject, message, 'application/vnd.trebuchet.viewer.markdown');
        }
        else {
            upload.addMessage(this.flags.subject, message);
        }
        const fragment = toBasedString('base64-url', fromRandom(32));
        upload.setFragment(fragment);
        if (password) {
            upload.setPassword(password);
        }
        await upload.upload();
        await this.setTransfer(upload.fileId, { fragment, password });
        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,
        };
    }
}
