import fs from 'fs';
import path from 'path';
import { z } from 'zod';
import auth from '../../Auth.js';
import Command, { globalOptionsZod } from '../../Command.js';
import request from '../../request.js';
import commands from './commands.js';
const allowedMethods = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options'];
export const options = z.looseObject({
    ...globalOptionsZod.shape,
    url: z.string().alias('u'),
    method: z.enum(allowedMethods).default('get').alias('m'),
    resource: z.string().optional().alias('r'),
    body: z.string().optional().alias('b'),
    filePath: z.string().optional().alias('p')
});
class RequestCommand extends Command {
    get name() {
        return commands.REQUEST;
    }
    get description() {
        return 'Executes the specified web request using CLI for Microsoft 365';
    }
    get schema() {
        return options;
    }
    getRefinedSchema(schema) {
        return schema
            .refine(opts => !opts.body || (opts.method !== 'get'), {
            error: 'Specify a different method when using body'
        })
            .refine(opts => !opts.body || opts['content-type'], {
            error: 'Specify the content-type when using body'
        })
            .refine(opts => !opts.filePath || fs.existsSync(path.dirname(opts.filePath)), {
            error: 'The location specified in the filePath does not exist'
        });
    }
    async commandAction(logger, args) {
        if (this.debug) {
            await logger.logToStderr(`Preparing request...`);
        }
        try {
            const url = this.resolveUrlTokens(args.options.url);
            const method = args.options.method.toUpperCase();
            const headers = {};
            this.addUnknownOptionsToPayloadZod(headers, args.options);
            if (!headers.accept) {
                headers.accept = 'application/json';
            }
            if (args.options.resource) {
                headers['x-resource'] = args.options.resource;
            }
            const config = {
                url: url,
                headers,
                method,
                data: args.options.body
            };
            if (headers.accept.toString().startsWith('application/json')) {
                config.responseType = 'json';
            }
            if (args.options.filePath) {
                config.responseType = 'stream';
            }
            if (this.verbose) {
                await logger.logToStderr(`Executing request...`);
            }
            if (args.options.filePath) {
                const file = await request.execute(config);
                const filePath = await new Promise((resolve, reject) => {
                    const writer = fs.createWriteStream(args.options.filePath);
                    file.data.pipe(writer);
                    writer.on('error', err => {
                        reject(err);
                    });
                    writer.on('close', () => {
                        resolve(args.options.filePath);
                    });
                });
                if (this.verbose) {
                    await logger.logToStderr(`File saved to path ${filePath}`);
                }
            }
            else {
                const res = await request.execute(config);
                await logger.log(res);
            }
        }
        catch (err) {
            this.handleError(err);
        }
    }
    resolveUrlTokens(url) {
        if (url.startsWith('@graphbeta')) {
            return url.replace('@graphbeta', 'https://graph.microsoft.com/beta');
        }
        if (url.startsWith('@graph')) {
            return url.replace('@graph', 'https://graph.microsoft.com/v1.0');
        }
        if (url.startsWith('@spo')) {
            if (auth.connection.spoUrl) {
                return url.replace('@spo', auth.connection.spoUrl);
            }
            throw `SharePoint root site URL is unknown. Please set your SharePoint URL using command 'spo set'.`;
        }
        return url;
    }
}
export default new RequestCommand();
//# sourceMappingURL=request.js.map