"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.addApplicationGenerator = addApplicationGenerator;
const tslib_1 = require("tslib");
const devkit_1 = require("@nx/devkit");
const path = tslib_1.__importStar(require("path"));
const utils_1 = require("../utils");
const dependency_config_1 = require("../dependency-config");
async function getEnquirerPrompt() {
    const enquirer = await import('enquirer');
    // Handle both CommonJS and ESM exports
    return enquirer.prompt || enquirer.default?.prompt || enquirer;
}
async function promptForRuntimeName(availableRuntimes, existingRuntimeName, existingVisualName, skipDynamicRuntimeVisualPrompt) {
    const prompt = await getEnquirerPrompt();
    let runtimeName = existingRuntimeName;
    let visualName = existingVisualName;
    if (skipDynamicRuntimeVisualPrompt) {
        return { runtimeName, visualName };
    }
    if (!runtimeName) {
        const runtimeChoices = [
            { value: '', name: '(none)' },
            ...Object.keys(availableRuntimes).map(name => ({ name, value: name }))
        ];
        const response = await prompt({
            type: 'select',
            name: 'runtimeName',
            message: 'Select a runtime for this application (optional):',
            choices: runtimeChoices,
        });
        runtimeName = response.runtimeName;
        runtimeName = runtimeName === '(none)' ? '' : runtimeName;
    }
    if (!visualName && runtimeName && availableRuntimes[runtimeName]) {
        const availableVisuals = availableRuntimes[runtimeName].visuals;
        if (availableVisuals.length > 0) {
            const visualChoices = [
                { value: '', name: '(none)' },
                ...availableVisuals.map(name => ({ name, value: name }))
            ];
            const response = await prompt({
                type: 'select',
                name: 'visualName',
                message: 'Select a visual type to mount (optional):',
                choices: visualChoices,
            });
            visualName = response.visualName;
            visualName = visualName === '(none)' ? '' : visualName;
        }
    }
    return { runtimeName, visualName };
}
async function promptForHtmlPageTitle() {
    const prompt = await getEnquirerPrompt();
    const response = await prompt({
        type: 'input',
        name: 'htmlPageTitle',
        message: 'What should the HTML page title be?',
    });
    return response.htmlPageTitle;
}
async function promptForDependencies(_isPlayground) {
    const prompt = await getEnquirerPrompt();
    const choices = [
        { value: 'ds', label: 'Kaltura DS - Design System (requires GIT_TOKEN)' },
    ];
    const response = await prompt({
        type: 'multiselect',
        name: 'dependencies',
        message: 'Select dependencies to install (use space to select, enter to confirm):',
        choices: choices.map(c => ({ name: c.value, message: c.label })),
    });
    return response.dependencies;
}
async function addApplicationGenerator(tree, options) {
    // Validate iframe-with-post-messages is not supported
    if (options.servingType === 'iframe-with-post-messages') {
        throw new Error('iframe-with-post-messages serving type is not currently supported. Please choose a different serving type.');
    }
    const isPlayground = options.servingType === 'local-dev-playground';
    // Validate and read .unisphere configuration
    const unisphereConfig = (0, utils_1.validateUnisphereConfig)(tree);
    const promptResult = await promptForRuntimeName(unisphereConfig.runtimes, options.runtimeName || '', options.visualName || '', options.skipDynamicRuntimeVisualPrompt || false);
    const runtimeName = promptResult.runtimeName;
    const visualName = promptResult.visualName;
    if (!isPlayground && !options.htmlPageTitle) {
        options.htmlPageTitle = options.htmlPageTitle || await promptForHtmlPageTitle();
    }
    if (options.dependencies === undefined) {
        options.dependencies = await promptForDependencies(isPlayground);
    }
    const baseDependencies = ['react'];
    const selectedDependencies = [...baseDependencies, ...(options.dependencies || [])];
    // Validate runtime exists if runtimeName is provided
    if (runtimeName) {
        if (!(0, utils_1.checkIfRuntimeExists)(tree, runtimeName)) {
            throw new Error(`Runtime "${runtimeName}" does not exist, please check the available runtimes under 'unisphere/runtimes'`);
        }
    }
    // Extract environment variables
    const widgetName = unisphereConfig.name;
    let applicationName = options.name;
    if (isPlayground && !options.name.endsWith('-dev')) {
        applicationName += '-dev';
    }
    const applicationNameAsLowerDashCase = (0, devkit_1.names)(applicationName).fileName;
    const typesPackageInfo = (0, utils_1.findTypesOrCorePackageInfo)(tree);
    // Determine subdirectory based on serving type
    // local-dev-playground -> local/, other types -> server/
    const subdirectory = isPlayground ? 'local' : 'server';
    const projectRoot = `unisphere/applications/${subdirectory}/${applicationNameAsLowerDashCase}`;
    const hasDs = selectedDependencies.includes('ds');
    const templateVariables = {
        htmlPageTitle: options.servingType === 'local-dev-playground'
            ? `${runtimeName || 'Runtime'} - Local Dev Application`
            : options.htmlPageTitle,
        servingType: options.servingType,
        hasDs,
        ...(0, utils_1.createNameTransforms)(applicationNameAsLowerDashCase, 'applicationName'),
        ...(0, utils_1.createNameTransforms)(widgetName, 'widgetName'),
        ...(0, utils_1.createNameTransforms)(runtimeName, 'runtimeName'),
        ...(0, utils_1.createNameTransforms)(visualName, 'visualName'),
        tmpl: '',
        typesAlias: typesPackageInfo.alias,
        subdirectory,
        projectRoot,
    };
    // Check if the application already exists
    if (tree.exists(projectRoot)) {
        throw new Error(`Application "${applicationNameAsLowerDashCase}" already exists at ${projectRoot}.\n` +
            'Please choose a different application name or remove the existing application first.');
    }
    // Choose template based on serving type
    const templatePath = 'templates/default';
    // Generate files from templates
    (0, devkit_1.generateFiles)(tree, path.join(__dirname, templatePath), projectRoot, templateVariables);
    // For local-dev-playground apps, generate setup-local-runtimes.ts
    if (isPlayground) {
        const rawConfig = (0, devkit_1.readJson)(tree, '.unisphere');
        const experienceName = `unisphere.${rawConfig.type}.${rawConfig.name}`;
        const setupLocalRuntimesContent = `export function setupLocalRuntimes() {
  if (!process.env.LOCAL_RUNTIMES) return;

  const runtimes: Record<string, { token: string; baseEnvName: string }> = {};
  process.env.LOCAL_RUNTIMES.split(',').forEach((entry) => {
    const [name, port] = entry.split('@');
    if (name && port) {
      runtimes[name] = { token: port, baseEnvName: '' };
    }
  });

  const overrides = {
    baseEnvName: '',
    mode: 'integration',
    options: { verbose: 'inherit' },
    baseEnvScope: { core: 'inherit', presets: 'inherit' },
    runtimes: {
      '${experienceName}': runtimes,
    },
  };

  (window as any).unisphereRuntimeOverrides = btoa(JSON.stringify(overrides));
}
`;
        tree.write(path.join(projectRoot, 'src', 'setup-local-runtimes.ts'), setupLocalRuntimesContent);
    }
    // Install selected dependencies
    (0, dependency_config_1.installSelectedDependencies)(tree, selectedDependencies);
    // Update .unisphere configuration
    (0, utils_1.updateUnisphereConfig)(tree, 'applications', applicationNameAsLowerDashCase, {
        sourceRoot: projectRoot,
    });
    // Update tsconfig.base.json with path mapping
    const applicationPathKey = `unisphere-application-${applicationNameAsLowerDashCase}`;
    const applicationPathValue = `${projectRoot}/src/index.ts`;
    (0, utils_1.updateTsConfigPaths)(tree, applicationPathKey, applicationPathValue);
    const scriptName = `serve:${applicationNameAsLowerDashCase}`;
    const scriptCommand = runtimeName ?
        `concurrently "npx unisphere runtime serve ${runtimeName} --port 8400" "npx unisphere application serve ${applicationNameAsLowerDashCase} --port 4002"`
        : `npx unisphere application serve ${applicationNameAsLowerDashCase} --port 4002`;
    (0, utils_1.addScriptToRootPackageJson)(tree, scriptName, scriptCommand);
    await (0, devkit_1.formatFiles)(tree);
    // Return a function that will be executed after all file operations are complete
    return () => {
        (0, devkit_1.installPackagesTask)(tree, true);
        devkit_1.logger.info('');
        devkit_1.logger.info('✅ Application generated successfully!');
        devkit_1.logger.info('');
        devkit_1.logger.info(`🚀 Application Name: ${applicationNameAsLowerDashCase}`);
        devkit_1.logger.info(`🔧 Serving Type: ${options.servingType}`);
        devkit_1.logger.info(`📁 Location: ${projectRoot}`);
        devkit_1.logger.info('');
        devkit_1.logger.info(`📜 To run the application locally: npm run ${scriptName}`);
        devkit_1.logger.info('');
    };
}
exports.default = addApplicationGenerator;
