"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.addDocumentationGenerator = addDocumentationGenerator;
const tslib_1 = require("tslib");
const devkit_1 = require("@nx/devkit");
const child_process_1 = require("child_process");
const path = tslib_1.__importStar(require("path"));
const utils_1 = require("../utils");
const discover_typedoc_plugins_1 = require("./discover-typedoc-plugins");
function validateOptions(options) {
    if (options.name) {
        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.isExperienceLevel && options.subName) {
        const subNamePattern = /^[a-zA-Z][a-zA-Z0-9\-\s]*$/;
        if (!subNamePattern.test(options.subName)) {
            throw new Error(`Invalid value '${options.subName}' for option 'subName'\n` +
                `  Pattern: ^[a-zA-Z][a-zA-Z0-9\\-\\s]*$\n` +
                `  Received: ${options.subName}`);
        }
    }
    if (!options.isExperienceLevel && !options.subName) {
        throw new Error(`Missing required option: 'subName'\n` +
            `  Description: Sub-name for the documentation site (used when not experience-level)\n` +
            `  Type: string\n` +
            `  Pattern: ^[a-zA-Z][a-zA-Z0-9\\-\\s]*$\n` +
            `  Example: nx g @unisphere/nx:add-documentation --subName=api-docs`);
    }
}
async function addDocumentationGenerator(tree, options) {
    // Validate options
    validateOptions(options);
    // Validate .unisphere configuration exists
    const unisphereConfig = (0, utils_1.validateUnisphereConfig)(tree);
    // Check workspace pattern for documentation apps
    const rootPackageJsonPath = 'package.json';
    if (tree.exists(rootPackageJsonPath)) {
        const packageJson = JSON.parse(tree.read(rootPackageJsonPath, 'utf-8') || '{}');
        const workspaces = packageJson.workspaces || [];
        // Check if using the old catch-all pattern that doesn't work with documentation apps
        const hasCatchAllPattern = workspaces.includes('unisphere/**');
        if (hasCatchAllPattern) {
            throw new Error('Documentation sites require @unisphere/nx version 3.1.0 or higher.\n\n' +
                'Your workspace is using an old npm workspaces pattern that prevents documentation sites ' +
                'from having their own node_modules.\n\n' +
                'Please upgrade by running:\n' +
                '  npx nx migrate @unisphere/nx@latest\n' +
                '  npx nx migrate --run-migrations\n\n' +
                'This will update your workspace pattern to support documentation sites.');
        }
    }
    // Resolve experience name: use --name flag, or auto-resolve from .unisphere config
    const documentationName = options.name || unisphereConfig.name;
    const documentationNameAsLowerDashCase = (0, devkit_1.names)(documentationName).fileName;
    devkit_1.logger.info(`Using experience name: ${documentationNameAsLowerDashCase}`);
    // Build the full documentation name
    const subNameAsLowerDashCase = options.subName ? (0, devkit_1.names)(options.subName).fileName : null;
    const fullDocumentationName = subNameAsLowerDashCase
        ? `${documentationNameAsLowerDashCase}-${subNameAsLowerDashCase}`
        : documentationNameAsLowerDashCase;
    const projectRoot = `unisphere/documentation/${fullDocumentationName}`;
    // Check if the documentation site already exists
    if (tree.exists(projectRoot)) {
        throw new Error(`Documentation site "${fullDocumentationName}" already exists at ${projectRoot}.\n` +
            'Please choose a different name or remove the existing documentation site first.');
    }
    // Discover publishable packages for typedoc plugin auto-configuration
    const discoveredPlugins = (0, discover_typedoc_plugins_1.discoverTypedocPlugins)(tree, projectRoot);
    if (discoveredPlugins.length > 0) {
        devkit_1.logger.info(`📚 Auto-discovered ${discoveredPlugins.length} package(s) for TypeDoc API documentation`);
    }
    // Generate files from template
    const templateVariables = {
        ...(0, utils_1.createNameTransforms)(fullDocumentationName, 'documentationName'),
        ...(0, utils_1.createNameTransforms)(documentationNameAsLowerDashCase, 'experienceName'),
        hasSubName: !!subNameAsLowerDashCase,
        subNameKebab: subNameAsLowerDashCase || '',
        typedocPluginsConfig: (0, discover_typedoc_plugins_1.buildTypedocPluginsCode)(discoveredPlugins),
        tmpl: '',
    };
    (0, devkit_1.generateFiles)(tree, path.join(__dirname, 'templates'), projectRoot, templateVariables);
    // Update .unisphere configuration
    (0, utils_1.updateUnisphereConfig)(tree, 'documentation', fullDocumentationName, {
        sourceRoot: projectRoot,
    });
    // Add documentation folder to .nxignore to prevent NX from scanning it
    // Docusaurus has its own node_modules which can slow down NX
    const nxIgnorePath = '.nxignore';
    const ignoreEntry = `${projectRoot}/node_modules`;
    let nxIgnoreContent = '';
    if (tree.exists(nxIgnorePath)) {
        nxIgnoreContent = tree.read(nxIgnorePath, 'utf-8') || '';
    }
    if (!nxIgnoreContent.includes(ignoreEntry)) {
        const newContent = nxIgnoreContent
            ? `${nxIgnoreContent.trimEnd()}\n\n# Documentation site (Docusaurus) - has its own node_modules\n${ignoreEntry}\n`
            : `# Documentation site (Docusaurus) - has its own node_modules\n${ignoreEntry}\n`;
        tree.write(nxIgnorePath, newContent);
    }
    // Copy .npmrc from workspace root so npm install can authenticate with private registries
    const npmrcPath = '.npmrc';
    if (tree.exists(npmrcPath)) {
        const npmrcContent = tree.read(npmrcPath, 'utf-8');
        if (npmrcContent) {
            tree.write(`${projectRoot}/.npmrc`, npmrcContent);
        }
    }
    await (0, devkit_1.formatFiles)(tree);
    devkit_1.logger.info('');
    devkit_1.logger.info('Documentation site generated successfully!');
    devkit_1.logger.info('');
    devkit_1.logger.info(`Name: ${fullDocumentationName}`);
    devkit_1.logger.info(`Type: Documentation Site (Docusaurus)`);
    devkit_1.logger.info(`Location: ${projectRoot}`);
    devkit_1.logger.info('');
    if (options.skipInstall) {
        devkit_1.logger.info('Skipping npm install (--skip-install).');
        devkit_1.logger.info('');
        devkit_1.logger.info(`To install: cd ${projectRoot} && npm install`);
        devkit_1.logger.info(`To serve:   npx unisphere documentation serve ${fullDocumentationName}`);
        devkit_1.logger.info(`To build:   npx unisphere documentation build ${fullDocumentationName}`);
        devkit_1.logger.info('');
        return;
    }
    // Return callback to run npm install after the tree is flushed to disk
    const workspaceRoot = tree.root;
    return () => {
        const fullProjectPath = path.join(workspaceRoot, projectRoot);
        devkit_1.logger.info('Installing dependencies...');
        devkit_1.logger.info('');
        (0, child_process_1.execSync)('npm install', {
            cwd: fullProjectPath,
            stdio: 'inherit',
        });
        devkit_1.logger.info('');
        devkit_1.logger.info(`To serve: npx unisphere documentation serve ${fullDocumentationName}`);
        devkit_1.logger.info(`To build: npx unisphere documentation build ${fullDocumentationName}`);
        devkit_1.logger.info('');
    };
}
exports.default = addDocumentationGenerator;
