using System.Collections.Generic;
using NUnit.Framework;
using Sirenix.Utilities;
using Test.Util;
using UnityEditor;
using UnityEngine;
using VOID.Generic.Objects.Item;

namespace Test.EditMode.Prefabs.Generic
{
    public class ItemObjectTest
    {
        private List<GameObject> _gameObjects = new();

        [OneTimeSetUp]
        public void Setup()
        {
            AssetDatabase.FindAssets("t:GameObject").ForEach(gameObjectGuid =>
            {
                var gameObjectPath = AssetDatabase.GUIDToAssetPath(gameObjectGuid);
                var gameObject = AssetDatabase.LoadAssetAtPath<GameObject>(gameObjectPath);
                var itemObjects = gameObject.GetComponentsInChildren<ItemObject>();
                
                // If prefab have any AbstractObject or any of its children anywhere - take it, we will test it
                if (itemObjects.Length > 0) _gameObjects.Add(gameObject);
            });
        }

        [OneTimeTearDown]
        public void Cleanup()
        {
            _gameObjects?.Clear();
            _gameObjects = null;
        }

        [Test]
        public void ItemData_Name()
        {
            _gameObjects.ForEach(gameObject =>
            {
                var itemObject = gameObject.GetComponent<ItemObject>();
                var prefabPath = AssetDatabase.GetAssetPath(gameObject.GetInstanceID());
                var prefabPathHyperlink = DebugLogUtil.Hyperlink(prefabPath);
                
                if (itemObject.basicData.finalName.IsNullOrWhitespace())
                    Debug.LogWarning($"Name is not defined: {prefabPathHyperlink}", itemObject);
            });
        }

        [Test]
        public void ItemData_Icon()
        {
            _gameObjects.ForEach(gameObject =>
            {
                var itemObject = gameObject.GetComponent<ItemObject>();
                var prefabPath = AssetDatabase.GetAssetPath(gameObject.GetInstanceID());
                var prefabPathHyperlink = DebugLogUtil.Hyperlink(prefabPath);
                
                if (!itemObject.basicData.image)
                    Debug.LogError($"{itemObject.name}'s icon is empty: {prefabPathHyperlink}", itemObject);
                
                if (itemObject.basicData.image.width != itemObject.basicData.image.height)
                    Debug.LogWarning($"{itemObject.name}'s icon size proportions are invalid (width != height): {prefabPathHyperlink}", itemObject);
            });
        }

        [Test]
        public void ItemData_Description()
        {
            // Nothing here
        }

        [Test]
        public void ItemData_Weight()
        {
            _gameObjects.ForEach(gameObject =>
            {
                var itemObject = gameObject.GetComponent<ItemObject>();
                var prefabPath = AssetDatabase.GetAssetPath(gameObject.GetInstanceID());
                var prefabPathHyperlink = DebugLogUtil.Hyperlink(prefabPath);
                
                if (itemObject.itemData.weight < 0f)
                    Debug.LogError($"{itemObject.basicData.finalName}'s weight is lesser than 0: {prefabPathHyperlink}", itemObject);
            });
        }

        [Test]
        public void ItemData_Quality()
        {
            _gameObjects.ForEach(gameObject =>
            {
                var itemObject = gameObject.GetComponent<ItemObject>();
                var prefabPath = AssetDatabase.GetAssetPath(gameObject.GetInstanceID());
                var prefabPathHyperlink = DebugLogUtil.Hyperlink(prefabPath);
                
                if (!itemObject.itemData.quality)
                    Debug.LogError($"{itemObject.basicData.finalName}'s quality is not selected: {prefabPathHyperlink}", itemObject);
            });
        }

        [Test]
        public void ItemData_Value()
        {
            _gameObjects.ForEach(gameObject =>
            {
                var itemObject = gameObject.GetComponent<ItemObject>();
                var prefabPath = AssetDatabase.GetAssetPath(gameObject.GetInstanceID());
                var prefabPathHyperlink = DebugLogUtil.Hyperlink(prefabPath);

                if (itemObject.itemData.value < 0f)
                    Debug.LogError($"{itemObject.basicData.finalName}'s weight is lesser than 0: {prefabPathHyperlink}",
                        itemObject);
            });
        }

        [Test]
        public void ItemData_Stackable()
        {
            // Nothing
        }

        [Test]
        public void ItemData_StackSize()
        {
            _gameObjects.ForEach(gameObject =>
            {
                var itemObject = gameObject.GetComponent<ItemObject>();
                var prefabPath = AssetDatabase.GetAssetPath(gameObject.GetInstanceID());
                var prefabPathHyperlink = DebugLogUtil.Hyperlink(prefabPath);

                if (itemObject.itemData.stackSize < 1)
                    Debug.LogError($"{itemObject.basicData.finalName}'s stack size is lesser than 1: {prefabPathHyperlink}",
                        itemObject);

                if (!itemObject.itemData.stackable && itemObject.itemData.stackSize != 1)
                    Debug.LogError($"{itemObject.basicData.finalName} is not stackable, stack size must be 1: {prefabPathHyperlink}",
                        itemObject);

                if (itemObject.itemData.stackSize > itemObject.itemData.stackSizeMax)
                    Debug.LogError($"{itemObject.basicData.finalName}'s stack size is greater than max stack size: {prefabPathHyperlink}",
                        itemObject);
            });
        }

        [Test]
        public void ItemData_StackSizeMax()
        {
            _gameObjects.ForEach(gameObject =>
            {
                var itemObject = gameObject.GetComponent<ItemObject>();
                var prefabPath = AssetDatabase.GetAssetPath(gameObject.GetInstanceID());
                var prefabPathHyperlink = DebugLogUtil.Hyperlink(prefabPath);

                if (itemObject.itemData.stackSizeMax < 1)
                    Debug.LogError($"{itemObject.basicData.finalName}'s max stack size is lesser than 1: {prefabPathHyperlink}",
                        itemObject);

                if (!itemObject.itemData.stackable && itemObject.itemData.stackSizeMax != 1)
                    Debug.LogError($"{itemObject.basicData.finalName} is not stackable, stack size must be 1: {prefabPathHyperlink}",
                        itemObject);

                if (itemObject.itemData.stackSize > itemObject.itemData.stackSizeMax)
                    Debug.LogError($"{itemObject.basicData.finalName}'s stack size is greater than max stack size: {prefabPathHyperlink}",
                        itemObject);
            });
        }
    }
}

