"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.makeCreateNodesForGradleConfigFile = exports.createNodesV2 = void 0;
exports.writeTargetsToCache = writeTargetsToCache;
const devkit_1 = require("@nx/devkit");
const calculate_hash_for_create_nodes_1 = require("@nx/devkit/src/utils/calculate-hash-for-create-nodes");
const node_fs_1 = require("node:fs");
const node_path_1 = require("node:path");
const cache_directory_1 = require("nx/src/utils/cache-directory");
const file_hasher_1 = require("nx/src/hasher/file-hasher");
const split_config_files_1 = require("../utils/split-config-files");
const get_project_graph_from_gradle_plugin_1 = require("./utils/get-project-graph-from-gradle-plugin");
const gradle_plugin_options_1 = require("./utils/gradle-plugin-options");
function readProjectsCache(cachePath) {
    return (0, node_fs_1.existsSync)(cachePath) ? (0, devkit_1.readJsonFile)(cachePath) : {};
}
/**
 * Strips nxConfig from project and all targets, returning only Gradle-detected configuration.
 */
function stripNxConfig(project) {
    const { nxConfig, targets, ...rest } = project;
    const cleanedTargets = {};
    if (targets) {
        for (const [targetName, target] of Object.entries(targets)) {
            const { nxConfig: targetNxConfig, ...targetRest } = target;
            cleanedTargets[targetName] = targetRest;
        }
    }
    return {
        ...rest,
        targets: cleanedTargets,
    };
}
/**
 * Extracts only nxConfig properties from project and targets.
 * Returns undefined if no nxConfig exists.
 */
function extractNxConfigOnly(project) {
    const projectWithNxConfig = project;
    const projectLevelNxConfig = projectWithNxConfig.nxConfig;
    const targetsWithNxConfig = {};
    let hasAnyNxConfig = false;
    // Extract target-level nxConfig
    if (project.targets) {
        for (const [targetName, target] of Object.entries(project.targets)) {
            const targetNxConfig = target.nxConfig;
            if (targetNxConfig && Object.keys(targetNxConfig).length > 0) {
                targetsWithNxConfig[targetName] = targetNxConfig;
                hasAnyNxConfig = true;
            }
        }
    }
    // Check if we have project-level nxConfig
    if (projectLevelNxConfig && Object.keys(projectLevelNxConfig).length > 0) {
        hasAnyNxConfig = true;
    }
    if (!hasAnyNxConfig) {
        return undefined;
    }
    // Build result with only nxConfig properties
    let result = {};
    // Merge project-level nxConfig into root
    if (projectLevelNxConfig) {
        result = {
            ...projectLevelNxConfig,
        };
    }
    // Add target-level nxConfig if any exist
    if (Object.keys(targetsWithNxConfig).length > 0) {
        result.targets = targetsWithNxConfig;
    }
    return result;
}
function writeTargetsToCache(cachePath, results) {
    (0, devkit_1.writeJsonFile)(cachePath, results);
}
exports.createNodesV2 = [
    split_config_files_1.gradleConfigAndTestGlob,
    async (files, options, context) => {
        const { buildFiles: buildFilesFromSplitConfigFiles, gradlewFiles } = (0, split_config_files_1.splitConfigFiles)(files);
        const optionsHash = (0, file_hasher_1.hashObject)(options);
        const cachePath = (0, node_path_1.join)(cache_directory_1.workspaceDataDirectory, `gradle-${optionsHash}.hash`);
        const projectsCache = readProjectsCache(cachePath);
        await (0, get_project_graph_from_gradle_plugin_1.populateProjectGraph)(context.workspaceRoot, gradlewFiles.map((f) => (0, node_path_1.join)(context.workspaceRoot, f)), options);
        const report = (0, get_project_graph_from_gradle_plugin_1.getCurrentProjectGraphReport)();
        const { nodes, externalNodes = {}, buildFiles = [] } = report;
        // Combine buildFilesFromSplitConfigFiles and buildFiles, making each value distinct
        const allBuildFiles = Array.from(new Set([...buildFilesFromSplitConfigFiles, ...buildFiles]));
        try {
            const results = [];
            const normalizedOptions = (0, gradle_plugin_options_1.normalizeOptions)(options);
            for (const gradleFilePath of allBuildFiles) {
                const projectRoot = (0, node_path_1.dirname)(gradleFilePath);
                const hash = await (0, calculate_hash_for_create_nodes_1.calculateHashForCreateNodes)(projectRoot, normalizedOptions ?? {}, context);
                // Get project from cache or nodes
                projectsCache[hash] ??=
                    nodes[projectRoot] ?? nodes[(0, node_path_1.join)(devkit_1.workspaceRoot, projectRoot)];
                const project = projectsCache[hash];
                if (!project) {
                    continue;
                }
                const normalizedProjectRoot = (0, devkit_1.normalizePath)(projectRoot);
                // Result 1: Gradle-detected configuration (without nxConfig)
                const gradleConfig = stripNxConfig(project);
                gradleConfig.root = normalizedProjectRoot;
                results.push([
                    gradleFilePath,
                    {
                        projects: {
                            [normalizedProjectRoot]: gradleConfig,
                        },
                        externalNodes: externalNodes,
                    },
                ]);
                // Result 2: nxConfig-only configuration (if exists)
                const nxConfigOnly = extractNxConfigOnly(project);
                if (nxConfigOnly) {
                    nxConfigOnly.root = normalizedProjectRoot;
                    results.push([
                        gradleFilePath,
                        {
                            projects: {
                                [normalizedProjectRoot]: nxConfigOnly,
                            },
                        },
                    ]);
                }
            }
            return results;
        }
        finally {
            writeTargetsToCache(cachePath, projectsCache);
        }
    },
];
const makeCreateNodesForGradleConfigFile = (projects, projectsCache = {}, externalNodes = {}) => async (gradleFilePath, options, context) => {
    const projectRoot = (0, node_path_1.dirname)(gradleFilePath);
    options = (0, gradle_plugin_options_1.normalizeOptions)(options);
    const hash = await (0, calculate_hash_for_create_nodes_1.calculateHashForCreateNodes)(projectRoot, options ?? {}, context);
    projectsCache[hash] ??=
        projects[projectRoot] ?? projects[(0, node_path_1.join)(devkit_1.workspaceRoot, projectRoot)];
    const project = projectsCache[hash];
    if (!project) {
        return {};
    }
    const normalizedProjectRoot = (0, devkit_1.normalizePath)(projectRoot);
    project.root = normalizedProjectRoot;
    return {
        projects: {
            [normalizedProjectRoot]: project,
        },
        externalNodes: externalNodes,
    };
};
exports.makeCreateNodesForGradleConfigFile = makeCreateNodesForGradleConfigFile;
