using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using W.o.N_Stats;

public class StatDisplay : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
    private CharacterStat _stat;
    public CharacterStat Stat
    {
        get { return _stat; }
        set
        {
            _stat = value;
            UpdateStatValue();
        }
    }

    [SerializeField] Text valueText;
    [SerializeField] StatTooltip tooltip;

    private bool showingTooltip;

    private void OnValidate()
    {
        Text[] texts = GetComponentsInChildren<Text>();

        if (texts.Length >= 1)
        {
            valueText = texts[0];
        }
        else
        {
            Debug.LogError("Not enough Text components in children. Make sure you have at least 1 Text component for the value.");
        }

        if (tooltip == null)
            tooltip = FindObjectOfType<StatTooltip>();
    }

    public void OnPointerEnter(PointerEventData eventData)
    {
        tooltip.ShowTooltip(Stat, valueText.text, GetStatName()); // Pass the value and name here
        showingTooltip = true;
    }

    public void OnPointerExit(PointerEventData eventData)
    {
        tooltip.HideTooltip();
        showingTooltip = false;
    }

    public void UpdateStatValue()
    {
        valueText.text = _stat.Value.ToString();
        if (showingTooltip)
        {
            tooltip.ShowTooltip(Stat, valueText.text, GetStatName()); // Pass the value and name here
        }
    }

    // Added method to get the stat name
    private string GetStatName()
    {
        // You may need to customize this based on your specific implementation
        return gameObject.name; // For example, using the GameObject's name as the stat name
    }

    // Added method to set the stat name
    public void SetStatName(string statName)
    {
        // You can use this method to set the stat name if needed
    }
}

///
//StatDisplay Component
//This Unity component handles displaying the stat value on the UI and showing a tooltip when the user interacts with the stat.

//Fields:

//_stat: The CharacterStat being displayed.
//valueText: The UI Text component showing the stat value.
//tooltip: The StatTooltip component for displaying detailed information.
//Properties and Methods:

//Stat: Property for setting and updating the displayed stat value.
//OnValidate(): Ensures that the necessary UI components are assigned in the Unity Editor.
//OnPointerEnter(PointerEventData eventData): Shows the tooltip when the pointer enters the stat display area.
//OnPointerExit(PointerEventData eventData): Hides the tooltip when the pointer exits the stat display area.
//UpdateStatValue(): Updates the displayed stat value and the tooltip if it is showing.
//GetStatName(): Retrieves the name of the stat, using the GameObject's name as a default.
///


using UnityEngine;
using W.o.N_Stats;

public class StatPanel : MonoBehaviour
{
    [SerializeField] StatDisplay[] statDisplays;
    [SerializeField] string[] statNames;

    private CharacterStat[] stats;

    private void OnValidate()
    {
        statDisplays = GetComponentsInChildren<StatDisplay>();
        UpdateStatNames();
    }

    void Start()
    {
        // No need to call UpdateStatNames here, as it's already called in OnValidate
    }

    public void SetStats(params CharacterStat[] charStats)
    {
        stats = charStats;

        if (stats.Length > statDisplays.Length)
        {
            Debug.LogError("Not Enough Stat Displays!");
            return;
        }

        for (int i = 0; i < statDisplays.Length; i++)
        {
            statDisplays[i].gameObject.SetActive(i < stats.Length);

            if (i < stats.Length)
            {
                statDisplays[i].Stat = stats[i];
            }
        }
    }

    public void UpdateStatValues()
    {
        for (int i = 0; i < stats.Length; i++)
        {
            statDisplays[i].UpdateStatValue();
        }
    }

     public void UpdateStatNames()
    {
        for (int i = 0; i < statNames.Length; i++)
        {
            // Check if the index is within the array bounds
            if (i < statDisplays.Length)
            {
                statDisplays[i].SetStatName(statNames[i]);
            }
        }
    }

    // Define methods to get stat modifiers
    public float GetHealthModifier()
    {
        return GetStatModifier(StatModType.Flat, stats[0]);
    }

    public float GetManaModifier()
    {
        return GetStatModifier(StatModType.Flat, stats[1]);
    }

    public float GetDefenceModifier()
    {
        return GetStatModifier(StatModType.Flat, stats[2]);
    }

    public float GetAttackModifier()
    {
        return GetStatModifier(StatModType.Flat, stats[3]);
    }

    public float GetAttackSpeedModifier()
    {
        return GetStatModifier(StatModType.Flat, stats[4]);
    }

    public float GetCriticalModifier()
    {
        return GetStatModifier(StatModType.Flat, stats[5]);
    }

    public float GetLifeStealModifier()
    {
        return GetStatModifier(StatModType.Flat, stats[6]);
    }

    public float GetRangeModifier()
    {
        return GetStatModifier(StatModType.Flat, stats[7]);
    }

    public float GetElementalMasteryModifier()
    {
        return GetStatModifier(StatModType.Flat, stats[8]);
    }


    public float GetSpeedModifier()
    {
        return GetStatModifier(StatModType.Flat, stats[9]);
    }

    public float GetCooldownModifier()
    {
        return GetStatModifier(StatModType.Flat, stats[10]);
    }

    public float GetKnockbackModifier()
    {
        return GetStatModifier(StatModType.Flat, stats[11]);
    }


    public float GetRecoveryModifier()
    {
        return GetStatModifier(StatModType.Flat, stats[12]);
    }


    public float GetEvadeModifier()
    {
        return GetStatModifier(StatModType.Flat, stats[13]);
    }

    public float GetFortuneModifier()
    {
        return GetStatModifier(StatModType.Flat, stats[14]);
    }

    // Helper method to get the stat modifier
    private float GetStatModifier(StatModType modType, CharacterStat stat)
    {
        float totalModifier = 0f;

        foreach (var modifier in stat.StatModifiers)
        {
            if (modifier.Type == modType)
            {
                totalModifier += modifier.Value;
            }
        }

        return totalModifier;
    }
}

using UnityEngine;
using UnityEngine.UI;
using W.o.N_Stats;

public class Character : MonoBehaviour
{
    [Header("Stats")]
    public CharacterStat Health;
    public CharacterStat Mana;
    public CharacterStat Defence;
    public CharacterStat Attack;
    public CharacterStat AttackSpeed;
    public CharacterStat Critical;
    public CharacterStat LifeSteal;
    public CharacterStat Range;
    public CharacterStat ElementalMastery;
    public CharacterStat Speed;
    public CharacterStat Cooldown;
    public CharacterStat Knockback;
    public CharacterStat Recovery;
    public CharacterStat Evade;
    public CharacterStat Fortune;

    public int maxHealth;
    public int maxMana;
    public int maxDefense;
    public int maxAttack;
    public float maxAttackSpeed;
    public int maxCritical;
    public float maxLifeSteal;
    public float maxRange;
    public float maxElementalMastery;
    public float maxSpeed;
    public float maxCooldown;
    public float maxKnockback;
    public float maxRecovery;
    public float maxEvade;
    public float maxFortune;

    [Header("Public")]
    public Inventory Inventory;
    public EquipmentPanel EquipmentPanel;
    public Player player; // Reference to the Player script
    private WeaponTypeDetector weaponTypeDetector;

    
    [Header("Selected Seed")]
    public SeedItem selectedSeed; // Reference to the selected seed item
    public Color normalColor = Color.white;
    public Color selectedColor = new Color(0.5f, 0.5f, 0.5f, 1f);
    private static Character instance; // Reference to the character instance

    [Header("Serialize Field")]
    [SerializeField] CraftingWindow craftingWindow;
    [SerializeField] StatPanel statPanel;
    [SerializeField] ItemTooltip itemTooltip;
    [SerializeField] Image draggableItem;
    [SerializeField] DropItemArea dropItemArea;
    [SerializeField] QuestionDialog reallyDropItemDialog;

    private BaseItemSlot dragItemSlot;

    private void OnValidate()
    {
        if (itemTooltip == null)
            itemTooltip = FindObjectOfType<ItemTooltip>();
    }

    public void Awake()
    {
        statPanel.SetStats(Health, Mana, Defence, Attack, AttackSpeed, Critical, LifeSteal, Range, ElementalMastery, Speed, Cooldown, Knockback, Recovery, Evade, Fortune);
        instance = this; // Assign the current instance to the static variable
        statPanel.UpdateStatValues();
        // Get the WeaponTypeDetector component
        weaponTypeDetector = GetComponent<WeaponTypeDetector>();

        // Setup Events:
        // Right Click
        Inventory.OnRightClickEvent += InventoryRightClick;
        EquipmentPanel.OnRightClickEvent += EquipmentPanelRightClick;
        // Pointer Enter
        Inventory.OnPointerEnterEvent += ShowTooltip;
        EquipmentPanel.OnPointerEnterEvent += ShowTooltip;
        craftingWindow.OnPointerEnterEvent += ShowTooltip;
        // Pointer Exit
        Inventory.OnPointerExitEvent += HideTooltip;
        EquipmentPanel.OnPointerExitEvent += HideTooltip;
        craftingWindow.OnPointerExitEvent += HideTooltip;
        // Begin Drag
        Inventory.OnBeginDragEvent += BeginDrag;
        EquipmentPanel.OnBeginDragEvent += BeginDrag;
        // End Drag
        Inventory.OnEndDragEvent += EndDrag;
        EquipmentPanel.OnEndDragEvent += EndDrag;
        // Drag
        Inventory.OnDragEvent += Drag;
        EquipmentPanel.OnDragEvent += Drag;
        // Drop
        Inventory.OnDropEvent += Drop;
        EquipmentPanel.OnDropEvent += Drop;
        dropItemArea.OnDropEvent += DropItemOutsideUI;

    }

    public static Character GetInstance()
    {
        if (instance == null)
        {
            instance = FindObjectOfType<Character>(); // Find the Character instance in the scene
        }
        return instance;
    }
    
    private void Update()
    {
        // Change the following line to continuously update stats in real-time
        UpdateStatValues();
    }

    private void InventoryRightClick(BaseItemSlot itemSlot)
    {
        // Deselect the currently selected seed if the clicked item is not a seed item
        if (!(itemSlot.Item is SeedItem))
        {
            DeselectSeed();
        }

        // Handle the action for the clicked item
        if (itemSlot.Item is EquippableItem)
        {
            Equip((EquippableItem)itemSlot.Item);
        }
        else if (itemSlot.Item is UsableItem)
        {
            // Use the Usable Item
            UsableItem usableItem = (UsableItem)itemSlot.Item;
            usableItem.Use(player); // Assuming 'player' is a reference to the Player script
            Inventory.RemoveItem(usableItem); // Remove the used item from the inventory
        }
        else if (itemSlot.Item is SeedItem)
        {
            SeedItem seedItem = (SeedItem)itemSlot.Item;

            // If the clicked seed is the same as the currently selected seed, deselect it
            if (selectedSeed == seedItem)
            {
                DeselectSeed();
            }
            else // If the clicked seed is different from the currently selected one, select it
            {
                // Check if there's a previously selected seed, and deselect it
                if (selectedSeed != null)
                {
                    DeselectSeed();
                }

                selectedSeed = seedItem;
                Debug.Log("Selected seed: " + selectedSeed.name);
                UpdateSeedTintColors();
            }
        }

        UpdateMax();
        AdjustStatsIfNeeded();
    }

    private void DeselectSeed()
    {
        if (selectedSeed != null)
        {
            Debug.Log("Deselected seed: " + selectedSeed.name);
            selectedSeed = null;
            UpdateSeedTintColors();
        }
    }

    private void UpdateSeedTintColors()
    {
        // Update tint colors of seed items based on selection state
        foreach (BaseItemSlot itemSlot in Inventory.ItemSlots)
        {
            if (itemSlot.Item is SeedItem seedItem)
            {
                Image seedImage = itemSlot.GetComponent<Image>();
                if (seedItem == selectedSeed)
                {
                    seedImage.color = selectedColor;
                }
                else
                {
                    seedImage.color = normalColor;
                }
            }
        }
    }

    private void EquipmentPanelRightClick(BaseItemSlot itemSlot)
    {
        if (itemSlot.Item is EquippableItem)
        {
            Unequip((EquippableItem)itemSlot.Item);
        }
        UpdateMax();
    }

    private void ShowTooltip(BaseItemSlot itemSlot)
    {
        if (itemSlot.Item != null)
        {
            itemTooltip.ShowTooltip(itemSlot.Item);
        }
    }

    private void HideTooltip(BaseItemSlot itemSlot)
    {
        if (itemTooltip.gameObject.activeSelf)
        {
            itemTooltip.HideTooltip();
        }
    }

    private void BeginDrag(BaseItemSlot itemSlot)
    {
        if (itemSlot.Item != null && !(itemSlot is EquipmentSlot))
        {
            dragItemSlot = itemSlot;
            draggableItem.sprite = itemSlot.Item.Icon;
            draggableItem.transform.position = Input.mousePosition;
            draggableItem.gameObject.SetActive(true);
        }
    }

    private void Drag(BaseItemSlot itemSlot)
    {
        if (dragItemSlot != null)
        {
            draggableItem.transform.position = Input.mousePosition;
        }
    }

    private void EndDrag(BaseItemSlot itemSlot)
    {
        dragItemSlot = null;
        draggableItem.gameObject.SetActive(false);
    }

    private void Drop(BaseItemSlot dropItemSlot)
{
    if (dragItemSlot == null) return;

    // Case 1: Prevent dropping equippable items into equipment slots if the item is already equipped
    if (dragItemSlot.Item is EquippableItem && dropItemSlot is EquipmentSlot)
    {
        EndDrag(null);
        return;
    }

    // Case 2: Try to stack the item if dropItemSlot can accept stacks
    if (dropItemSlot.CanAddStack(dragItemSlot.Item))
    {
        AddStacks(dropItemSlot);
    }
    // Case 3: Swap items if both slots can receive each other's items
    else if (dropItemSlot.CanReceiveItem(dragItemSlot.Item) && dragItemSlot.CanReceiveItem(dropItemSlot.Item))
    {
        SwapItems(dropItemSlot, dragItemSlot);
    }
    // Case 4: Move item to dropItemSlot if it’s a valid drop
    else if (dropItemSlot.CanReceiveItem(dragItemSlot.Item))
    {
        MoveItemToSlot(dropItemSlot, dragItemSlot);
        RemoveItemFromSlot(dragItemSlot);
    }

    EndDrag(null);
}

    private void MoveItemToSlot(BaseItemSlot dropItemSlot, BaseItemSlot dragItemSlot)
{
    dropItemSlot.Item = dragItemSlot.Item;
    dropItemSlot.Amount = dragItemSlot.Amount;
}

private void RemoveItemFromSlot(BaseItemSlot itemSlot)
{
    itemSlot.Item = null;
    itemSlot.Amount = 0;
}

    private void AddStacks(BaseItemSlot dropItemSlot)
    {
        int numAddableStacks = dropItemSlot.Item.MaximumStacks - dropItemSlot.Amount;
        int stacksToAdd = Mathf.Min(numAddableStacks, dragItemSlot.Amount);

        dropItemSlot.Amount += stacksToAdd;
        dragItemSlot.Amount -= stacksToAdd;
    }

    private void SwapItems(BaseItemSlot dropItemSlot, BaseItemSlot originalSlot)
    {
        Item draggedItem = originalSlot.Item;
        int draggedItemAmount = originalSlot.Amount;

        originalSlot.Item = dropItemSlot.Item;
        originalSlot.Amount = dropItemSlot.Amount;

        dropItemSlot.Item = draggedItem;
        dropItemSlot.Amount = draggedItemAmount;

        if (originalSlot is EquipmentSlot)
        {
            ((EquippableItem)originalSlot.Item)?.Equip(this);
        }

        if (dropItemSlot is EquipmentSlot)
        {
            ((EquippableItem)dropItemSlot.Item)?.Equip(this);
        }

        statPanel.UpdateStatValues();
    }

   private void DropItemOutsideUI()
{
    if (dragItemSlot == null) return;

    if (dragItemSlot.Item != null)
    {
        // Check if the dialog should be shown or bypassed
        if (reallyDropItemDialog.ShouldAskAgain())
        {
            // Show the confirmation dialog
            reallyDropItemDialog.Show();
            BaseItemSlot slot = dragItemSlot;
            reallyDropItemDialog.OnYesEvent += () => DestroyItemInSlot(slot);
        }
        else
        {
            // Directly destroy the item if the user opted not to be asked again
            DestroyItemInSlot(dragItemSlot);
        }
    }
}

    private void DestroyItemInSlot(BaseItemSlot itemSlot)
    {
        // If the item is equipped, unequip first
        if (itemSlot is EquipmentSlot)
        {
            EquippableItem equippableItem = (EquippableItem)itemSlot.Item;
            equippableItem.Unequip(this);
            AdjustStatsIfNeeded();
            UpdateStatValues();
        }

        itemSlot.Item.Destroy();
        itemSlot.Item = null;
    }

    public void Equip(EquippableItem item)
    {
        if (Inventory.RemoveItem(item))
        {
            EquippableItem previousItem;
            if (EquipmentPanel.AddItem(item, out previousItem))
            {
                if (previousItem != null)
                {
                    Inventory.AddItem(previousItem);
                    previousItem.Unequip(this);
                }
                item.Equip(this);
            }
            else
            {
                Inventory.AddItem(item);
            }

            // Update stats immediately after equipping
            UpdateStatValues();
            AdjustStatsIfNeeded();

            // Update weapon type
            weaponTypeDetector.ManualUpdateWeaponType();
        }
    }

    public void Unequip(EquippableItem item)
    {
        if (Inventory.CanAddItem(item) && EquipmentPanel.RemoveItem(item))
        {
            item.Unequip(this);
            // Update stats immediately after unequipping
            UpdateStatValues();
            Inventory.AddItem(item);

            // Reset current stats to their maximum values
            AdjustStatsIfNeeded();

            // Update weapon type
            weaponTypeDetector.ManualUpdateWeaponType();
        }
    }

    // Method to call SetCurrentStatsToMax from the Player script
    public void AdjustStatsIfNeeded()
    {
        player.AdjustStatsIfNeeded();
    }

    public void UpdateMax()
    {
        player.UpdateMaxStats();
    }

    private ItemContainer openItemContainer;

public void OpenChest(Chest chest)
{
    OpenItemContainer(chest);
}

public void CloseChest(Chest chest)
{
    CloseItemContainer(chest);
}


private void TransferToItemContainer(BaseItemSlot itemSlot)
{
    Item item = itemSlot.Item;
    if (item != null && openItemContainer.CanAddItem(item))
    {
        Inventory.RemoveItem(item);
        openItemContainer.AddItem(item);
    }
}

private void TransferToInventory(BaseItemSlot itemSlot)
{
    Item item = itemSlot.Item;
    if (item != null && Inventory.CanAddItem(item))
    {
        openItemContainer.RemoveItem(item);
        Inventory.AddItem(item);
    }
}

public void OpenItemContainer(ItemContainer itemContainer)
{
    openItemContainer = itemContainer;

    Inventory.OnRightClickEvent -= InventoryRightClick;
    Inventory.OnRightClickEvent += TransferToItemContainer;

    itemContainer.OnRightClickEvent += TransferToInventory;

    itemContainer.OnPointerEnterEvent += ShowTooltip;
    itemContainer.OnPointerExitEvent += HideTooltip;
    itemContainer.OnBeginDragEvent += BeginDrag;
    itemContainer.OnEndDragEvent += EndDrag;
    itemContainer.OnDragEvent += Drag;
    itemContainer.OnDropEvent += Drop;
}

public void CloseItemContainer(ItemContainer itemContainer)
{
    openItemContainer = null;

    Inventory.OnRightClickEvent += InventoryRightClick;
    Inventory.OnRightClickEvent -= TransferToItemContainer;

    itemContainer.OnRightClickEvent -= TransferToInventory;

    itemContainer.OnPointerEnterEvent -= ShowTooltip;
    itemContainer.OnPointerExitEvent -= HideTooltip;
    itemContainer.OnBeginDragEvent -= BeginDrag;
    itemContainer.OnEndDragEvent -= EndDrag;
    itemContainer.OnDragEvent -= Drag;
    itemContainer.OnDropEvent -= Drop;
}

    public void UpdateStatValues()
    {
        statPanel.UpdateStatValues();
    }

       public void LoadStatsFromData(PlayerData data)
    {
        // Assign loaded max stats
        maxHealth = data.maxHealth;
        maxMana = data.maxMana;
        maxDefense = data.maxDefense;
        maxAttack = data.maxAttack;
        maxAttackSpeed = data.maxAttackSpeed;
        maxCritical = data.maxCritical;
        maxLifeSteal = data.maxLifeSteal;
        maxRange = data.maxRange;
        maxElementalMastery = data.maxElementalMastery;
        maxSpeed = data.maxSpeed;
        maxCooldown = data.maxCooldown;
        maxKnockback = data.maxKnockback;
        maxRecovery = data.maxRecovery;
        maxEvade = data.maxEvade;
        maxFortune = data.maxFortune;

        // Update CharacterStat fields
        Health.BaseValue = data.currentHealth;
        Mana.BaseValue = data.currentMana;
        Defence.BaseValue = data.currentDefense;
        Attack.BaseValue = data.currentAttack;
        AttackSpeed.BaseValue = data.currentAttackSpeed;
        Critical.BaseValue = data.currentCritical;
        LifeSteal.BaseValue = data.currentLifeSteal;
        Range.BaseValue = data.currentRange;
        ElementalMastery.BaseValue = data.currentElementalMastery;
        Speed.BaseValue = data.currentSpeed;
        Cooldown.BaseValue = data.currentCooldown;
        Knockback.BaseValue = data.currentKnockback;
        Recovery.BaseValue = data.currentRecovery;
        Evade.BaseValue = data.currentEvade;
        Fortune.BaseValue = data.currentFortune;

        // Update UI or any other components
        UpdateStatValues(); // Assuming this method updates UI with current stat values
    }

    public void UpdateMaxStats()
    {
        maxHealth = Mathf.RoundToInt(Health.Value);
        maxMana = Mathf.RoundToInt(Mana.Value);
        maxDefense = Mathf.RoundToInt(Defence.Value);
        maxAttack = Mathf.RoundToInt(Attack.Value);
        maxAttackSpeed = AttackSpeed.Value;
        maxCritical = Mathf.RoundToInt(Critical.Value);
        maxLifeSteal = LifeSteal.Value;
        maxRange = Range.Value;
        maxElementalMastery = ElementalMastery.Value;
        maxSpeed = Speed.Value;
        maxCooldown = Cooldown.Value;
        maxKnockback = Knockback.Value;
        maxRecovery = Recovery.Value;
        maxEvade = Evade.Value;
        maxFortune = Fortune.Value;
    }
}


i need to fix the update character stats values to also update character max stats values please