using System;
using UnityEditor;
using UnityEngine;
using System.Threading.Tasks;
using System.Collections.Generic;

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

namespace IntelligentProjectAnalyzer.Editor
{
    /// <summary>
    /// Acts as the central state machine and orchestrator of the dependency build process.
    /// This version performs the scan asynchronously and is driven by editor events.
    /// </summary>
    public static class DependencyStoreBuilder
    {
        private const int BatchSize = 20; // Number of assets to process per frame.

        #region State Management
        private enum BuilderState { Idle, PreFetching, Analyzing, Finalizing }
        private static BuilderState _currentState = BuilderState.Idle;

        // Queues for assets to be processed on the main thread
        private static Queue<string> _scriptGuidsToProcess;
        private static Queue<string> _prefabGuidsToProcess;
        private static Queue<string> _soGuidsToProcess;
        private static Queue<string> _sceneGuidsToProcess;
        private static Queue<string> _miscGuidsToProcess;

        // Lists to store the pre-fetched metadata
        private static List<AssetMetadata> _allMetadata;
        private static List<ScriptMetadata> _scriptMetadata;
        private static List<SceneMetadata> _sceneMetadata;
        private static List<MiscAssetMetadata> _miscMetadata;

        // Task for background analysis
        private static Task<List<AssetMetadata>> _analysisTask;
        #endregion

        // Static constructor to hook into the editor update loop.
        static DependencyStoreBuilder()
        {
            EditorApplication.update += OnEditorUpdate;
        }

        /// <summary>
        /// Starts the build process. Called by DependencyBuilderTriggers.
        /// </summary>
        public static void BuildStore()
        {
            if (_currentState != BuilderState.Idle)
            {
                // A build is already running.
                return;
            }

            // --- Initialize State and Queues ---
            Debug.Log($"--- Starting Async Dependency Store Build ---");
            DependencyCacheManager.CleanAndPrepareCache();

            (_scriptGuidsToProcess, _prefabGuidsToProcess, _soGuidsToProcess, _sceneGuidsToProcess, _miscGuidsToProcess) = AssetDataFetcher.FindAssetGuids();
            
            var analyzerSettings = AnalyzerSettingsCrud.GetOrCreateSettings();
            if (!analyzerSettings.AnalyzeScripts)
            {
                _scriptGuidsToProcess?.Clear();
            }
            if (!analyzerSettings.AnalyzePrefabs)
            {
                _prefabGuidsToProcess?.Clear();
            }
            if (!analyzerSettings.AnalyzeScriptableObjects)
            {
                _soGuidsToProcess?.Clear();
            }
            if (!analyzerSettings.AnalyzeMiscellaneous)
            {
                _miscGuidsToProcess?.Clear();
            }

            _allMetadata = new List<AssetMetadata>();
            _scriptMetadata = new List<ScriptMetadata>();
            _sceneMetadata = new List<SceneMetadata>();
            _miscMetadata = new List<MiscAssetMetadata>();

            _currentState = BuilderState.PreFetching;
        }

        private static void OnEditorUpdate()
        {
            // The state machine is processed here, once per editor frame.
            if (_currentState == BuilderState.Idle) return;

            try
            {
                switch (_currentState)
                {
                    case BuilderState.PreFetching:
                        ProcessPreFetchingBatch();
                        break;
                    case BuilderState.Analyzing:
                        WaitForAnalysis();
                        break;
                    case BuilderState.Finalizing:
                        FinalizeBuild();
                        break;
                }
            }
            catch (Exception e)
            {
                Debug.LogError($"An error occurred during the build process. Aborting. Exception: {e}");
                ResetState();
            }
        }

        private static void ProcessPreFetchingBatch()
        {
            var totalAssets = _scriptGuidsToProcess.Count + _prefabGuidsToProcess.Count + _soGuidsToProcess.Count + _sceneGuidsToProcess.Count + _miscGuidsToProcess.Count;
            var initialTotal = _allMetadata.Count + totalAssets;

            for (var i = 0; i < BatchSize; i++)
            {
                if (_sceneGuidsToProcess.Count > 0)
                {
                    var meta = AssetDataFetcher.PreFetchSceneMetadata(_sceneGuidsToProcess.Dequeue());
                    if (meta != null)
                    {
                        _allMetadata.Add(meta);
                        _sceneMetadata.Add(meta);
                    }
                }
                else if (_scriptGuidsToProcess.Count > 0)
                {
                    var meta = AssetDataFetcher.PreFetchScriptMetadata(_scriptGuidsToProcess.Dequeue());
                    if (meta != null)
                    {
                        _allMetadata.Add(meta);
                        _scriptMetadata.Add(meta);
                    }
                }
                else if (_prefabGuidsToProcess.Count > 0)
                {
                    var meta = AssetDataFetcher.PreFetchPrefabMetadata(_prefabGuidsToProcess.Dequeue());
                    if (meta != null) _allMetadata.Add(meta);
                }
                else if (_soGuidsToProcess.Count > 0)
                {
                    var meta = AssetDataFetcher.PreFetchScriptableObjectMetadata(_soGuidsToProcess.Dequeue());
                    if (meta != null) _allMetadata.Add(meta);
                }
                else if (_miscGuidsToProcess.Count > 0)
                {
                    var meta = AssetDataFetcher.PreFetchMiscAssetMetadata(_miscGuidsToProcess.Dequeue());
                    if (meta != null)
                    {
                        _allMetadata.Add(meta);
                        _miscMetadata.Add(meta);
                    }
                }
                else
                {
                    // All pre-fetching is complete.
                    Debug.Log("Pre-fetching complete. Starting background analysis...");
                    StartBackgroundAnalysis();
                    _currentState = BuilderState.Analyzing;
                    return;
                }
            }

            // Update progress bar
            var progress = initialTotal > 0 ? (float)_allMetadata.Count / initialTotal : 1;
            EditorUtility.DisplayProgressBar("Building Dependency Store (1/3)", "Pre-fetching asset data...", progress);
        }

        private static void StartBackgroundAnalysis()
        {
            // Gather all the data needed for the background task.
            var roslynSetupData = AssetDataFetcher.PreFetchRoslynSetupData(_scriptMetadata);

            // Start the background task, passing it the data it needs.
            _analysisTask = Task.Run(() => BackgroundAnalyzer.RunAnalysis(_allMetadata, roslynSetupData));
        }

        private static void WaitForAnalysis()
        {
            if (_analysisTask == null)
            {
                Debug.LogError("Analysis task was not started correctly. Aborting.");
                ResetState();
                return;
            }

            EditorUtility.DisplayProgressBar("Building Dependency Store (2/3)", "Analyzing dependencies in background...", _analysisTask.IsCompleted ? 1f : 0.5f);

            if (_analysisTask.IsCompleted)
            {
                _currentState = BuilderState.Finalizing;
            }
        }

        private static void FinalizeBuild()
        {
            EditorUtility.DisplayProgressBar("Building Dependency Store (3/3)", "Writing results to disk...", 0.9f);

            if (_analysisTask.IsFaulted)
            {
                Debug.LogError($"Background analysis failed: {_analysisTask.Exception}");
            }
            else
            {
                var results = _analysisTask.Result;
                DependencyCacheManager.WriteResults(results);
                Debug.Log("--- Async Dependency Store Build Complete! ---");
            }

            ResetState();
        }

        private static void ResetState()
        {
            EditorUtility.ClearProgressBar();
            _currentState = BuilderState.Idle;
            _analysisTask = null;
        }
    }
}
