using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

/// <summary>
/// Drag & Drop предметов между слотами.
/// Один общий DragIconCanvas на все слоты — создаётся при первом старте.
/// </summary>
public class InventoryDragDrop : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler, IPointerEnterHandler, IPointerExitHandler
{
    public Slot slot;
    public int slotIndex;

    [SerializeField] private float dragIconScale  = 1.2f;
    [SerializeField] private bool  allowDropOutside = true;
    [SerializeField] private float dropThreshold    = 100f;

    // ── Общий на все слоты drag-icon ─────────────────────────────────────────
    private static GameObject     _sharedCanvas;
    private static RectTransform  _sharedIcon;
    private static Image          _sharedImage;

    // ── Per-instance поля ─────────────────────────────────────────────────────
    private CanvasGroup   _canvasGroup;
    private bool          _isDragging;
    private RectTransform _inventoryPanelRect;

    // ── Unity lifecycle ───────────────────────────────────────────────────────

    void Start()
    {
        _canvasGroup = GetComponent<CanvasGroup>();

        // Создаём общий DragCanvas один раз для всех слотов
        if (_sharedCanvas == null)
            CreateSharedDragCanvas();

        // Ищем rect инвентарной панели для определения «вне панели»
        if (InventoryManager.Instance?.inventoryPanel != null)
            _inventoryPanelRect = InventoryManager.Instance.inventoryPanel
                                      .GetComponent<RectTransform>();
    }

    private static void CreateSharedDragCanvas()
    {
        _sharedCanvas = new GameObject("DragIconCanvas");
        DontDestroyOnLoad(_sharedCanvas);

        var c = _sharedCanvas.AddComponent<Canvas>();
        c.renderMode      = RenderMode.ScreenSpaceOverlay;
        c.sortingOrder    = 1000;
        c.overrideSorting = true;
        _sharedCanvas.AddComponent<GraphicRaycaster>();

        var iconGO = new GameObject("DragIcon");
        iconGO.transform.SetParent(_sharedCanvas.transform, false);

        _sharedIcon           = iconGO.AddComponent<RectTransform>();
        _sharedIcon.sizeDelta = new Vector2(48, 48);

        _sharedImage                = iconGO.AddComponent<Image>();
        _sharedImage.raycastTarget  = false;

        iconGO.SetActive(false);
    }

    // ── Drag handlers ─────────────────────────────────────────────────────────

    public void OnBeginDrag(PointerEventData eventData)
    {
        if (slot == null || slot.IsEmpty) return;

        _isDragging = true;

        if (_canvasGroup != null)
            _canvasGroup.blocksRaycasts = false;

        if (_sharedIcon != null && slot.item?.icon != null)
        {
            _sharedImage.sprite = slot.item.icon;
            _sharedIcon.localScale = Vector3.one * dragIconScale;
            _sharedIcon.position   = eventData.position;
            _sharedIcon.gameObject.SetActive(true);
        }

        var bg = GetComponent<Image>();
        if (bg != null)
            bg.color = new Color(1f, 1f, 1f, 0.5f);
    }

    public void OnDrag(PointerEventData eventData)
    {
        if (!_isDragging || _sharedIcon == null) return;
        _sharedIcon.position = eventData.position;
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        if (!_isDragging) return;
        _isDragging = false;

        if (_sharedIcon != null)
        {
            _sharedIcon.gameObject.SetActive(false);
            _sharedIcon.localScale = Vector3.one;
        }

        if (_canvasGroup != null)
            _canvasGroup.blocksRaycasts = true;

        var bg = GetComponent<Image>();
        if (bg != null)
            bg.color = slot.IsEmpty
                ? new Color(0.25f, 0.25f, 0.25f, 0.8f)
                : new Color(0.35f, 0.35f, 0.35f, 0.95f);

        // Сначала ищем целевой слот (инвентарь ИЛИ хотбар)
        var raycastResults = new System.Collections.Generic.List<RaycastResult>();
        EventSystem.current.RaycastAll(eventData, raycastResults);

        Slot targetSlot = null;
        foreach (var result in raycastResults)
        {
            var s = result.gameObject.GetComponent<Slot>();
            if (s != null && s != slot) { targetSlot = s; break; }
        }

        if (targetSlot != null)
        {
            // Нашли слот — перемещаем (работает и для хотбара)
            InventoryManager.Instance?.SwapSlots(slot, targetSlot);
            return;
        }

        // Слот не найден — выбросить в мир если за пределами инвентаря
        if (allowDropOutside && IsOutsideInventory(eventData.position))
            DropItemOutside();
    }

    // ── Вспомогательные ───────────────────────────────────────────────────────

    private bool IsOutsideInventory(Vector2 screenPos)
    {
        if (_inventoryPanelRect == null) return false;

        Vector3[] corners = new Vector3[4];
        _inventoryPanelRect.GetWorldCorners(corners);

        return screenPos.x < corners[0].x - dropThreshold ||
               screenPos.x > corners[2].x + dropThreshold ||
               screenPos.y < corners[0].y - dropThreshold ||
               screenPos.y > corners[2].y + dropThreshold;
    }

    private void DropItemOutside()
    {
        if (slot == null || slot.IsEmpty) return;

        var  item   = slot.item;
        int  amount = slot.amount;

        Vector3 dropPos = Vector3.zero;
        if (Camera.main != null)
            dropPos = Camera.main.transform.position + Camera.main.transform.forward * 2f;

        if (InventoryItemFactory.Instance != null)
            InventoryItemFactory.Instance.DropItem(item, amount, dropPos);

        slot.Clear();
        Debug.Log($"[DragDrop] Выброшен: {item.itemName} x{amount}");
    }

    public void OnPointerEnter(PointerEventData eventData) { }
    public void OnPointerExit(PointerEventData eventData)  { }
}
