/**
 * Copyright (c) Siemens 2016 - 2026
 * SPDX-License-Identifier: MIT
 */
import { normalize } from '@angular-devkit/core';
import { SchematicsException } from '@angular-devkit/schematics';
import { allTargetOptions, allWorkspaceTargets, getWorkspace } from '@schematics/angular/utility/workspace';
import { dirname, isAbsolute, relative, resolve } from 'path/posix';
import * as ts from 'typescript';
import { createTreeAwareCompilerHost } from './ts-compiler-host.js';
import { parseTsconfigFile } from './ts-utils.js';
export const getGlobalStyles = async (tree) => {
    const globalStyles = new Set();
    for (const [name, target] of allWorkspaceTargets(await getWorkspace(tree))) {
        if (['build', 'test'].includes(name)) {
            for (const [, opt] of allTargetOptions(target)) {
                if (opt.styles && Array.isArray(opt.styles)) {
                    opt.styles.forEach((style) => {
                        if (typeof style === 'string') {
                            globalStyles.add(normalize(style));
                        }
                    });
                }
            }
        }
    }
    return [...globalStyles];
};
export const getTsConfigPaths = async (tree) => {
    const buildPaths = new Set();
    for (const [name, target] of allWorkspaceTargets(await getWorkspace(tree))) {
        if (['build', 'test'].includes(name)) {
            for (const [, opt] of allTargetOptions(target)) {
                if (typeof opt?.tsConfig === 'string') {
                    const tsConfig = opt.tsConfig;
                    if (tree.exists(tsConfig)) {
                        buildPaths.add(normalize(tsConfig));
                    }
                }
            }
        }
    }
    return [...buildPaths];
};
export async function* createPrograms(tree) {
    const basePath = normalize(process.cwd());
    // Wrap the tree to force full paths since parsing the TypeScript config requires full paths.
    const tsConfigs = await getTsConfigPaths(tree);
    if (!tsConfigs.length) {
        throw new SchematicsException('Could not find any tsconfig file. Cannot run the migration.');
    }
    for (const configPath of tsConfigs) {
        const tsConfigPath = resolve(basePath, configPath);
        const config = parseTsconfigFile(tsConfigPath, dirname(tsConfigPath), tree);
        yield ts.createProgram({
            options: config.options,
            rootNames: config.fileNames,
            host: createTreeAwareCompilerHost(tree, config.options)
        });
    }
}
export async function* discoverSourceFiles(tree, context, projectPath, extension = '.ts') {
    const basePath = normalize(process.cwd());
    const tsConfigs = await getTsConfigPaths(tree);
    if (!tsConfigs.length) {
        throw new SchematicsException('Could not find any tsconfig file. Cannot run the migration.');
    }
    context.logger.debug(`Found tsconfig files: ${tsConfigs.join(', ')}`);
    const normalizedProjectPath = projectPath
        ? normalize(isAbsolute(projectPath) ? projectPath : resolve(basePath, projectPath))
        : undefined;
    const emitted = new Set();
    for await (const program of createPrograms(tree)) {
        const typeChecker = program.getTypeChecker();
        for (const sourceFile of program.getSourceFiles()) {
            if (sourceFile.isDeclarationFile) {
                continue;
            }
            const absolutePath = normalize(sourceFile.fileName);
            if (!absolutePath.endsWith(extension)) {
                continue;
            }
            if (normalizedProjectPath && !absolutePath.startsWith(normalizedProjectPath)) {
                continue;
            }
            const relativePath = normalize(relative(basePath, absolutePath));
            if (!tree.exists(relativePath)) {
                continue;
            }
            if (emitted.has(relativePath)) {
                continue;
            }
            emitted.add(relativePath);
            yield {
                path: relativePath,
                sourceFile,
                typeChecker
            };
        }
    }
}
