using UnityEngine;
using UnityEngine.UI;
using TMPro;

/// <summary>
/// Слот инвентаря - отображает предмет и его количество
/// </summary>
public class Slot : MonoBehaviour
{
    public int slotIndex;
    public ItemData item;
    public int amount;

    [Header("UI References")]
    public Image iconImage;
    public TextMeshProUGUI amountText;
    public GameObject amountPanel;
    public Image slotBackground;

    [Header("Visual Settings")]
    [SerializeField] private Color emptySlotColor = new Color(0.2f, 0.2f, 0.2f, 0.5f);
    [SerializeField] private Color filledSlotColor = new Color(0.3f, 0.3f, 0.3f, 0.9f);
    [SerializeField] private Color hoverColor = new Color(0.5f, 0.5f, 0.5f, 1f);
    [SerializeField] private Color selectedColor = new Color(0.4f, 0.6f, 0.9f, 1f);

    [Header("Drag & Drop")]
    [SerializeField] private bool allowDrag = true;

    public bool IsEmpty => item == null || amount <= 0;
    public bool HasItem => !IsEmpty;

    // События для внешних подписчиков
    public System.Action<Slot> OnSlotClicked;
    public System.Action<Slot> OnSlotRightClicked;
    public System.Action<Slot> OnSlotHovered;
    public System.Action<Slot> OnSlotDragStart;

    private bool _isSelected;

    void Awake()
    {
        // Автоматическое получение компонентов если не назначены
        if (iconImage == null)
            iconImage = transform.Find("Icon")?.GetComponent<Image>();

        if (amountText == null)
            amountText = transform.Find("AmountPanel/Text")?.GetComponent<TextMeshProUGUI>();

        if (amountPanel == null)
            amountPanel = transform.Find("AmountPanel")?.gameObject;

        if (slotBackground == null)
            slotBackground = GetComponent<Image>();
    }

    void Start()
    {
        UpdateSlotUI();
    }

    /// <summary>
    /// Обновить визуальное отображение слота
    /// </summary>
    public void UpdateSlotUI()
    {
        if (IsEmpty)
        {
            ClearVisuals();
            return;
        }

        // Иконка
        if (item.icon != null)
        {
            iconImage.sprite = item.icon;
            iconImage.enabled = true;
        }
        else
        {
            iconImage.enabled = false;
        }

        // Количество
        if (amount > 1)
        {
            amountText.text = amount.ToString();
            amountPanel.SetActive(true);
        }
        else
        {
            amountPanel.SetActive(false);
        }

        // Цвет фона
        if (slotBackground != null)
            slotBackground.color = filledSlotColor;
    }

    private void ClearVisuals()
    {
        iconImage.sprite = null;
        iconImage.enabled = false;
        amountPanel?.SetActive(false);

        if (slotBackground != null)
            slotBackground.color = emptySlotColor;
    }

    /// <summary>
    /// Очистить слот
    /// </summary>
    public void Clear()
    {
        item = null;
        amount = 0;
        UpdateSlotUI();

        // Уведомляем менеджер
        if (InventoryManager.Instance != null)
        {
            InventoryManager.Instance.OnSlotCleared(slotIndex);
        }

        // Вызываем событие
        InventoryEvents.Instance?.InvokeSlotChanged(slotIndex, null);
    }

    /// <summary>
    /// Установить предмет в слот
    /// </summary>
    public void SetItem(ItemData newItem, int newAmount)
    {
        item = newItem;
        amount = newAmount;
        UpdateSlotUI();

        // Вызываем событие изменения
        InventoryEvents.Instance?.InvokeSlotChanged(slotIndex, item?.id);
    }

    /// <summary>
    /// Добавить предметы в слот
    /// </summary>
    /// <returns>Количество не поместившихся предметов</returns>
    public int AddItems(ItemData newItem, int addAmount)
    {
        if (item == null)
        {
            // Пустой слот - просто кладём
            item = newItem;
            amount = Mathf.Min(addAmount, newItem.maxStack);
            UpdateSlotUI();

            // Событие добавления
            InventoryEvents.Instance?.InvokeItemAdded(item.id, amount);
            InventoryEvents.Instance?.InvokeSlotChanged(slotIndex, item.id);

            return addAmount - amount;
        }

        if (item.id != newItem.id)
        {
            // Другой предмет - нельзя добавить
            return addAmount;
        }

        // Тот же предмет - пытаемся добавить в стек
        int space = item.maxStack - amount;
        if (space <= 0) return addAmount;

        int toAdd = Mathf.Min(space, addAmount);
        amount += toAdd;
        UpdateSlotUI();

        // Событие изменения
        InventoryEvents.Instance?.InvokeItemCountChanged(item.id, amount);
        InventoryEvents.Instance?.InvokeSlotChanged(slotIndex, item.id);

        return addAmount - toAdd;
    }

    /// <summary>
    /// Взять часть предметов из слота
    /// </summary>
    /// <returns>(предмет, взятое количество)</returns>
    public (ItemData, int) TakeItems(int takeAmount)
    {
        if (IsEmpty) return (null, 0);

        int actualTake = Mathf.Min(takeAmount, amount);
        amount -= actualTake;

        ItemData resultItem = item;

        if (amount <= 0)
        {
            Clear();
        }
        else
        {
            UpdateSlotUI();
            // Событие изменения количества
            InventoryEvents.Instance?.InvokeItemCountChanged(item.id, amount);
        }

        // Событие удаления
        InventoryEvents.Instance?.InvokeItemRemoved(resultItem.id, actualTake);

        return (resultItem, actualTake);
    }

    /// <summary>
    /// Взять все предметы из слота
    /// </summary>
    public (ItemData, int) TakeAll()
    {
        return TakeItems(amount);
    }

    // ==================== UI Events ====================

    void OnMouseDown()
    {
        if (Input.GetMouseButton(0))
        {
            OnSlotClicked?.Invoke(this);

            if (allowDrag)
            {
                OnSlotDragStart?.Invoke(this);
            }
        }
        else if (Input.GetMouseButton(1))
        {
            OnSlotRightClicked?.Invoke(this);
        }
    }

    /// <summary>
    /// Установить состояние выделения слота
    /// </summary>
    public void SetSelected(bool selected)
    {
        _isSelected = selected;
        if (slotBackground != null)
        {
            slotBackground.color = selected ? selectedColor :
                (IsEmpty ? emptySlotColor : filledSlotColor);
        }
    }

    /// <summary>
    /// Поменять содержимое с другим слотом
    /// </summary>
    public void SwapWith(Slot other)
    {
        if (other == null || other == this) return;

        var tempItem = this.item;
        var tempAmount = this.amount;

        this.SetItem(other.item, other.amount);
        other.SetItem(tempItem, tempAmount);
    }

    // ==================== Getters ====================

    public ItemData GetItem() => item;
    public int GetAmount() => amount;
    public string GetItemId() => item?.id;
    public bool IsSelected() => _isSelected;
}