using UnityEngine;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif
using System;

namespace SpecialMoveCards
{
    /// <summary>
    /// Holds up to two cards, exposes UseCard(slot), integrates with Animation via SpecialAnimationBridge.
    /// </summary>
    public class PlayerPocket : MonoBehaviour
    {
    [Header("Animation")] public SpecialAnimationBridge animationBridge;
    [Header("UI")] public UIController_Pocket pocketUI;
    [Tooltip("Tag used to find the Pocket UI at runtime if not assigned in inspector.")]
    [SerializeField] private string pocketUITag = "Pocket UI";
    private Coroutine resolveUICoroutine;

    [Header("Input (Optional)")]
#if ENABLE_INPUT_SYSTEM
    public InputAction useSlot1Action; // bind to keyboard 1
    public InputAction useSlot2Action; // bind to keyboard 2
    [Tooltip("Input System action that triggers using the next available card in the pocket (left-most).")]
    public InputActionReference specialMoveAction; // expected to be bound to e.g. gamepad X / keyboard E
#endif
        [Tooltip("Allow using cards while holding only 1.")]
        public bool allowUseWithSingleCard = true;

        private CardData[] slots = new CardData[2];
        public int Count { get { return (slots[0] != null ? 1 : 0) + (slots[1] != null ? 1 : 0); } }

        private void Awake()
        {
            // Skip if card system is disabled globally
            if (CardSpawner.CARD_SYSTEM_DISABLED)
            {
                Debug.Log("[PlayerPocket] Card System is DISABLED - disabling component");
                enabled = false;
                return;
            }
            
            if (animationBridge == null)
                animationBridge = GetComponent<SpecialAnimationBridge>();

            // Try to auto-resolve UI early (player is often spawned from prefab)
            if (pocketUI == null)
                TryResolvePocketUIOnce();
        }

        private void OnEnable()
        {
#if ENABLE_INPUT_SYSTEM
            // Create defaults if not wired in Inspector
            if (useSlot1Action == null)
            {
                useSlot1Action = new InputAction(name: "UseCardSlot1", binding: "<Keyboard>/1");
            }
            if (useSlot2Action == null)
            {
                useSlot2Action = new InputAction(name: "UseCardSlot2", binding: "<Keyboard>/2");
            }

            if (useSlot1Action != null)
            {
                useSlot1Action.SafeEnable();
                useSlot1Action.performed += OnUseSlot1;
            }
            if (useSlot2Action != null)
            {
                useSlot2Action.SafeEnable();
                useSlot2Action.performed += OnUseSlot2;
            }

            // Hook SpecialMove input if provided
            if (specialMoveAction != null && specialMoveAction.action != null)
            {
                specialMoveAction.action.SafeEnable();
                specialMoveAction.action.performed += OnSpecialMovePerformed;
            }
#endif
            PushUI();
        }

        private void OnDisable()
        {
#if ENABLE_INPUT_SYSTEM
            if (useSlot1Action != null) useSlot1Action.performed -= OnUseSlot1;
            if (useSlot2Action != null) useSlot2Action.performed -= OnUseSlot2;
            if (useSlot1Action != null) useSlot1Action.Disable();
            if (useSlot2Action != null) useSlot2Action.Disable();

            if (specialMoveAction != null && specialMoveAction.action != null)
            {
                specialMoveAction.action.performed -= OnSpecialMovePerformed;
                specialMoveAction.action.Disable();
            }
#endif
            if (resolveUICoroutine != null)
            {
                StopCoroutine(resolveUICoroutine);
                resolveUICoroutine = null;
            }
        }

        private void Update()
        {
            // Legacy fallback
            if (Input.GetKeyDown(KeyCode.Alpha1)) UseCard(0);
            if (Input.GetKeyDown(KeyCode.Alpha2)) UseCard(1);
        }

#if ENABLE_INPUT_SYSTEM
        private void OnUseSlot1(InputAction.CallbackContext ctx) { if (ctx.performed) UseCard(0); }
        private void OnUseSlot2(InputAction.CallbackContext ctx) { if (ctx.performed) UseCard(1); }
    private void OnSpecialMovePerformed(InputAction.CallbackContext ctx)
    {
        if (!ctx.performed) return;
        // Always consume the left-most available card (sequential use)
        // UseCard will compact and raise events/UI.
        if (slots[0] != null) { UseCard(0); return; }
        if (slots[1] != null) { UseCard(1); return; }
        // no card -> ignore
    }
#endif

        /// <summary>
        /// Try adding a card to the first empty slot. Returns true if added.
        /// </summary>
        public bool TryAddCard(CardData data)
        {
            if (data == null) return false;
            if (slots[0] == null) { slots[0] = data; OnChanged(); GameEvents.RaiseCardPicked(data); return true; }
            if (slots[1] == null) { slots[1] = data; OnChanged(); GameEvents.RaiseCardPicked(data); return true; }
            return false; // full
        }

        /// <summary>
        /// Uses a card at slot index (0 or 1). Consumes immediately and plays mapped animation.
        /// </summary>
        public void UseCard(int slotIndex)
        {
            if (slotIndex < 0 || slotIndex > 1) return;
            var data = slots[slotIndex];
            if (data == null)
            {
                // If only one card and user pressed empty slot, optionally redirect to occupied slot
                if (allowUseWithSingleCard && Count == 1)
                {
                    int other = slotIndex == 0 ? 1 : 0;
                    if (slots[other] != null) { UseCard(other); }
                }
                return;
            }

            // Consume first
            slots[slotIndex] = null;
            CompactLeft();
            OnChanged();
            GameEvents.RaiseCardUsed(data, slotIndex);

            // Play animation
            if (animationBridge)
            {
                animationBridge.PlaySpecialMove(data.animationTriggerName);
            }

            // Optional particles could be spawned by listening to GameEvents.CardUsed
        }

        /// <summary>
        /// Get a snapshot of slots (length 2). Do not mutate the returned array.
        /// </summary>
        public CardData[] GetSnapshot()
        {
            var snap = new CardData[2];
            snap[0] = slots[0];
            snap[1] = slots[1];
            return snap;
        }

        private void CompactLeft()
        {
            // Keep items packed to the left: [A,null] => [A,null], [null,B] => [B,null]
            if (slots[0] == null && slots[1] != null)
            {
                slots[0] = slots[1];
                slots[1] = null;
            }
        }

        private void OnChanged()
        {
            PushUI();
            GameEvents.RaisePocketChanged(GetSnapshot(), Count);
        }

        private void PushUI()
        {
            if (pocketUI == null)
            {
                // Attempt to resolve again at first use; if still missing, start a short retry loop
                TryResolvePocketUIOnce();
                if (pocketUI == null && resolveUICoroutine == null)
                    resolveUICoroutine = StartCoroutine(ResolvePocketUIRoutine());
            }

            if (pocketUI)
                pocketUI.UpdateUI(GetSnapshot());
        }

        private void TryResolvePocketUIOnce()
        {
            if (string.IsNullOrEmpty(pocketUITag)) return;
            var go = GameObject.FindWithTag(pocketUITag);
            if (go == null) return;
            var ui = go.GetComponent<UIController_Pocket>();
            if (ui != null) pocketUI = ui;
        }

        private System.Collections.IEnumerator ResolvePocketUIRoutine()
        {
            // Try for a short window (e.g., next 1 second) in case UI spawns after the player
            float timeout = 1.0f;
            float t = 0f;
            while (pocketUI == null && t < timeout)
            {
                TryResolvePocketUIOnce();
                if (pocketUI != null) break;
                t += Time.deltaTime;
                yield return null;
            }
            resolveUICoroutine = null;
            if (pocketUI)
                pocketUI.UpdateUI(GetSnapshot());
            else
                Debug.LogWarning("PlayerPocket: Could not find Pocket UI by tag '" + pocketUITag + "' within 1s. Make sure the UI exists and is tagged.");
        }
    }
}
