import readline from 'node:readline';
import { MAX_ANSWER_LENGTH } from './constants.js';

/**
 * Create prompt function that writes
 * the message and default value to stdout
 * and reads input from stdin.
 *
 * @example
 * await prompt({stdin: process.stdin, stdout: process.stdout})({
 *     type: 'input',
 *     message: 'Server URL',
 *     default: 'http://localhost'
 * })
 * // prints 'Server URL [http://localhost]: ', and returns input
 *
 * @param {Object} opts
 * @param {stream.Readable} opts.stdin - standard input stream
 * @param {stream.Writable} opts.stdout - standard output stream
 * @returns prompt function
 */
export const prompt = ({stdin, stdout}) => (opts) => {
    opts ??= {};
    opts.type ??= 'input';
    opts.message ??= '?';
    const hidden = opts.type === 'password';
    const promptMessage = opts.message + (opts.default ? ` [${opts.default}]: ` : ': ');

    const readLineInterface = readline.createInterface({
        input: stdin,
        output: stdout,
        prompt: promptMessage
    });

    readLineInterface.prompt();

    if (hidden) {
        stdin.setRawMode(true);
        readLineInterface._writeToOutput = () => {};
    }

    return new Promise((resolve, reject) => readLineInterface
        .on('line', line => {
            if (hidden) {
                stdout.write('\n');
                stdin.setRawMode(false);
            }
            readLineInterface.close();
            const answer = line.trim();
            if (answer.length > MAX_ANSWER_LENGTH) {
                const err = new Error('Input is too long');
                reject(err);
            }
            resolve(answer || (opts.default ?? ''));
        })
        .on('SIGINT', () => reject())
    );
};
