using UnityEngine;
using System.Collections.Generic;

#if UNITY_EDITOR
using UnityEditor;
#endif

/// <summary>
/// Конфигурация для фабрики предметов - создать в Assets > Create > Inventory > Item Factory Config
/// </summary>
[CreateAssetMenu(fileName = "ItemFactoryConfig", menuName = "Inventory/Item Factory Config")]
public class ItemFactoryConfig : ScriptableObject
{
    [Header("World Item Prefabs")]
    public GameObject worldItemPrefab;  // Префаб предмета в мире

    [Header("Spawner Prefab")]
    public GameObject itemSpawnerPrefab;  // Префаб спавнера

    [Header("Pickup Settings")]
    public float pickupRadius = 1.5f;
    public float despawnTime = 300f;  // 5 минут

    [Header("Drop Settings")]
    public float dropForce = 2f;
    public float dropRandomness = 0.5f;
}

/// <summary>
/// Фабрика для создания префабов предметов - заменяет прямой Instantiate и Resources.Load
/// </summary>
public class InventoryItemFactory : MonoBehaviour
{
    public static InventoryItemFactory Instance { get; private set; }

    [Header("Configuration")]
    [Tooltip("Создать в Assets > Create > Inventory > Item Factory Config")]
    public ItemFactoryConfig config;

    [Header("Debug")]
    public bool logSpawns = false;

    // Кэшированные ссылки для быстрого доступа
    private Dictionary<string, GameObject> _prefabCache = new Dictionary<string, GameObject>();

    void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }

    /// <summary>
    /// Создать предмет в мире (WorldItem)
    /// </summary>
    /// <param name="itemData">Данные предмета</param>
    /// <param name="amount">Количество</param>
    /// <param name="position">Позиция спавна</param>
    /// <param name="rotation"> rotation ( Quaternion.identity по умолчанию)</param>
    public WorldItem CreateWorldItem(ItemData itemData, int amount, Vector3 position, Quaternion rotation = default)
    {
        GameObject go;

        if (config == null || config.worldItemPrefab == null)
        {
            // Fallback - создаём без префаба
            go = new GameObject($"WorldItem_{itemData.itemName}");
            go.transform.position = position;
            go.transform.rotation = rotation;

            // Добавляем компоненты для физики
            var collider = go.AddComponent<SphereCollider>();
            collider.radius = 0.3f;
            collider.isTrigger = true;
            var rb = go.AddComponent<Rigidbody>();
            rb.isKinematic = true;
            rb.useGravity = false;
        }
        else
        {
            go = Instantiate(config.worldItemPrefab, position, rotation);
        }
        var worldItem = go.GetComponent<WorldItem>();

        if (worldItem == null)
            worldItem = go.AddComponent<WorldItem>();

        worldItem.Setup(itemData, amount);

        if (logSpawns)
            Debug.Log($"[Factory] Created WorldItem: {itemData.itemName} x{amount} at {position}");

        return worldItem;
    }

    /// <summary>
    /// Создать предмет в мире с настраиваемым временем жизни
    /// </summary>
    public WorldItem CreateWorldItem(ItemData itemData, int amount, Vector3 position, float lifetime, Quaternion rotation = default)
    {
        var worldItem = CreateWorldItem(itemData, amount, position, rotation);
        if (worldItem != null && lifetime > 0)
        {
            Destroy(worldItem.gameObject, lifetime);
        }
        return worldItem;
    }

    /// <summary>
    /// Создать спавнер предмета (точка появления)
    /// </summary>
    public ItemSpawner CreateItemSpawner(ItemData itemData, int amount, Vector3 position)
    {
        if (config == null || config.itemSpawnerPrefab == null)
        {
            // Создаём базовый спавнер без префаба
            return CreateSpawnerFallback(itemData, amount, position);
        }

        var go = Instantiate(config.itemSpawnerPrefab, position, Quaternion.identity);
        var spawner = go.GetComponent<ItemSpawner>();

        if (spawner == null)
            spawner = go.AddComponent<ItemSpawner>();

        spawner.Setup(itemData, amount, config.despawnTime);

        if (logSpawns)
            Debug.Log($"[Factory] Created Spawner: {itemData.itemName} x{amount}");

        return spawner;
    }

    private ItemSpawner CreateSpawnerFallback(ItemData itemData, int amount, Vector3 position)
    {
        var go = new GameObject($"Spawner_{itemData.itemName}");
        go.transform.position = position;
        var spawner = go.AddComponent<ItemSpawner>();
        spawner.Setup(itemData, amount, config != null ? config.despawnTime : 300f);
        return spawner;
    }

    /// <summary>
    /// Выбросить предмет из инвентаря (drop)
    /// </summary>
    public WorldItem DropItem(ItemData itemData, int amount, Vector3 dropPosition, Vector3? velocity = null)
    {
        // Добавляем небольшое случайное смещение
        Vector3 offset = Vector3.zero;
        if (config != null)
        {
            offset = new Vector3(
                Random.Range(-config.dropRandomness, config.dropRandomness),
                0.5f,
                Random.Range(-config.dropRandomness, config.dropRandomness)
            );
        }

        Vector3 spawnPos = dropPosition + offset;
        Quaternion rotation = Quaternion.Euler(
            Random.Range(0, 360),
            Random.Range(0, 360),
            Random.Range(0, 360)
        );

        var worldItem = CreateWorldItem(itemData, amount, spawnPos, rotation);

        // Добавляем начальную скорость (для выброса из инвентаря)
        if (velocity.HasValue && worldItem != null)
        {
            var rb = worldItem.GetComponent<Rigidbody>();
            if (rb == null)
                rb = worldItem.gameObject.AddComponent<Rigidbody>();

            rb.linearVelocity = velocity.Value + (Vector3.up * (config?.dropForce ?? 2f));
        }

        // Если у ItemData нет связанной модели — создаём простой визуал (куб)
        if (itemData != null && itemData.modelPrefab == null && worldItem != null)
        {
            var visual = GameObject.CreatePrimitive(PrimitiveType.Cube);
            visual.name = "Visual";
            visual.transform.SetParent(worldItem.transform, false);
            visual.transform.localPosition = Vector3.zero;
            visual.transform.localScale = Vector3.one * 0.3f;
            // Удаляем лишний коллайдер на визуале
            var col = visual.GetComponent<Collider>();
            if (col != null) GameObject.Destroy(col);
        }

        return worldItem;
    }

    /// <summary>
    /// Предмет подбирается игроком - вызывается из WorldItem
    /// </summary>
    public bool PickupItem(WorldItem worldItem, MonoBehaviour picker)
    {
        if (worldItem == null || worldItem.itemData == null)
            return false;

        int remaining = InventoryManager.Instance.AddItem(worldItem.itemData, worldItem.amount);

        if (remaining <= 0)
        {
            if (logSpawns)
                Debug.Log($"[Factory] Picked up: {worldItem.itemData.itemName} x{worldItem.amount}");
            Destroy(worldItem.gameObject);
            return true;
        }
        else
        {
            // Частичный подбор
            worldItem.amount = remaining;
            return false;
        }
    }

    /// <summary>
    /// Создать префаб из GameObject в рантайме (динамические предметы)
    /// </summary>
    public GameObject CreateItemModel(GameObject modelPrefab, Transform parent)
    {
        if (modelPrefab == null)
            return null;

        return Instantiate(modelPrefab, parent);
    }
}

#if UNITY_EDITOR
/// <summary>
/// Кастомный редактор для быстрой настройки фабрики
/// </summary>
[CustomEditor(typeof(InventoryItemFactory))]
public class InventoryItemFactoryEditor : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        var factory = (InventoryItemFactory)target;

        GUILayout.Space(10);

        if (factory.config == null)
        {
            EditorGUILayout.HelpBox(
                "Создайте ItemFactoryConfig: Assets > Create > Inventory > Item Factory Config",
                MessageType.Warning);
        }

        if (GUILayout.Button("Создать ItemFactoryConfig"))
        {
            var config = ScriptableObject.CreateInstance<ItemFactoryConfig>();
            AssetDatabase.CreateAsset(config, "Assets/Inventory/Configs/ItemFactoryConfig.asset");
            AssetDatabase.SaveAssets();
            factory.config = config;
            Debug.Log("Создан ItemFactoryConfig");
        }

        GUILayout.Space(5);

        if (GUILayout.Button("Создать тестовый предмет в сцене"))
        {
            if (InventoryManager.Instance?.itemDatabase?.Count > 0)
            {
                var item = InventoryManager.Instance.itemDatabase[0];
                factory.CreateWorldItem(item, 5, Vector3.zero + Vector3.forward * 2);
            }
            else
            {
                Debug.LogWarning("Сначала добавьте предметы в InventoryManager");
            }
        }
    }
}
#endif