import fs from 'fs';
import path from 'path';
import { setTimeout } from 'timers/promises';
import { z } from 'zod';
import { globalOptionsZod } from '../../../../Command.js';
import request from '../../../../request.js';
import { formatting } from '../../../../utils/formatting.js';
import { validation } from '../../../../utils/validation.js';
import PowerPlatformCommand from '../../../base/PowerPlatformCommand.js';
import commands from '../../commands.js';
export const options = z.strictObject({
    ...globalOptionsZod.shape,
    name: z.string()
        .refine(val => validation.isValidGuid(val), {
        message: 'The value is not a valid GUID for option name.'
    })
        .alias('n'),
    environmentName: z.string().alias('e'),
    packageDisplayName: z.string().optional(),
    packageDescription: z.string().optional().alias('d'),
    packageCreatedBy: z.string().optional().alias('c'),
    packageSourceEnvironment: z.string().optional().alias('s'),
    path: z.string().optional()
        .refine(val => !val || fs.existsSync(path.dirname(val)), {
        message: 'Specified path where to save the file does not exist.'
    })
        .alias('p')
});
class PaAppExportCommand extends PowerPlatformCommand {
    constructor() {
        super(...arguments);
        this.pollingInterval = 5000;
    }
    get name() {
        return commands.APP_EXPORT;
    }
    get description() {
        return 'Exports the specified Power App';
    }
    get schema() {
        return options;
    }
    async commandAction(logger, args) {
        try {
            const location = await this.exportPackage(args, logger);
            const packageLink = await this.getPackageLink(logger, location);
            let filename = args.options.name;
            if (args.options.packageDisplayName) {
                //Replace all illegal characters from the file name
                const illegalCharsRegEx = /[\\/:*?"<>|]/g;
                filename = args.options.packageDisplayName.replace(illegalCharsRegEx, '_');
            }
            const requestOptions = {
                url: packageLink,
                // Set responseType to arraybuffer, otherwise binary data will be encoded
                // to utf8 and binary data is corrupt
                responseType: 'arraybuffer',
                headers: {
                    'x-anonymous': true
                }
            };
            const file = await request.get(requestOptions);
            let path = args.options.path || './';
            if (!path.endsWith('/')) {
                path += '/';
            }
            path += `${filename}.zip`;
            fs.writeFileSync(path, file, 'binary');
            if (this.verbose) {
                await logger.logToStderr(`File saved to path '${path}'`);
            }
        }
        catch (err) {
            this.handleRejectedODataJsonPromise(err);
        }
    }
    async getPackageResources(args, logger) {
        if (this.verbose) {
            await logger.logToStderr('Getting the Microsoft Power App resources...');
        }
        const requestOptions = {
            url: `${this.resource}/providers/Microsoft.BusinessAppPlatform/environments/${formatting.encodeQueryParameter(args.options.environmentName)}/listPackageResources?api-version=2016-11-01`,
            headers: {
                accept: 'application/json'
            },
            data: {
                baseResourceIds: [
                    `/providers/Microsoft.PowerApps/apps/${args.options.name}`
                ]
            },
            responseType: 'json'
        };
        const response = await request.post(requestOptions);
        Object.keys(response.resources).forEach((key) => {
            response.resources[key].suggestedCreationType = 'Update';
        });
        return response.resources;
    }
    async exportPackage(args, logger) {
        if (this.verbose) {
            await logger.logToStderr(`Initiating package export for Microsoft Power App ${args.options.name}...`);
        }
        const resources = await this.getPackageResources(args, logger);
        const requestOptions = {
            url: `${this.resource}/providers/Microsoft.BusinessAppPlatform/environments/${formatting.encodeQueryParameter(args.options.environmentName)}/exportPackage?api-version=2016-11-01`,
            headers: {
                accept: 'application/json'
            },
            responseType: 'json',
            data: {
                includedResourceIds: [
                    `/providers/Microsoft.PowerApps/apps/${args.options.name}`
                ],
                details: {
                    creator: args.options.packageCreatedBy,
                    description: args.options.packageDescription,
                    displayName: args.options.packageDisplayName || args.options.name,
                    sourceEnvironment: args.options.packageSourceEnvironment
                },
                resources: resources
            },
            fullResponse: true
        };
        const response = await request.post(requestOptions);
        return response.headers.location;
    }
    async getPackageLink(logger, location) {
        if (this.verbose) {
            await logger.logToStderr('Retrieving the package link and waiting on the exported package.');
        }
        let status;
        let link;
        const requestOptions = {
            url: location,
            headers: {
                accept: 'application/json'
            },
            responseType: 'json'
        };
        do {
            const response = await request.get(requestOptions);
            status = response.properties.status;
            if (status === "Succeeded") {
                link = response.properties.packageLink.value;
            }
            else {
                await setTimeout(this.pollingInterval);
            }
            if (this.verbose) {
                await logger.logToStderr(`Current status of the get package link: ${status}`);
            }
        } while (status === 'Running');
        return link;
    }
}
export default new PaAppExportCommand();
//# sourceMappingURL=app-export.js.map