using System.Linq;
using UnityEditor;
using UnityEngine;
using LLM.Editor.Core;
using System.Collections.Generic;
using IntelligentProjectAnalyzer.Analyzer;
using Object = UnityEngine.Object;

namespace LLM.Editor.Analysis
{
    /// <summary>
    /// Finds all references to a specific method or class in the project using Roslyn for scripts,
    /// AssetDatabase for prefabs, and a scene search for GameObjects.
    /// </summary>
    public class FindReferencesProvider : IContextProvider
    {
        public object GetContext(Object target, string qualifier)
        {
            if (string.IsNullOrEmpty(qualifier))
            {
                return "Error: A method or class name (qualifier) is required for FindReferences.";
            }

            if (!qualifier.Contains(".")) // If it's just a method name...
            {
                // ...try to find the class from the working context.
                var workingContext = SessionManager.LoadWorkingContext();
                var lastScript = workingContext["lastScriptAnalyzed"]?["className"]?.ToString();
                if (!string.IsNullOrEmpty(lastScript))
                {
                    var fullQualifier = $"{lastScript}.{qualifier}";
                    Debug.Log($"[FindReferencesProvider] Inferred full qualifier as '{fullQualifier}' from working context.");
                }
            }

            // Let Roslyn handle the complex task of parsing the qualifier.
            var (scriptReferences, foundScriptGuid, scriptType) = RoslynReferenceFinder.FindReferences(qualifier);

            if (string.IsNullOrEmpty(foundScriptGuid) || scriptType == null)
            {
                return $"Error: Could not resolve '{qualifier}' to a known type or method in the project.";
            }

            var prefabReferences = FindPrefabReferences(foundScriptGuid);
            var sceneReferences = FindSceneReferences(scriptType);

            return new
            {
                scriptReferences,
                prefabReferences,
                sceneReferences
            };
        }

        /// <summary>
        /// Finds all prefabs that have the target script as a dependency.
        /// </summary>
        private static List<object> FindPrefabReferences(string scriptGuid)
        {
            var results = new List<object>();
            var allPrefabGuids = AssetDatabase.FindAssets("t:Prefab");

            foreach (var prefabGuid in allPrefabGuids)
            {
                var path = AssetDatabase.GUIDToAssetPath(prefabGuid);
                var dependencies = AssetDatabase.GetDependencies(path, false);
                if (dependencies.Any(dep => AssetDatabase.AssetPathToGUID(dep) == scriptGuid))
                {
                    results.Add(new { path, guid = prefabGuid });
                }
            }
            return results;
        }

        /// <summary>
        /// Finds all GameObjects in the active scene that have the target script component.
        /// </summary>
        private static List<object> FindSceneReferences(System.Type scriptType)
        {
            var instances = Object.FindObjectsOfType(scriptType, true);
            return instances.Select(inst => new
            {
                inst.name,
                instanceId = inst.GetInstanceID()
            }).Cast<object>().ToList();
        }
    }
}