"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.addRuntimeGenerator = addRuntimeGenerator;
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");
function validateOptions(options) {
    if (!options.name || options.name.trim() === '') {
        throw new Error(`Missing required option: 'name'\n` +
            `  Description: The name of the runtime to create\n` +
            `  Type: string\n` +
            `  Pattern: ^[a-zA-Z][a-zA-Z0-9\\-\\s]*$\n` +
            `  Example: nx g @unisphere/nx:add-runtime --name=my-runtime --consumer=external`);
    }
    const namePattern = /^[a-zA-Z][a-zA-Z0-9\-\s]*$/;
    if (!namePattern.test(options.name)) {
        throw new Error(`Invalid value '${options.name}' for option 'name'\n` +
            `  Pattern: ^[a-zA-Z][a-zA-Z0-9\\-\\s]*$\n` +
            `  Received: ${options.name}`);
    }
    if (!options.consumer) {
        throw new Error(`Missing required option: 'consumer'\n` +
            `  Description: Is this runtime loaded from within the same experience or by an external consumer?\n` +
            `  Allowed values: external, internal\n` +
            `  Example: nx g @unisphere/nx:add-runtime --name=my-runtime --consumer=external`);
    }
    if (!['external', 'internal'].includes(options.consumer)) {
        throw new Error(`Invalid value '${options.consumer}' for option 'consumer'\n` +
            `  Allowed values: external, internal\n` +
            `  Received: ${options.consumer}`);
    }
}
function updateTypesIndexExport(tree, runtimeName, basePath) {
    const indexPath = `${basePath}/src/index.ts`;
    if (!tree.exists(indexPath)) {
        throw new Error(`Index file not found at ${indexPath}`);
    }
    const currentContent = tree.read(indexPath, 'utf-8');
    if (!currentContent) {
        throw new Error(`Failed to read content from ${indexPath}`);
    }
    const exportLine = `export * from './lib/${runtimeName}-runtime';`;
    // Check if the export already exists
    if (currentContent.includes(exportLine)) {
        return; // Already exported
    }
    // Add the export at the end of the file
    const updatedContent = currentContent + '\n' + exportLine;
    tree.write(indexPath, updatedContent);
}
async function addRuntimeGenerator(tree, options) {
    validateOptions(options);
    // Normalize consumer option - Nx list prompts may return string labels instead of boolean values
    let isExternal = options?.consumer === 'external' ? true : false;
    // Validate and read .unisphere configuration
    const unisphereConfig = (0, utils_1.validateUnisphereConfig)(tree);
    // Validate dependencies
    const selectedDependencies = options.dependencies || [];
    // Extract environment variables
    const companyName = unisphereConfig.company;
    const widgetName = unisphereConfig.name;
    // Validate and correct runtime naming for React/DS dependencies
    let userInputRuntimeName = (0, devkit_1.names)(options.name).fileName;
    // Find types package (or fallback to core)
    const typesPackageInfo = (0, utils_1.findTypesOrCorePackageInfo)(tree);
    const analyticsAppId = options.analyticsAppId;
    // Prepare template variables
    const templateVariables = {
        companyName,
        analyticsAppId,
        typesAlias: typesPackageInfo.alias,
        // Add all name transformations
        ...(0, utils_1.createNameTransforms)(userInputRuntimeName, 'runtimeName'),
        ...(0, utils_1.createNameTransforms)(widgetName, 'widgetName'),
        tmpl: '',
    };
    const projectRoot = `unisphere/runtimes/${userInputRuntimeName}`;
    // Check if the runtime already exists
    if (tree.exists(projectRoot)) {
        throw new Error(`Runtime "${userInputRuntimeName}" already exists at ${projectRoot}.\n` +
            'Please choose a different runtime name or remove the existing runtime first.');
    }
    // Check if the runtime types file already exists in types/core package
    const runtimeTypesPath = `${typesPackageInfo.basePath}/src/lib/${userInputRuntimeName}-runtime/runtime-types.ts`;
    if (tree.exists(runtimeTypesPath)) {
        const packageName = typesPackageInfo.hasTypesPackage ? 'types' : 'core';
        throw new Error(`Runtime types file "${userInputRuntimeName}-runtime/runtime-types.ts" already exists in ${packageName} package.\n` +
            'Please choose a different runtime name or remove the existing file first.');
    }
    // Generate files from templates for the runtime
    (0, devkit_1.generateFiles)(tree, path.join(__dirname, 'templates/new-runtime'), projectRoot, templateVariables);
    // Generate the runtime types file in the types/core package using template
    (0, devkit_1.generateFiles)(tree, path.join(__dirname, 'templates/types-templates'), `${typesPackageInfo.basePath}/src/lib`, templateVariables);
    // Update types package index.ts to export the new runtime types
    updateTypesIndexExport(tree, userInputRuntimeName, typesPackageInfo.basePath);
    // Update .unisphere configuration
    (0, utils_1.updateUnisphereConfig)(tree, 'runtimes', userInputRuntimeName, {
        sourceRoot: `unisphere/runtimes/${userInputRuntimeName}`,
        distributionChannel: 'unisphere',
    });
    // Update tsconfig.base.json with path mapping
    const runtimePathKey = `unisphere-runtime-${userInputRuntimeName}`;
    const runtimePathValue = `unisphere/runtimes/${userInputRuntimeName}/src/index.ts`;
    (0, utils_1.updateTsConfigPaths)(tree, runtimePathKey, runtimePathValue);
    // Install selected dependencies
    (0, dependency_config_1.installSelectedDependencies)(tree, selectedDependencies);
    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('✅ Runtime generated successfully!');
        devkit_1.logger.info('');
        devkit_1.logger.info(`🚀 Runtime Name: ${userInputRuntimeName}`);
        devkit_1.logger.info(`📁 Location: ${projectRoot}`);
        if (analyticsAppId) {
            devkit_1.logger.info(`📊 Analytics App ID: ${analyticsAppId}`);
        }
        devkit_1.logger.info(`🔧 Consumer: ${isExternal ? 'External' : 'Internal'}`);
        devkit_1.logger.info('');
        devkit_1.logger.info('📝 Next steps:');
        devkit_1.logger.info(`   1. Add a visual: nx g @unisphere/nx:add-visual --runtimeName=${userInputRuntimeName}`);
        devkit_1.logger.info(`   2. Add a dev app: nx g @unisphere/nx:add-application --name=${userInputRuntimeName}-dev --runtimeName=${userInputRuntimeName}`);
        devkit_1.logger.info('');
    };
}
exports.default = addRuntimeGenerator;
