using System.IO;
using System.Linq;
using System.Collections.Generic;
using IntelligentProjectAnalyzer.Analyzer;

// All using statements now refer to the new data-only class
using static IntelligentProjectAnalyzer.Editor.DependencyBuilderData;

namespace IntelligentProjectAnalyzer.Editor
{
    /// <summary>
    /// Executes the CPU-intensive analysis on a background thread to avoid freezing the editor.
    /// </summary>
    public static class BackgroundAnalyzer
    {
        /// <summary>
        /// Runs the full dependency analysis on a collection of assets.
        /// </summary>
        /// <param name="allMetadata">A list containing metadata for all assets to be analyzed.</param>
        /// <param name="roslynSetupData">The setup data required for Roslyn analysis.</param>
        /// <returns>A list of analysis results, one for each processed asset.</returns>
        public static List<AssetMetadata> RunAnalysis(List<AssetMetadata> allMetadata, RoslynSetupData roslynSetupData)
        {
            // Initialize the Roslyn analyzer with all the necessary data.
            var roslynAnalyzer = new RoslynTypeDependencyAnalyzer(roslynSetupData.SourceFiles, roslynSetupData.References, roslynSetupData.PreprocessorSymbols, roslynSetupData.SystemTypePrefixes);

            // --- IMPORTANT ---
            // First, run analysis on ALL script types to build the complete, internal dependency tree in the analyzer.
            var allScriptTypes = roslynAnalyzer.TypeToPathMap.Keys;
            roslynAnalyzer.AnalyzeTypeDependenciesForFile(allScriptTypes);

            // Now, iterate through our assets and populate the script dependencies.
            foreach (var metadata in allMetadata)
            {
                // We only need to run Roslyn analysis for scripts.
                // Prefabs and SOs have their direct dependencies already.
                if (metadata is ScriptMetadata scriptMetadata)
                {
                    ProcessScript(scriptMetadata, roslynAnalyzer, roslynSetupData.TypeToGuidMap);
                }
            }
            return allMetadata;
        }

        /// <summary>
        /// Processes a single script to find all its recursive dependencies.
        /// </summary>
        private static void ProcessScript(ScriptMetadata metadata, RoslynTypeDependencyAnalyzer analyzer, IReadOnlyDictionary<string, string> typeToGuidMap)
        {
            // Get all types defined within this specific script file.
            var typesInFile = analyzer.TypeToPathMap
                .Where(pair => Path.GetFullPath(pair.Value).Replace('\\', '/') == metadata.FullPath)
                .Select(pair => pair.Key);

            var allDependenciesInFile = new HashSet<string>();

            foreach (var typeName in typesInFile)
            {
                // For each type, get its complete, recursive list of dependencies from the analyzer's pre-built tree.
                var dependenciesForType = analyzer.GetRecursiveDependencies(typeName);
                foreach (var dep in dependenciesForType)
                {
                    allDependenciesInFile.Add(dep);
                }
            }

            // Now, convert the dependency type names back to GUIDs and add them to the metadata object.
            foreach (var depName in allDependenciesInFile)
            {
                if (typeToGuidMap.TryGetValue(depName, out var depGuid) && !string.IsNullOrEmpty(depGuid) && !metadata.DependencyGuids.Contains(depGuid))
                {
                    metadata.DependencyGuids.Add(depGuid);
                }
            }
        }
    }
}