/*!
 * Copyright (C) Microsoft Corporation. All rights reserved.
 */
import * as fs from 'fs';
import * as http from 'http';
import { getSettings } from '../CliSettings.js';
import { createPlayUrl } from '../CliUtils.js';
import { HelpStrings } from '../Constants/HelpStrings.js';
import { printError, printInfo, printWarning } from '../Utils/ConsoleOutput.js';
import { RunArguments } from './VerbConstants.js';
export async function runAsync(argumentProvider) {
    const settings = getSettings();
    const { appConfig, fileConfig } = settings;
    createOptionSchema(argumentProvider, appConfig?.localAppUrl);
    await argumentProvider.runVerb();
    if (!appConfig) {
        throw new Error('power.config.json is required to run an app');
    }
    if (!appConfig.environmentId) {
        throw new Error('Environment ID is required in power.config.json to run an app');
    }
    if (!appConfig.region) {
        appConfig.region = 'prod';
    }
    const powerConfigPath = fileConfig.powerConfigPath;
    const port = await argumentProvider.getOption('port');
    const appUrl = await argumentProvider.getOption('localAppUrl');
    // Start the local server
    await startLocalServer(powerConfigPath, parseInt(port, 10), appConfig, appUrl);
}
async function startLocalServer(powerConfigPath, port, appConfig, localAppUrl) {
    return new Promise((resolve, reject) => {
        const server = http.createServer((req, res) => {
            res.setHeader('Access-Control-Allow-Origin', '*');
            res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');
            res.setHeader('Access-Control-Allow-Headers', '*');
            if (req.method === 'OPTIONS') {
                res.writeHead(200);
                res.end();
                return;
            }
            try {
                if (!fs.existsSync(powerConfigPath)) {
                    res.writeHead(404, { 'Content-Type': 'application/json' });
                    res.end(JSON.stringify({ error: 'power.config.json not found' }));
                    return;
                }
                const fileContent = fs.readFileSync(powerConfigPath, 'utf8');
                res.writeHead(200, { 'Content-Type': 'application/json' });
                res.end(fileContent);
            }
            catch (error) {
                printError(`Error serving power.config.json: ${error.message}`);
                res.writeHead(500, { 'Content-Type': 'application/json' });
                res.end(JSON.stringify({ error: 'Internal server error' }));
            }
        });
        server.listen(port, 'localhost', async () => {
            printInfo(`Your power.config.json to setup connections is available at http://localhost:${port}`);
            printInfo(`\nYou can play your app locally at ${createPlayUrl(appConfig.region, appConfig.environmentId, 'local', localAppUrl, `http://localhost:${port}`)}`);
            // Check if localAppUrl is running
            await checkLocalAppUrl(localAppUrl);
        });
        server.on('error', (error) => {
            printError(`Server error: ${error.message}`);
            reject(error);
        });
        process.on('SIGINT', () => {
            printInfo('\nShutting down server...');
            server.close(() => {
                printInfo('Server stopped');
                process.exit(0);
            });
        });
    });
}
function createOptionSchema(argumentProvider, localAppUrl) {
    argumentProvider.setDescription(HelpStrings.Verbs.Run.Description);
    argumentProvider.addExamples(HelpStrings.Verbs.Run.Examples);
    argumentProvider.addOptions([
        {
            flags: {
                key: RunArguments.Port.name,
                alias: RunArguments.Port.alias,
            },
            env: RunArguments.Port.envVar,
            default: RunArguments.Port.initialValue,
            description: HelpStrings.Verbs.Run.Options.Port,
        },
        {
            flags: {
                key: RunArguments.LocalAppUrl.name,
                alias: RunArguments.LocalAppUrl.alias,
            },
            env: RunArguments.LocalAppUrl.envVar,
            default: localAppUrl || RunArguments.LocalAppUrl.initialValue,
            description: HelpStrings.Verbs.Run.Options.LocalAppUrl,
        },
    ]);
}
async function checkLocalAppUrl(localAppUrl) {
    try {
        const controller = new AbortController();
        const timeoutId = setTimeout(() => controller.abort(), 5000);
        const response = await fetch(localAppUrl, {
            method: 'HEAD',
            signal: controller.signal,
        });
        clearTimeout(timeoutId);
        if (response.ok || response.status < 500) {
            // No-op
            return;
        }
        else {
            printWarning(`Warning: Your local app running at ${localAppUrl} returned status ${response.status}, which is unexpected. Check your app code for exceptions.`);
        }
    }
    catch (error) {
        printWarning(`Warning: Your local app is NOT currently running at ${localAppUrl}`);
    }
}
//# sourceMappingURL=Run.js.map