using LLM.Editor.Core;
using UnityEditor;
using UnityEngine;

namespace LLM.Editor.Commands
{
    public static class CommandUtility
    {
        public static Object ResolveIdentifier(Data.CommandContext context, string logicalName)
        {
            if (string.IsNullOrEmpty(logicalName))
            {
                context.ErrorMessage = "Identifier is null or empty.";
                return null;
            }

            if (!context.IdentifierMap.TryGetValue(logicalName, out var pId))
            {
                var foundObject = GameObject.Find(logicalName);
                if (foundObject) return foundObject;

                if (AssetDatabase.GUIDToAssetPath(logicalName) != "")
                {
                    return AssetDatabase.LoadAssetAtPath<Object>(AssetDatabase.GUIDToAssetPath(logicalName));
                }
                
                context.ErrorMessage = $"Logical name '{logicalName}' not found in the identifier map.";
                return null;
            }

            // 1. Try to resolve by InstanceID (fastest)
            if (pId.instanceID != 0)
            {
                var obj = EditorUtility.InstanceIDToObject(pId.instanceID);
                if (obj) return obj;
            }

            // 2. Fallback to resolving by path
            if (!string.IsNullOrEmpty(pId.path))
            {
                var go = GameObject.Find(pId.path);
                if (go)
                {
                    // Heal the map for the next lookup
                    pId.instanceID = go.GetInstanceID();
                    SessionManager.SaveIdentifierMap(context.IdentifierMap);
                    return go;
                }
            }
            
            // 3. Fallback to resolving by GUID for assets
            if (!string.IsNullOrEmpty(pId.guid))
            {
                var assetPath = AssetDatabase.GUIDToAssetPath(pId.guid);
                if (!string.IsNullOrEmpty(assetPath))
                {
                    return AssetDatabase.LoadAssetAtPath<Object>(assetPath);
                }
            }

            context.ErrorMessage = $"Failed to resolve identifier '{logicalName}'. The object may have been deleted or the scene/project state has changed significantly.";
            return null;
        }
        
        public static string GetGameObjectPath(GameObject obj)
        {
            if (obj == null) return null;
            var path = "/" + obj.name;
            while (obj.transform.parent)
            {
                obj = obj.transform.parent.gameObject;
                path = "/" + obj.name + path;
            }
            return path;
        }
    }
}
