using UnityEngine;
using System.Collections.Generic;
using System.Collections;

/// <summary>
/// Manages the execution of battle actions and coordinates with existing systems
/// </summary>
public class BattleActionSystem : MonoBehaviour
{
    [Header("References")]
    public BattleActionWheel actionWheel;

    [Header("Item System")]
    public BattleItemSelector itemSelectionUI;

    [Header("Spell System")]
    public SpellSelectionUI spellSelectionUI;

    [Header("Settings")]
    public LayerMask enemyLayerMask = 1 << 10;
    public LayerMask playerLayerMask = 1 << 9;
    public LayerMask groundLayerMask = 1 << 0;

    private Character currentCharacter;
    private EnhancedCharacterActionData pendingAction;
    private bool isWaitingForTarget = false;
    private Camera mainCamera;

    // Events
    public event System.Action<Character> OnActionCompleted;
    public event System.Action<Character, BattleActionType> OnActionStarted;

    void Awake()
    {
        mainCamera = Camera.main;

        // Find or create action wheel
        if (actionWheel == null)
            actionWheel = FindFirstObjectByType<BattleActionWheel>();
    }

    void Start()
    {
        // Subscribe to action wheel events
        if (actionWheel != null)
        {
            actionWheel.OnActionSelected += OnActionTypeSelected;
            actionWheel.OnWheelClosed += OnActionWheelClosed;
        }

        // Subscribe to item/spell selection events
        if (itemSelectionUI != null)
        {
            itemSelectionUI.OnItemSelected += OnItemSelected;
            itemSelectionUI.OnSelectionCancelled += OnItemSelectionCancelled;
        }

        if (spellSelectionUI != null)
        {
            spellSelectionUI.OnSpellSelected += OnSpellSelected;
            spellSelectionUI.OnSelectionCancelled += OnSpellSelectionCancelled;
        }
    }

    void Update()
    {
        if (isWaitingForTarget)
        {
            HandleTargetSelection();
        }
    }

    /// <summary>
    /// Shows the action wheel for a character
    /// </summary>
    public void ShowActionWheel(Character character)
    {
        currentCharacter = character;

        if (actionWheel != null)
        {
            Vector3 wheelPosition = character.transform.position + Vector3.up * 2f;
            actionWheel.ShowWheel(character, wheelPosition);
        }
        else
        {
            Debug.LogError("BattleActionSystem: No action wheel assigned!");
        }
    }

    /// <summary>
    /// Hides the action wheel
    /// </summary>
    public void HideActionWheel()
    {
        if (actionWheel != null)
        {
            actionWheel.HideWheel();
        }
    }

    /// <summary>
    /// Executes the character's selected action
    /// </summary>
    public void ExecuteCharacterAction(Character character)
    {
        if (character == null)
        {
            Debug.LogWarning("BattleActionSystem: Invalid character");
            return;
        }

        var actionData = character.GetEnhancedActionData<EnhancedCharacterActionData>();
        if (actionData == null)
        {
            Debug.LogWarning($"BattleActionSystem: Character {character.CharacterName} has no enhanced action data");
            return;
        }

        if (!actionData.hasValidAction)
        {
            Debug.LogWarning($"BattleActionSystem: Character {character.CharacterName} has no valid action");
            return;
        }

        Debug.Log($"🎯 Executing {actionData.actionType} for {character.CharacterName}: {actionData.GetActionDescription()}");

        OnActionStarted?.Invoke(character, actionData.actionType);

        StartCoroutine(ExecuteActionCoroutine(character, actionData));
    }

    private IEnumerator ExecuteActionCoroutine(Character character, EnhancedCharacterActionData actionData)
    {
        switch (actionData.actionType)
        {
            case BattleActionType.Move:
                yield return ExecuteMoveAction(character, actionData);
                break;

            case BattleActionType.Attack:
                yield return ExecuteAttackAction(character, actionData);
                break;

            case BattleActionType.UseItem:
                yield return ExecuteItemAction(character, actionData);
                break;

            case BattleActionType.CastSpell:
                yield return ExecuteSpellAction(character, actionData);
                break;

            case BattleActionType.Defend:
                yield return ExecuteDefendAction(character, actionData);
                break;

            case BattleActionType.Wait:
                yield return ExecuteWaitAction(character, actionData);
                break;

            case BattleActionType.RunAway:
                yield return ExecuteRunAwayAction(character, actionData);
                break;
        }

        actionData.state = ActionDecisionState.ActionExecuted;
        OnActionCompleted?.Invoke(character);
    }

    #region Action Execution Methods

    private IEnumerator ExecuteMoveAction(Character character, EnhancedCharacterActionData actionData)
    {
        Debug.Log($"🚶 {character.CharacterName} moving to {actionData.targetPosition}");

        // Use existing movement system or implement new one
        character.transform.position = actionData.targetPosition;

        yield return new WaitForSeconds(0.5f); // Animation time
    }

    private IEnumerator ExecuteAttackAction(Character character, EnhancedCharacterActionData actionData)
    {
        if (actionData.targetEnemy == null)
        {
            Debug.LogWarning($"Attack action for {character.CharacterName} has no target!");
            yield break;
        }

        Debug.Log($"⚔️ {character.CharacterName} attacking {actionData.targetEnemy.name}");

        // Use existing attack system
        Character targetCharacter = actionData.targetEnemy.GetComponent<Character>();
        if (targetCharacter != null)
        {
            character.AttackTarget(targetCharacter);
        }

        yield return new WaitForSeconds(1f); // Attack animation time
    }

    private IEnumerator ExecuteItemAction(Character character, EnhancedCharacterActionData actionData)
    {
        Debug.Log($"🧪 {character.CharacterName} using item: {actionData.selectedItemName}");

        // Placeholder item usage logic
        yield return UseItem(character, actionData.selectedItemName, actionData.selectedItemIndex, actionData.targetCharacter);

        yield return new WaitForSeconds(0.8f);
    }

    private IEnumerator ExecuteSpellAction(Character character, EnhancedCharacterActionData actionData)
    {
        Debug.Log($"✨ {character.CharacterName} casting spell: {actionData.selectedSpellName}");

        // Placeholder spell casting logic
        yield return CastSpell(character, actionData.selectedSpellName, actionData.targetCharacter, actionData.targetPosition);

        yield return new WaitForSeconds(1.2f);
    }

    private IEnumerator ExecuteDefendAction(Character character, EnhancedCharacterActionData actionData)
    {
        Debug.Log($"🛡️ {character.CharacterName} defending");

        // Apply defend buff (reduce incoming damage, increase AC, etc.)
        ApplyDefendBuff(character);

        yield return new WaitForSeconds(0.3f);
    }

    private IEnumerator ExecuteWaitAction(Character character, EnhancedCharacterActionData actionData)
    {
        Debug.Log($"⏳ {character.CharacterName} waiting");

        // Character does nothing but maintains position
        yield return new WaitForSeconds(0.1f);
    }

    private IEnumerator ExecuteRunAwayAction(Character character, EnhancedCharacterActionData actionData)
    {
        Debug.Log($"🏃 {character.CharacterName} running away");

        // Move character away from enemies or off battlefield
        yield return HandleRunAway(character);

        yield return new WaitForSeconds(1f);
    }

    #endregion

    #region Event Handlers

    private void OnActionTypeSelected(BattleActionType actionType)
    {
        if (currentCharacter == null) return;

        Debug.Log($"🎯 Action type selected: {actionType} for {currentCharacter.CharacterName}");

        // Initialize enhanced action data if needed
        var actionData = currentCharacter.GetEnhancedActionData<EnhancedCharacterActionData>();
        if (actionData == null)
        {
            actionData = new EnhancedCharacterActionData();
            currentCharacter.SetEnhancedActionData(actionData);
        }

        switch (actionType)
        {
            case BattleActionType.Move:
                StartTargetSelectionForMove();
                break;

            case BattleActionType.Attack:
                StartTargetSelectionForAttack();
                break;

            case BattleActionType.UseItem:
                ShowItemSelection();
                break;

            case BattleActionType.CastSpell:
                ShowSpellSelection();
                break;

            case BattleActionType.Defend:
                actionData.SetDefendAction();
                CompleteActionSelection();
                break;

            case BattleActionType.Wait:
                actionData.SetWaitAction();
                CompleteActionSelection();
                break;

            case BattleActionType.RunAway:
                actionData.SetRunAwayAction();
                CompleteActionSelection();
                break;
        }
    }

    private void OnActionWheelClosed()
    {
        if (!isWaitingForTarget)
        {
            CancelActionSelection();
        }
    }

    private void OnItemSelected(string itemName, int itemIndex)
    {
        var actionData = currentCharacter?.GetEnhancedActionData<EnhancedCharacterActionData>();
        if (actionData == null) return;

        // Determine if item requires targeting
        bool requiresTarget = DoesItemRequireTarget(itemName);

        actionData.SetItemAction(itemName, itemIndex, requiresTarget);

        if (requiresTarget)
        {
            StartTargetSelectionForItem();
        }
        else
        {
            CompleteActionSelection();
        }
    }

    private void OnItemSelectionCancelled()
    {
        CancelActionSelection();
    }

    private void OnSpellSelected(string spellName)
    {
        var actionData = currentCharacter?.GetEnhancedActionData<EnhancedCharacterActionData>();
        if (actionData == null) return;

        // Determine spell properties
        var spellInfo = GetSpellInfo(spellName);

        actionData.SetSpellAction(spellName, spellInfo.requiresTarget, spellInfo.isAoE, spellInfo.aoeRadius);

        if (spellInfo.requiresTarget)
        {
            StartTargetSelectionForSpell();
        }
        else
        {
            CompleteActionSelection();
        }
    }

    private void OnSpellSelectionCancelled()
    {
        CancelActionSelection();
    }

    #endregion

    #region Target Selection

    private void StartTargetSelectionForMove()
    {
        Debug.Log("🎯 Select move target...");
        pendingAction = currentCharacter.GetEnhancedActionData<EnhancedCharacterActionData>();
        isWaitingForTarget = true;
        // Show move cursor or indicators
    }

    private void StartTargetSelectionForAttack()
    {
        Debug.Log("🎯 Select attack target...");
        pendingAction = currentCharacter.GetEnhancedActionData<EnhancedCharacterActionData>();
        isWaitingForTarget = true;
        // Show attack cursor or highlight enemies
    }

    private void StartTargetSelectionForItem()
    {
        Debug.Log("🎯 Select item target...");
        pendingAction = currentCharacter.GetEnhancedActionData<EnhancedCharacterActionData>();
        isWaitingForTarget = true;
    }

    private void StartTargetSelectionForSpell()
    {
        Debug.Log("🎯 Select spell target...");
        pendingAction = currentCharacter.GetEnhancedActionData<EnhancedCharacterActionData>();
        isWaitingForTarget = true;
    }

    private void HandleTargetSelection()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;

            // Check for character targets
            if (Physics.Raycast(ray, out hit, Mathf.Infinity, enemyLayerMask | playerLayerMask))
            {
                Character targetCharacter = hit.collider.GetComponent<Character>();
                if (targetCharacter != null)
                {
                    SetCharacterTarget(targetCharacter);
                    return;
                }
            }

            // Check for ground/position targets
            if (Physics.Raycast(ray, out hit, Mathf.Infinity, groundLayerMask))
            {
                SetPositionTarget(hit.point);
                return;
            }
        }

        // Cancel targeting with right click or escape
        if (Input.GetMouseButtonDown(1) || Input.GetKeyDown(KeyCode.Escape))
        {
            CancelTargetSelection();
        }
    }

    private void SetCharacterTarget(Character target)
    {
        if (pendingAction == null) return;

        if (pendingAction.actionType == BattleActionType.Attack && target.CompareTag("Enemy"))
        {
            pendingAction.SetTarget(target.gameObject);
            CompleteActionSelection();
        }
        else if (pendingAction.actionType == BattleActionType.UseItem || pendingAction.actionType == BattleActionType.CastSpell)
        {
            pendingAction.SetTarget(target);
            CompleteActionSelection();
        }
    }

    private void SetPositionTarget(Vector3 position)
    {
        if (pendingAction == null) return;

        if (pendingAction.actionType == BattleActionType.Move)
        {
            pendingAction.SetMoveAction(position);
            CompleteActionSelection();
        }
        else if (pendingAction.actionType == BattleActionType.CastSpell && pendingAction.isAreaOfEffect)
        {
            pendingAction.SetTarget(position);
            CompleteActionSelection();
        }
    }

    private void CancelTargetSelection()
    {
        isWaitingForTarget = false;
        pendingAction = null;
        CancelActionSelection();
    }

    #endregion

    #region Helper Methods

    private void CompleteActionSelection()
    {
        isWaitingForTarget = false;
        pendingAction = null;

        if (currentCharacter != null)
        {
            currentCharacter.SetVisualState(ActionDecisionState.ActionSelected);
            var actionData = currentCharacter.GetEnhancedActionData<EnhancedCharacterActionData>();
            if (actionData != null)
            {
                Debug.Log($"✅ Action selection complete for {currentCharacter.CharacterName}: {actionData.GetActionDescription()}");
            }
        }
    }

    private void CancelActionSelection()
    {
        isWaitingForTarget = false;
        pendingAction = null;

        if (currentCharacter != null)
        {
            var actionData = currentCharacter.GetEnhancedActionData<EnhancedCharacterActionData>();
            if (actionData != null)
                actionData.Reset();

            currentCharacter.SetVisualState(ActionDecisionState.NoAction);
            Debug.Log($"❌ Action selection cancelled for {currentCharacter.CharacterName}");
        }

        currentCharacter = null;
    }

    private void ShowItemSelection()
    {
        if (itemSelectionUI != null)
        {
            itemSelectionUI.ShowItemSelection(currentCharacter);
        }
        else
        {
            Debug.LogWarning("No ItemSelectionUI found - creating placeholder item action");
            // Placeholder: auto-select a health potion
            OnItemSelected("Health Potion", 0);
        }
    }

    private void ShowSpellSelection()
    {
        if (spellSelectionUI != null)
        {
            spellSelectionUI.ShowSpellSelection(currentCharacter);
        }
        else
        {
            Debug.LogWarning("No SpellSelectionUI found - creating placeholder spell action");
            // Placeholder: auto-select a basic spell
            OnSpellSelected("Magic Missile");
        }
    }

    private bool DoesItemRequireTarget(string itemName)
    {
        // Placeholder logic - determine if item needs a target
        return itemName.ToLower().Contains("heal") || itemName.ToLower().Contains("buff") || itemName.ToLower().Contains("restore");
    }

    private (bool requiresTarget, bool isAoE, float aoeRadius) GetSpellInfo(string spellName)
    {
        // Placeholder spell database
        switch (spellName.ToLower())
        {
            case "magic missile":
                return (true, false, 0f);
            case "heal":
                return (true, false, 0f);
            case "fireball":
                return (true, true, 3f);
            case "shield":
                return (false, false, 0f);
            default:
                return (true, false, 0f);
        }
    }

    private IEnumerator UseItem(Character user, string itemName, int itemIndex, Character target)
    {
        Debug.Log($"📦 Using item {itemName} on {(target ? target.CharacterName : "self")}");

        // Try to find and use the actual item from inventory
        bool itemConsumed = false;
        var inventory = user.GetComponent<Inventory>();

        if (inventory != null)
        {
            // Try to find the item in the inventory
            var miscItems = inventory.Miscellaneous;
            foreach (var slot in miscItems)
            {
                if (slot.item != null && slot.item.itemName == itemName && slot.quantity > 0)
                {
                    if (slot.item is MiscellaneousItem miscItem && miscItem.isConsumable)
                    {
                        // Use the item effect
                        Character effectTarget = target ?? user;
                        miscItem.UseItem(effectTarget);

                        // Remove one from inventory
                        inventory.RemoveItem(slot.item, 1);
                        itemConsumed = true;

                        Debug.Log($"💚 {user.CharacterName} used {itemName} on {effectTarget.CharacterName}");
                        break;
                    }
                }
            }
        }

        // If no ScriptableObject item found, try CombatDataTransfer session data
        if (!itemConsumed && CombatDataTransfer.HasValidSession())
        {
            var session = CombatDataTransfer.GetCurrentSession();
            var playerData = session.playerTeam.Find(p =>
                p.characterName == user.CharacterName ||
                user.CharacterName.StartsWith(p.characterName));

            if (playerData != null && playerData.miscItems != null)
            {
                // Remove item from session data
                for (int i = 0; i < playerData.miscItems.Count; i++)
                {
                    if (playerData.miscItems[i] == itemName)
                    {
                        playerData.miscItems.RemoveAt(i);
                        itemConsumed = true;

                        // Apply basic effects based on item name
                        Character effectTarget = target ?? user;
                        ApplyItemEffectByName(itemName, effectTarget);

                        Debug.Log($"💚 {user.CharacterName} used {itemName} on {effectTarget.CharacterName} (from session data)");
                        break;
                    }
                }
            }
        }

        // Fallback - basic effects without consumption
        if (!itemConsumed)
        {
            Debug.LogWarning($"📦 Could not find consumable item {itemName} in {user.CharacterName}'s inventory - applying basic effect");
            Character effectTarget = target ?? user;
            ApplyItemEffectByName(itemName, effectTarget);
        }

        yield return null;
    }

    /// <summary>
    /// Apply item effects based on item name (fallback method)
    /// </summary>
    private void ApplyItemEffectByName(string itemName, Character target)
    {
        string lowerName = itemName.ToLower();

        if (lowerName.Contains("heal") || lowerName.Contains("potion"))
        {
            target.Heal(20); // Standard healing amount
            Debug.Log($"💚 {target.CharacterName} healed for 20 HP from {itemName}");
        }
        else if (lowerName.Contains("antidote"))
        {
            // Could add poison removal here if implemented
            target.Heal(5); // Minor healing from antidote
            Debug.Log($"💚 {target.CharacterName} recovered from {itemName}");
        }
        else if (lowerName.Contains("bread") || lowerName.Contains("food"))
        {
            target.Heal(10); // Minor healing from food
            Debug.Log($"💚 {target.CharacterName} recovered 10 HP from {itemName}");
        }
        else
        {
            // Generic beneficial effect
            target.Heal(15);
            Debug.Log($"💚 {target.CharacterName} gained 15 HP from {itemName}");
        }
    }

    private IEnumerator CastSpell(Character caster, string spellName, Character target, Vector3 targetPosition)
    {
        Debug.Log($"🔮 Casting {spellName} from {caster.CharacterName}");

        // Placeholder spell effects
        switch (spellName.ToLower())
        {
            case "magic missile":
                if (target != null)
                {
                    target.TakeDamage(15);
                    Debug.Log($"💥 {target.CharacterName} hit by Magic Missile for 15 damage");
                }
                break;

            case "heal":
                if (target != null)
                {
                    target.Heal(25);
                    Debug.Log($"💚 {target.CharacterName} healed for 25 HP");
                }
                break;

            case "fireball":
                // AoE damage around target position
                Debug.Log($"🔥 Fireball explodes at {targetPosition}");
                break;
        }

        yield return null;
    }

    private void ApplyDefendBuff(Character character)
    {
        // Placeholder: apply defensive buff
        Debug.Log($"🛡️ {character.CharacterName} gains defensive stance");
        // TODO: Implement actual defensive bonuses
    }

    private IEnumerator HandleRunAway(Character character)
    {
        // Placeholder: move character away from combat
        Vector3 runDirection = -character.transform.forward;
        Vector3 runTarget = character.transform.position + runDirection * 5f;

        character.transform.position = runTarget;

        Debug.Log($"🏃 {character.CharacterName} retreats to {runTarget}");
        yield return null;
    }

    #endregion
}
