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

[System.Serializable]
public class InventorySlot
{
    public Item item;
    public int quantity;
    public bool isEquipped;

    public InventorySlot(Item item, int quantity = 1, bool equipped = false)
    {
        this.item = item;
        this.quantity = quantity;
        this.isEquipped = equipped;
    }
}

public class Inventory : MonoBehaviour
{
    [Header("Inventory Settings")]
    public int maxWeaponSlots = 10;
    public int maxArmorSlots = 15;
    public int maxMiscSlots = 20;

    [SerializeField] private List<InventorySlot> weapons = new List<InventorySlot>();
    [SerializeField] private List<InventorySlot> armor = new List<InventorySlot>();
    [SerializeField] private List<InventorySlot> miscellaneous = new List<InventorySlot>();

    // Equipment slots
    [SerializeField] private WeaponItem equippedWeapon;
    [SerializeField] private ArmorItem equippedHelmet;
    [SerializeField] private ArmorItem equippedChest;
    [SerializeField] private ArmorItem equippedLegs;
    [SerializeField] private ArmorItem equippedFeet;
    [SerializeField] private ArmorItem equippedHands;
    [SerializeField] private ArmorItem equippedArms;
    [SerializeField] private ArmorItem equippedShield;

    public List<InventorySlot> Weapons => weapons;
    public List<InventorySlot> Armor => armor;
    public List<InventorySlot> Miscellaneous => miscellaneous;

    public WeaponItem EquippedWeapon => equippedWeapon;

    public bool AddItem(Item item, int quantity = 1)
    {
        if (item == null) return false;

        List<InventorySlot> targetList = GetInventoryListForItem(item);
        int maxSlots = GetMaxSlotsForItem(item);

        if (targetList == null) return false;

        // Check for existing stack if stackable
        if (item is MiscellaneousItem miscItem && miscItem.isStackable)
        {
            var existingSlot = targetList.FirstOrDefault(slot => slot.item == item);
            if (existingSlot != null)
            {
                int maxStack = miscItem.maxStackSize;
                int canAdd = Mathf.Min(quantity, maxStack - existingSlot.quantity);
                existingSlot.quantity += canAdd;
                quantity -= canAdd;

                if (quantity <= 0) return true;
            }
        }

        // Add new slot if we have space
        if (targetList.Count < maxSlots)
        {
            targetList.Add(new InventorySlot(item, quantity));
            Debug.Log($"Added {quantity}x {item.itemName} to inventory");
            return true;
        }

        Debug.LogWarning($"No space in inventory for {item.itemName}");
        return false;
    }

    public bool RemoveItem(Item item, int quantity = 1)
    {
        List<InventorySlot> targetList = GetInventoryListForItem(item);
        if (targetList == null) return false;

        var slot = targetList.FirstOrDefault(s => s.item == item);
        if (slot == null) return false;

        if (slot.quantity >= quantity)
        {
            slot.quantity -= quantity;
            if (slot.quantity <= 0)
            {
                targetList.Remove(slot);
            }
            Debug.Log($"Removed {quantity}x {item.itemName} from inventory");
            return true;
        }

        return false;
    }

    public bool HasItem(Item item, int quantity = 1)
    {
        List<InventorySlot> targetList = GetInventoryListForItem(item);
        if (targetList == null) return false;

        var slot = targetList.FirstOrDefault(s => s.item == item);
        return slot != null && slot.quantity >= quantity;
    }

    public bool EquipWeapon(WeaponItem weapon)
    {
        if (!HasItem(weapon)) return false;

        // Unequip current weapon
        if (equippedWeapon != null)
        {
            UnequipWeapon();
        }

        equippedWeapon = weapon;

        // Mark as equipped in inventory
        var slot = weapons.FirstOrDefault(s => s.item == weapon);
        if (slot != null)
        {
            slot.isEquipped = true;
        }

        Debug.Log($"Equipped {weapon.itemName}");
        return true;
    }

    public bool UnequipWeapon()
    {
        if (equippedWeapon == null) return false;

        // Mark as not equipped in inventory
        var slot = weapons.FirstOrDefault(s => s.item == equippedWeapon);
        if (slot != null)
        {
            slot.isEquipped = false;
        }

        Debug.Log($"Unequipped {equippedWeapon.itemName}");
        equippedWeapon = null;
        return true;
    }

    public bool EquipArmor(ArmorItem armorItem)
    {
        if (!HasItem(armorItem)) return false;

        switch (armorItem.armorSlot)
        {
            case ArmorSlot.Head:
                if (equippedHelmet != null) UnequipArmor(equippedHelmet);
                equippedHelmet = armorItem;
                break;
            case ArmorSlot.Chest:
                if (equippedChest != null) UnequipArmor(equippedChest);
                equippedChest = armorItem;
                break;
            case ArmorSlot.Legs:
                if (equippedLegs != null) UnequipArmor(equippedLegs);
                equippedLegs = armorItem;
                break;
            case ArmorSlot.Feet:
                if (equippedFeet != null) UnequipArmor(equippedFeet);
                equippedFeet = armorItem;
                break;
            case ArmorSlot.Hands:
                if (equippedHands != null) UnequipArmor(equippedHands);
                equippedHands = armorItem;
                break;
            case ArmorSlot.Arms:
                if (equippedArms != null) UnequipArmor(equippedArms);
                equippedArms = armorItem;
                break;
            case ArmorSlot.Shield:
                if (equippedShield != null) UnequipArmor(equippedShield);
                equippedShield = armorItem;
                break;
        }

        // Mark as equipped in inventory
        var slot = armor.FirstOrDefault(s => s.item == armorItem);
        if (slot != null)
        {
            slot.isEquipped = true;
        }

        Debug.Log($"Equipped {armorItem.itemName}");
        return true;
    }

    public bool UnequipArmor(ArmorItem armorItem)
    {
        bool wasEquipped = false;

        if (equippedHelmet == armorItem) { equippedHelmet = null; wasEquipped = true; }
        else if (equippedChest == armorItem) { equippedChest = null; wasEquipped = true; }
        else if (equippedLegs == armorItem) { equippedLegs = null; wasEquipped = true; }
        else if (equippedFeet == armorItem) { equippedFeet = null; wasEquipped = true; }
        else if (equippedHands == armorItem) { equippedHands = null; wasEquipped = true; }
        else if (equippedArms == armorItem) { equippedArms = null; wasEquipped = true; }
        else if (equippedShield == armorItem) { equippedShield = null; wasEquipped = true; }

        if (wasEquipped)
        {
            // Mark as not equipped in inventory
            var slot = armor.FirstOrDefault(s => s.item == armorItem);
            if (slot != null)
            {
                slot.isEquipped = false;
            }

            Debug.Log($"Unequipped {armorItem.itemName}");
            return true;
        }

        return false;
    }

    public List<ArmorItem> GetEquippedArmor()
    {
        var equipped = new List<ArmorItem>();
        if (equippedHelmet != null) equipped.Add(equippedHelmet);
        if (equippedChest != null) equipped.Add(equippedChest);
        if (equippedLegs != null) equipped.Add(equippedLegs);
        if (equippedFeet != null) equipped.Add(equippedFeet);
        if (equippedHands != null) equipped.Add(equippedHands);
        if (equippedArms != null) equipped.Add(equippedArms);
        if (equippedShield != null) equipped.Add(equippedShield);
        return equipped;
    }

    public int GetTotalArmorClass()
    {
        int totalAC = 0;
        var equippedArmor = GetEquippedArmor();
        foreach (var armor in equippedArmor)
        {
            totalAC += armor.armorClass;
        }
        return totalAC;
    }

    public (int str, int dex, int con, int wis) GetTotalStatModifiers()
    {
        int str = 0, dex = 0, con = 0, wis = 0;

        var equippedArmor = GetEquippedArmor();
        foreach (var armor in equippedArmor)
        {
            str += armor.strengthModifier;
            dex += armor.dexterityModifier;
            con += armor.constitutionModifier;
            wis += armor.wisdomModifier;
        }

        return (str, dex, con, wis);
    }

    private List<InventorySlot> GetInventoryListForItem(Item item)
    {
        switch (item.itemType)
        {
            case ItemType.Weapon:
                return weapons;
            case ItemType.Armor:
                return armor;
            case ItemType.Miscellaneous:
            case ItemType.Consumable:
            case ItemType.Tool:
            case ItemType.Accessory:
                return miscellaneous;
            default:
                return null;
        }
    }

    private int GetMaxSlotsForItem(Item item)
    {
        switch (item.itemType)
        {
            case ItemType.Weapon:
                return maxWeaponSlots;
            case ItemType.Armor:
                return maxArmorSlots;
            case ItemType.Miscellaneous:
            case ItemType.Consumable:
            case ItemType.Tool:
            case ItemType.Accessory:
                return maxMiscSlots;
            default:
                return 0;
        }
    }
}