"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.addPackageGenerator = addPackageGenerator;
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.packageName || options.packageName.trim() === '') {
        throw new Error(`Missing required option: 'packageName'\n` +
            `  Description: The name of the package to create\n` +
            `  Type: string\n` +
            `  Pattern: ^[a-zA-Z][a-zA-Z0-9\\-\\s]*$\n` +
            `  Example: nx g @unisphere/nx:add-package --packageName=my-package --scope=local`);
    }
    const namePattern = /^[a-zA-Z][a-zA-Z0-9\-\s]*$/;
    if (!namePattern.test(options.packageName)) {
        throw new Error(`Invalid value '${options.packageName}' for option 'packageName'\n` +
            `  Pattern: ^[a-zA-Z][a-zA-Z0-9\\-\\s]*$\n` +
            `  Received: ${options.packageName}`);
    }
    if (!options.scope) {
        throw new Error(`Missing required option: 'scope'\n` +
            `  Description: The distribution scope of the package\n` +
            `  Allowed values: local, kaltura-corp, unisphere, kaltura-ui, kaltura-apps, kaltura-sdk\n` +
            `  Example: nx g @unisphere/nx:add-package --packageName=my-package --scope=local`);
    }
    const allowedScopes = ['local', 'kaltura-corp', 'unisphere', 'kaltura-ui', 'kaltura-apps', 'kaltura-sdk'];
    if (!allowedScopes.includes(options.scope)) {
        throw new Error(`Invalid value '${options.scope}' for option 'scope'\n` +
            `  Allowed values: ${allowedScopes.join(', ')}\n` +
            `  Received: ${options.scope}`);
    }
    if (options.dependencies) {
        const allowedDeps = ['react', 'ds', 'mui'];
        const invalidDeps = options.dependencies.filter(dep => !allowedDeps.includes(dep));
        if (invalidDeps.length > 0) {
            throw new Error(`Invalid dependencies: ${invalidDeps.join(', ')}\n` +
                `  Allowed values: ${allowedDeps.join(', ')}`);
        }
    }
}
/**
 * Resolves the @unisphere/runtime version from the workspace's root package.json
 * Falls back to a default version if not found
 */
function resolveUnisphereRuntimeVersion(tree) {
    const defaultVersion = '^1.54.1';
    try {
        // Try to read the workspace root package.json
        const packageJsonPath = 'package.json';
        if (!tree.exists(packageJsonPath)) {
            devkit_1.logger.warn(`Could not find package.json at workspace root. Using default @unisphere/runtime version: ${defaultVersion}`);
            return defaultVersion;
        }
        const packageJson = (0, devkit_1.readJson)(tree, packageJsonPath);
        // Check in dependencies
        if (packageJson.dependencies?.['@unisphere/runtime']) {
            return packageJson.dependencies['@unisphere/runtime'];
        }
        // Check in devDependencies
        if (packageJson.devDependencies?.['@unisphere/runtime']) {
            return packageJson.devDependencies['@unisphere/runtime'];
        }
        devkit_1.logger.warn(`@unisphere/runtime not found in workspace package.json. Using default version: ${defaultVersion}`);
        return defaultVersion;
    }
    catch (error) {
        devkit_1.logger.warn(`Error reading package.json: ${error}. Using default @unisphere/runtime version: ${defaultVersion}`);
        return defaultVersion;
    }
}
async function addPackageGenerator(tree, options) {
    // Validate options
    validateOptions(options);
    // Validate and read .unisphere configuration
    const unisphereConfig = (0, utils_1.validateUnisphereConfig)(tree);
    // Validate dependencies
    const selectedDependencies = options.dependencies || [];
    (0, dependency_config_1.validateGitToken)(selectedDependencies);
    // Validate and correct package naming for React/DS dependencies
    let userInputPackageName = (0, devkit_1.names)(options.packageName).fileName;
    userInputPackageName = (0, dependency_config_1.validateReactNaming)(userInputPackageName, selectedDependencies);
    // Extract environment variables
    const companyName = unisphereConfig.company;
    const experienceName = unisphereConfig.name;
    // Calculate packageJsonName based on scope and names
    let packageJsonName;
    if (experienceName === userInputPackageName) {
        packageJsonName = userInputPackageName;
    }
    else {
        packageJsonName = experienceName + `-${userInputPackageName}`;
    }
    const scopeToPrefixMap = {
        'unisphere': '@unisphere/',
        'kaltura-corp': '@kaltura-corp/unisphere-',
        'kaltura-ui': '@kaltura-ui/',
        'kaltura-apps': '@kaltura-apps/',
        'kaltura-sdk': '@kaltura-sdk/',
        'local': '@local/',
    };
    const prefix = scopeToPrefixMap[options.scope];
    packageJsonName = prefix + packageJsonName;
    const transformedPackageName = (0, devkit_1.names)(userInputPackageName);
    const githubUrl = `https://github.com/${companyName}/${experienceName}`;
    // Resolve @unisphere/runtime version from workspace package.json
    const unisphereRuntimeVersion = resolveUnisphereRuntimeVersion(tree);
    // Determine which dependencies are selected
    const hasDs = selectedDependencies.includes('ds');
    const hasReact = selectedDependencies.includes('react') || hasDs;
    // Determine subdirectory based on scope (schema v2.0.0+)
    const subdirectory = (0, utils_1.getSubdirectoryFromScope)(options.scope);
    const projectRoot = `unisphere/packages/${subdirectory}/${userInputPackageName}`;
    // Prepare template variables
    const templateVariables = {
        scope: options.scope,
        githubUrl,
        companyName,
        unisphereRuntimeVersion,
        hasDs,
        hasReact,
        subdirectory,
        ...(0, utils_1.createNameTransforms)(userInputPackageName, 'packageName'),
        ...(0, utils_1.createNameTransforms)(experienceName, 'experienceName'),
        ...(0, utils_1.createNameTransforms)(packageJsonName, 'packageJsonName'),
        ...transformedPackageName,
        tmpl: '',
    };
    // Check if name already exists across all element types in .unisphere
    (0, utils_1.validateElementNameUnique)(tree, userInputPackageName, 'packages');
    // Check if the project already exists on filesystem
    if (tree.exists(projectRoot)) {
        throw new Error(`Package "${userInputPackageName}" already exists at ${projectRoot}.\n` +
            'Please choose a different package name or remove the existing package first.');
    }
    // Generate files from templates (project.json.template will define the project)
    (0, devkit_1.generateFiles)(tree, path.join(__dirname, 'templates/new-package'), projectRoot, templateVariables);
    // Update .unisphere configuration
    (0, utils_1.updateUnisphereConfig)(tree, 'packages', userInputPackageName, {
        sourceRoot: `unisphere/packages/${subdirectory}/${userInputPackageName}`,
        scope: 'widget',
    });
    // Update tsconfig.base.json with path mapping
    (0, utils_1.updateTsConfigPaths)(tree, packageJsonName, `unisphere/packages/${subdirectory}/${userInputPackageName}/src/index.ts`);
    // 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('✅ Package generated successfully!');
        devkit_1.logger.info('');
        devkit_1.logger.info(`📦 Package Name: ${userInputPackageName}`);
        devkit_1.logger.info(`🏷️  Full Package Name: ${packageJsonName}`);
        devkit_1.logger.info(`📁 Location: ${projectRoot}`);
        devkit_1.logger.info(`🔧 Scope: ${options.scope}`);
        devkit_1.logger.info('');
    };
}
exports.default = addPackageGenerator;
