using NUnit.Framework;
using UnityEngine;
using LLM.Editor.Analysis;
using LLM.Editor.Helper;
using System.Collections.Generic;

namespace LLM.Editor.Tests.Unit
{
    public class GetDataTestComponent : MonoBehaviour
    {
        public string testField = "Hello";
    }

    [TestFixture]
    public class GetDataFromPathProviderTests
    {
        private GameObject _testObject;
        private GetDataFromPathProvider _provider;

        [SetUp]
        public void SetUp()
        {
            _provider = new GetDataFromPathProvider();
            _testObject = new GameObject("TestObject");
            _testObject.AddComponent<GetDataTestComponent>();
        }

        [TearDown]
        public void TearDown()
        {
            if (_testObject != null)
            {
                Object.DestroyImmediate(_testObject);
            }
        }

        private string CreatePathRequestJson(params PathStep[] steps)
        {
            var request = new PathRequest { steps = new List<PathStep>(steps) };
            return request.ToJson();
        }

        [Test]
        public void GetContext_ForSimpleProperty_ReturnsValue()
        {
            // Arrange
            _testObject.transform.position = new Vector3(1, 2, 3);
            var pathJson = CreatePathRequestJson(
                new PathStep { type = "component", name = "UnityEngine.Transform" },
                new PathStep { type = "property", name = "position" }
            );

            // Act
            var context = _provider.GetContext(_testObject, pathJson);

            // Assert
            Assert.IsInstanceOf<Vector3>(context);
            Assert.AreEqual(new Vector3(1, 2, 3), (Vector3)context);
        }

        [Test]
        public void GetContext_ForCustomField_ReturnsValue()
        {
            // Arrange
            var pathJson = CreatePathRequestJson(
                new PathStep { type = "component", name = "LLM.Editor.Tests.Unit.GetDataTestComponent" },
                new PathStep { type = "field", name = "testField" }
            );

            // Act
            var context = _provider.GetContext(_testObject, pathJson);

            // Assert
            Assert.IsInstanceOf<string>(context);
            Assert.AreEqual("Hello", (string)context);
        }

        [Test]
        public void GetContext_ForChainedPath_ReturnsChildComponent()
        {
            // Arrange
            var childObject = new GameObject("Child");
            childObject.transform.SetParent(_testObject.transform);
            childObject.AddComponent<BoxCollider>();

            var pathJson = CreatePathRequestJson(
                new PathStep { type = "child", name = "Child" },
                new PathStep { type = "component", name = "UnityEngine.BoxCollider" }
            );

            // Act
            var context = _provider.GetContext(_testObject, pathJson);
            
            // Assert
            // The provider returns a dictionary when the final object is a component
            Assert.IsInstanceOf<Dictionary<string, object>>(context);
            var data = (Dictionary<string, object>)context;
            Assert.IsInstanceOf<BoxCollider>(data["requestedComponentData"]);
        }

        [Test]
        public void GetContext_WithInvalidPath_ReturnsError()
        {
            // Arrange
            var pathJson = CreatePathRequestJson(
                new PathStep { type = "child", name = "NonExistentChild" },
                new PathStep { type = "component", name = "UnityEngine.BoxCollider" }
            );

            // Act
            var context = _provider.GetContext(_testObject, pathJson);

            // Assert
            Assert.IsInstanceOf<string>(context);
            Assert.IsTrue(((string)context).Contains("Path evaluation failed at a null object"));
        }
    }
}
