using System;
using UnityEngine;
using UnityEditor;
using LLM.Editor.Core;
using LLM.Editor.Helper;
using JetBrains.Annotations;

namespace LLM.Editor.Commands
{
    [Serializable]
    public class CreateGameObjectParams
    {
        public string gameObjectName;
        public string logicalName; // A unique name for the LLM to reference this object later
        public string primitiveType; // Optional: e.g., "Cube", "Sphere", "Capsule"
    }

    [UsedImplicitly]
    public class CreateGameObjectCommand : ICommand
    {
        private readonly CreateGameObjectParams _params;

        public CreateGameObjectCommand(string jsonParams)
        {
            _params = jsonParams?.FromJson<CreateGameObjectParams>();
        }

        public CommandOutcome Execute(Data.CommandContext context)
        {
            if (_params == null || string.IsNullOrEmpty(_params.gameObjectName))
            {
                context.ErrorMessage = "Invalid parameters. A name for the GameObject is required.";
                return CommandOutcome.Error;
            }

            GameObject newGameObject;

            if (string.IsNullOrEmpty(_params.primitiveType))
            {
                newGameObject = new GameObject(_params.gameObjectName);
            }
            else
            {
                try
                {
                    var type = (PrimitiveType)Enum.Parse(typeof(PrimitiveType), _params.primitiveType, true);
                    newGameObject = GameObject.CreatePrimitive(type);
                    newGameObject.name = _params.gameObjectName;
                }
                catch (ArgumentException)
                {
                    context.ErrorMessage = $"Invalid primitive type: '{_params.primitiveType}'. Valid types are Cube, Sphere, Capsule, Cylinder, Plane, Quad.";
                    return CommandOutcome.Error;
                }
            }
            
            Undo.RegisterCreatedObjectUndo(newGameObject, $"Create {newGameObject.name}");
            
            // --- Identifier Persistence Logic ---
            var logicalName = !string.IsNullOrEmpty(_params.logicalName) ? _params.logicalName : $"{_params.gameObjectName}_{Guid.NewGuid():N}";
            
            var pId = new Data.PersistentIdentifier
            {
                logicalName = logicalName,
                instanceID = newGameObject.GetInstanceID(),
                path = CommandUtility.GetGameObjectPath(newGameObject)
            };
            
            context.IdentifierMap[logicalName] = pId;
            SessionManager.SaveIdentifierMap(context.IdentifierMap);
            
            // Set the logical name as the current subject so the LLM knows what to reference.
            context.CurrentSubject = logicalName;
            // --- End of Logic ---
            
            Selection.activeGameObject = newGameObject;

            Debug.Log($"[CreateGameObjectCommand] Successfully created '{newGameObject.name}' and mapped it to logical name '{logicalName}'.");
            return CommandOutcome.Success;
        }
    }
}
