'use strict';
/**
 * @license Angular v22.0.0-next.10
 * (c) 2010-2026 Google LLC. https://angular.dev/
 * License: MIT
 */
'use strict';

require('@angular-devkit/core');
require('node:path/posix');
var project_paths = require('./project_paths-D2V-Uh2L.cjs');
var migrations = require('@angular/compiler-cli/private/migrations');
var ts = require('typescript');
var ng_decorators = require('./ng_decorators-IVztR9rk.cjs');
require('@angular/compiler-cli');
require('node:path');
var apply_import_manager = require('./apply_import_manager-CxA_YYgB.cjs');
var leading_space = require('./leading_space-BTPRV0wu.cjs');
require('@angular-devkit/schematics');
require('./project_tsconfig_paths-DkkMibv-.cjs');
require('./imports-CKV-ITqD.cjs');

class ChangeDetectionEagerMigration extends project_paths.TsurgeFunnelMigration {
    config;
    constructor(config = {}) {
        super();
        this.config = config;
    }
    async analyze(info) {
        const { sourceFiles, program } = info;
        const typeChecker = program.getTypeChecker();
        const replacements = [];
        const importManager = new migrations.ImportManager();
        const printer = ts.createPrinter();
        for (const sf of sourceFiles) {
            const file = project_paths.projectFile(sf, info);
            if (this.config.shouldMigrate && !this.config.shouldMigrate(file)) {
                continue;
            }
            ts.forEachChild(sf, (node) => {
                if (!ts.isClassDeclaration(node)) {
                    return;
                }
                const decorators = ng_decorators.getAngularDecorators(typeChecker, ts.getDecorators(node) || []);
                const componentDecorator = decorators.find((d) => d.name === 'Component' && d.moduleName === '@angular/core');
                if (!componentDecorator) {
                    return;
                }
                // The helper `getAngularDecorators` guarantees that `node` is `CallExpressionDecorator`.
                // So `componentDecorator.node.expression` is `ts.CallExpression`.
                const callExpression = componentDecorator.node.expression;
                if (callExpression.arguments.length !== 1 ||
                    !ts.isObjectLiteralExpression(callExpression.arguments[0])) {
                    return;
                }
                const metadata = callExpression.arguments[0];
                const changeDetectionProp = metadata.properties.find((p) => ts.isPropertyAssignment(p) &&
                    (ts.isIdentifier(p.name) || ts.isStringLiteral(p.name)) &&
                    p.name.text === 'changeDetection');
                if (!changeDetectionProp) {
                    // Property missing. Add it.
                    const changeDetectionStrategyExpr = importManager.addImport({
                        exportModuleSpecifier: '@angular/core',
                        exportSymbolName: 'ChangeDetectionStrategy',
                        requestedFile: sf,
                    });
                    // Print the identifier
                    const exprText = printer.printNode(ts.EmitHint.Unspecified, changeDetectionStrategyExpr, sf);
                    const properties = metadata.properties;
                    let insertPos;
                    let toInsert;
                    if (properties.length > 0) {
                        const lastProp = properties[properties.length - 1];
                        insertPos = lastProp.getStart();
                        toInsert = `changeDetection: ${exprText}.Eager,\n${leading_space.getLeadingLineWhitespaceOfNode(lastProp)}`;
                    }
                    else {
                        insertPos = metadata.getStart() + 1;
                        toInsert = `\n  changeDetection: ${exprText}.Eager\n`;
                    }
                    replacements.push(new project_paths.Replacement(project_paths.projectFile(sf, info), new project_paths.TextUpdate({
                        position: insertPos,
                        end: insertPos,
                        toInsert: toInsert,
                    })));
                    return;
                }
                // Check if explicitly set to Default.
                if (!ts.isPropertyAccessExpression(changeDetectionProp.initializer)) {
                    return;
                }
                const initializer = changeDetectionProp.initializer;
                // Best effort check for ChangeDetectionStrategy.Default
                if (!ts.isIdentifier(initializer.expression) || initializer.name.text !== 'Default') {
                    return;
                }
                // Verify it is indeed ChangeDetectionStrategy.
                // We can check if the symbol of the expression is imported from @angular/core and named ChangeDetectionStrategy.
                const symbol = typeChecker.getSymbolAtLocation(initializer.expression);
                if (!symbol || !symbol.declarations || symbol.declarations.length === 0) {
                    return;
                }
                const declaration = symbol.declarations[0];
                if (!ts.isImportSpecifier(declaration)) {
                    return;
                }
                const propertyName = declaration.propertyName?.text ?? declaration.name.text;
                const importDecl = declaration.parent.parent.parent;
                if (!ts.isImportDeclaration(importDecl) ||
                    !ts.isStringLiteral(importDecl.moduleSpecifier) ||
                    importDecl.moduleSpecifier.text !== '@angular/core' ||
                    propertyName !== 'ChangeDetectionStrategy') {
                    return;
                }
                replacements.push(new project_paths.Replacement(project_paths.projectFile(sf, info), new project_paths.TextUpdate({
                    position: initializer.name.getStart(),
                    end: initializer.name.getEnd(),
                    toInsert: 'Eager',
                })));
            });
        }
        apply_import_manager.applyImportManagerChanges(importManager, replacements, sourceFiles, info);
        return project_paths.confirmAsSerializable({
            replacements,
        });
    }
    async combine(unitA, unitB) {
        return project_paths.confirmAsSerializable({
            replacements: [...unitA.replacements, ...unitB.replacements],
        });
    }
    async globalMeta(combinedData) {
        return project_paths.confirmAsSerializable(combinedData);
    }
    async stats(globalMetadata) {
        return project_paths.confirmAsSerializable({});
    }
    async migrate(globalData) {
        return { replacements: globalData.replacements };
    }
}

function migrate(options) {
    return async (tree, context) => {
        await project_paths.runMigrationInDevkit({
            tree,
            getMigration: (fs) => new ChangeDetectionEagerMigration(),
        });
    };
}

exports.migrate = migrate;
