using UnityEngine;
    using UnityEngine.UI;
    using W.o.N_Stats;
    using System;
    using System.Collections;
    using UnityEngine.EventSystems;
    using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

    public class Player : MonoBehaviour
    {
        #region Stats Name And Player Info

         // Property to set or get the player name
        public string PlayerName
        {
            get { return PlayerPrefs.GetString("PlayerName", "Default Name"); }
            set { PlayerPrefs.SetString("PlayerName", value); }
        }

        [Header("Level and Experience")]
        public int PlayerLevel;
        public int CurrentEXP;
        public int ExpToLevelUp;

        [Header("Health")]
        public int currentHealth;
        public int maxHealth;

        [Header("Mana")]
        public int currentMana;
        public int maxMana;

        [Header("Defense")]
        public int currentDefense;
        public int maxDefense;

        [Header("Attack")]
        public int currentAttack;
        public int maxAttack;

        [Header("Attack Speed")]
        public float currentAttackSpeed;
        public float maxAttackSpeed;

        [Header("Critical")]
        public int currentCritical;
        public int maxCritical;

        [Header("Life Steal")]
        public float currentLifeSteal;
        public float maxLifeSteal;

        [Header("Range")]
        public float currentRange;
        public float maxRange;

        [Header("Elemental Mastery")]
        public float currentElementalMastery;
        public float maxElementalMastery;

        [Header("Cooldown")]
        public float currentCooldown;
        public float maxCooldown;

        [Header("Knockback")]
        public float currentKnockback;
        public float maxKnockback;

        [Header("Speed")]
        public float currentSpeed;
        public float maxSpeed;

        [Header("Recovery")]
        public float currentRecovery;
        public float maxRecovery;

        [Header("Evade")]
        public float currentEvade;
        public float maxEvade;

        [Header("Fortune")]
        public float currentFortune;
        public float maxFortune;

        [Header("Character and Stat Panel")]
        public Character character;
        public StatPanel statPanel;
        public PlayerSkill playerSkill;
        public Inventory inventory;
        public EquipmentPanel equipmentPanel;
        [Header("Hurt Effect")]
        [SerializeField] private GameObject hurtParticlePrefab; 

        [SerializeField]
        private PlayerDamageIndicator damageIndicatorScript; // Reference to the PlayerDamageIndicator script

        public PlayerLevelUpText levelUpTextScript; // Reference to the PlayerLevelUpText script

        #endregion

        private float lastDamageTime = 0f; // Track the time of the last damage taken or mana used
        private float lastRecoveryTime = 0f;
        private bool hasEquippedItemRecently = false;
        private float timeSinceEquippingItem = 0f;
        private float equipItemRecoveryDelay = 30f;

        [Header("Player Camera")]
        public Camera playerCamera; // Assign the player's camera directly in the inspector
        [Header("Button Assignment")]

        public float attackRange = 2f;
        public LayerMask mobsLayer; // Specify the layer for "Mobs"

        [SerializeField] private bool displayGizmo = true; // Toggle to display Gizmo

        // Event to notify UI that stats have changed
        public Action OnStatsChanged { get; set; }

        private void OnDrawGizmos()
        {
            if (displayGizmo)
            {
                Gizmos.color = Color.green;
                Gizmos.DrawWireSphere(transform.position, attackRange);
            }
        }

        // Method to update the player's name
        public void UpdatePlayerName(string newName)
        {
            PlayerName = newName;
        }

        public void TakeDamage(int damage)
        {
            // Spawn the hurt particle effect if the prefab is assigned
            if (hurtParticlePrefab != null)
            {
                GameObject hurtParticle = Instantiate(hurtParticlePrefab, transform.position, Quaternion.identity);
                Destroy(hurtParticle, 0.45f); // Destroy the particle effect after 0.45 seconds
            }

            // Call the ShowDamageText method from PlayerDamageIndicator script and pass the damage value
            if (damageIndicatorScript != null)
            {
                damageIndicatorScript.ShowDamageText(damage);
            }

            // Check if the player can evade
            if (UnityEngine.Random.Range(0f, 100f) <= currentEvade)
            {
                Debug.Log($"{PlayerName} Evaded the Attack & Avoided {damage} Damage!");
            }
            else
            {
                // Calculate actual damage after considering defense
                int actualDamage = Mathf.Max(0, damage - currentDefense);

                // Damage defense first if there's any
                if (currentDefense > 0)
                {
                    int defenseDamage = Mathf.Max(0, damage - actualDamage);
                    currentDefense = Mathf.Max(0, currentDefense - damage);

                    // Log damage taken to defense if defense is greater than 0
                    if (defenseDamage > 0)
                    {
                        Debug.Log($"{PlayerName} Defense took {defenseDamage} damage!");
                    }
                }

                // If defense is reduced to 0, or no defense, damage health
                if (currentDefense == 0)
                {
                    int healthDamage = actualDamage;
                    currentHealth -= healthDamage;

                    // Log the health damage
                    Debug.Log($"{PlayerName} took {healthDamage} damage to health!");

                    // Check if health reaches 0
                    if (currentHealth <= 0)
                    {
                        Debug.Log($"{PlayerName} Died!");

                        // Respawn the player at the saved location and restore all stats to full
                        LoadPlayerData(PlayerName); // Respawn the player using saved data
                    }
                }
            }

            // Update the last damage time to trigger recovery
            lastDamageTime = Time.time;
        }


        private void RespawnPlayer()
        {
            // Restore all stats to full
            SetCurrentStatsToMax(); // Reset current stats to their maximum values

            // Teleport the player back to the saved location using the PlayerSaveLocation script
            PlayerSaveLocation saveLocationScript = GetComponent<PlayerSaveLocation>();
            if (saveLocationScript != null)
            {
                saveLocationScript.TeleportToSavedLocation();
            }
        }

        void Start()
        {
             // Construct the base directory path

            SetStartingStats(); // Call this method to set starting stats
            InitializeStats();
            SetCurrentStatsToMax();
            // Set the initial values for level and experience
            PlayerLevel = 1;
            CurrentEXP = 0;
            ExpToLevelUp = 250;
            
            string baseDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "World Of Normies", "SAVE DATA", PlayerName);

            // Check if the player's directory exists
            if (Directory.Exists(baseDirectory))
            {
                // Construct the full file path for the player's data file
                string filePath = Path.Combine(baseDirectory, $"{PlayerName}_Data.sav");

                // Check if the player's data file exists
                if (File.Exists(filePath))
                {
                    // Load player data from file
                LoadPlayerData(PlayerName);
                }
            }
        }

        private void Update()
        {
            // This Bellow When An Item Is Equipped It Will Update The Stats on Both The UI And The Player
            UpdateMaxStats();

            // Check if enough time has passed since the last damage or mana/defense depletion
            if (!hasEquippedItemRecently && Time.time - lastDamageTime >= 30f)
            {
                // Increment current health, mana, and defense towards their maximum values over time
                if (Time.time - lastRecoveryTime >= 5f) // Check if 5 seconds have passed since last recovery
                {
                    // Increment stats by maxRecovery amount
                    currentHealth = Mathf.Min(maxHealth, currentHealth + Mathf.RoundToInt(maxRecovery));
                    currentMana = Mathf.Min(maxMana, currentMana + Mathf.RoundToInt(maxRecovery));
                    currentDefense = Mathf.Min(maxDefense, currentDefense + Mathf.RoundToInt(maxRecovery));

                    // Update the last recovery time
                    lastRecoveryTime = Time.time;
                }
            }

            // Update the time since equipping an item
            if (hasEquippedItemRecently)
            {
                timeSinceEquippingItem += Time.deltaTime;
                if (timeSinceEquippingItem >= equipItemRecoveryDelay)
                {
                    // Enough time has passed after equipping an item, reset the flag and trigger recovery
                    hasEquippedItemRecently = false;
                    lastDamageTime = Time.time;
                }
            }
        }

    public void LevelUp()
        {
            // Call the LevelUpText method from PlayerLevelUpText script
            if (levelUpTextScript != null)
            {
                levelUpTextScript.ShowLevelUpText();
            }

            PlayerLevel++;
            CurrentEXP -= ExpToLevelUp;
            ExpToLevelUp *= 2;

            // Update character stats
            character.Health.BaseValue += 5 * PlayerLevel;
            character.Mana.BaseValue += 2 * PlayerLevel;
            character.Defence.BaseValue += 1 * PlayerLevel;
            character.Attack.BaseValue += 1 * PlayerLevel;
            character.AttackSpeed.BaseValue += 0.008f * PlayerLevel;
            character.Critical.BaseValue += 0.05F * PlayerLevel;
            character.LifeSteal.BaseValue += 0.5f * PlayerLevel;
            character.Range.BaseValue += 0.015f * PlayerLevel;
            character.ElementalMastery.BaseValue += 0.13f * PlayerLevel;
            character.Cooldown.BaseValue += 0.1f * PlayerLevel;
            character.Knockback.BaseValue += 0.025f * PlayerLevel;
            character.Speed.BaseValue += 0.005f * PlayerLevel;
            character.Recovery.BaseValue += 0.5f * PlayerLevel;
            character.Evade.BaseValue += 0.01f * PlayerLevel;
            character.Fortune.BaseValue += 0.015f * PlayerLevel;

        // Update stat values
        character.UpdateStatValues();

        // Update max stats
        UpdateMaxStats();

        // Set current stats to max
        SetCurrentStatsToMax();

        // Show updated stats on UI
    statPanel.SetStats(character.Health, character.Mana, character.Defence, character.Attack , character.AttackSpeed,  character.Critical, character.LifeSteal, character.Range, character.ElementalMastery, character.Speed, character.Cooldown, character.Knockback, character.Recovery, character.Evade, character.Fortune);
    }
    private void SetStartingStats()
        {
            // Set starting stats for the player based on character stats
            currentHealth = (int)character.Health.Value;
            maxHealth = (int)character.Health.Value;

            currentMana = (int)character.Mana.Value;
            maxMana = (int)character.Mana.Value;

            currentDefense = (int)character.Defence.Value;
            maxDefense = (int)character.Defence.Value;

            currentAttack = (int)character.Attack.Value;
            maxAttack = (int)character.Attack.Value;

            currentAttackSpeed = character.AttackSpeed.Value;
            maxAttackSpeed = character.AttackSpeed.Value;

            currentCritical = (int)character.Critical.Value;
            maxCritical = (int)character.Critical.Value;

            currentLifeSteal = character.LifeSteal.Value;
            maxLifeSteal = character.LifeSteal.Value;

            currentRange = character.Range.Value;
            maxRange = character.Range.Value;

            currentElementalMastery = character.ElementalMastery.Value;
            maxElementalMastery = character.ElementalMastery.Value;

            currentSpeed = character.Speed.Value;
            maxSpeed = character.Speed.Value;

            currentCooldown = character.Cooldown.Value;
            maxCooldown = character.Cooldown.Value;

            currentKnockback = character.Knockback.Value;
            maxKnockback = character.Knockback.Value;

            currentRecovery = character.Recovery.Value;
            maxRecovery = character.Recovery.Value;

            currentEvade = character.Evade.Value;
            maxEvade = character.Evade.Value;

            currentFortune = character.Fortune.Value;
            maxFortune = character.Fortune.Value;

            // Call UpdateStatValues to apply the changes
            character.UpdateStatValues();

            // Update max and current stats
            UpdateMaxStats();
            SetCurrentStatsToMax();
        }
    // Update the maximum stats of the character
    public void UpdateMaxStats()
        {
            // Update max stats for the player based on character stats
            maxHealth = (int)character.Health.Value;
            maxMana = (int)character.Mana.Value;
            maxDefense = (int)character.Defence.Value;
            maxAttack = (int)character.Attack.Value;
            maxAttackSpeed = character.AttackSpeed.Value;
            maxCritical = (int)character.Critical.Value;
            maxLifeSteal = character.LifeSteal.Value;
            maxRange = character.Range.Value;
            maxElementalMastery = character.ElementalMastery.Value;
            maxSpeed = character.Speed.Value;
            maxCooldown = character.Cooldown.Value;
            maxKnockback = character.Knockback.Value;
            maxRecovery = character.Recovery.Value;
            maxEvade = character.Evade.Value;
            maxFortune = character.Fortune.Value;
        }

    // Check if any current stats have changed due to equipping items
    public void CurrentStatsChange()
    {
            // Mark that an item has been equipped recently
            hasEquippedItemRecently = true;
            timeSinceEquippingItem = 0f;
    }

        public void InitializeStats()
    {
        // Update max stats
        UpdateMaxStats();

        // Initialize current stats
        maxHealth = Mathf.RoundToInt(character.Health.Value);
        currentHealth = maxHealth;

        maxMana = Mathf.RoundToInt(character.Mana.Value);
        currentMana = maxMana;

        maxDefense = Mathf.RoundToInt(character.Defence.Value);
        currentDefense = maxDefense;

        maxAttack = Mathf.RoundToInt(character.Attack.Value);
        currentAttack = maxAttack;

        maxAttackSpeed = character.AttackSpeed.Value;
        currentAttackSpeed = maxAttackSpeed;

        maxCritical = Mathf.RoundToInt(character.Critical.Value);
        currentCritical = maxCritical;

        maxLifeSteal = Mathf.RoundToInt(character.LifeSteal.Value);
        currentLifeSteal = maxLifeSteal;

        maxRange = Mathf.RoundToInt(character.Range.Value);
        currentRange = maxRange;

        maxElementalMastery = Mathf.RoundToInt(character.ElementalMastery.Value);
        currentElementalMastery = maxElementalMastery;

        maxSpeed = Mathf.RoundToInt(character.Speed.Value);
        currentSpeed = maxSpeed;

        maxCooldown = character.Cooldown.Value;
        currentCooldown = maxCooldown;

        maxKnockback = Mathf.RoundToInt(character.Knockback.Value);
        currentKnockback = maxKnockback;

        maxRecovery = character.Recovery.Value;
        currentRecovery = maxRecovery;

        maxEvade = character.Evade.Value;
        currentEvade = maxEvade;

        maxFortune = Mathf.RoundToInt(character.Fortune.Value);
        currentFortune = maxFortune;

        // Replace UpdateCurrentStats with the appropriate method
        // (e.g., SetCurrentStatsToMax or any other method that updates your current stats)
        SetCurrentStatsToMax();
    }
        public void SetCurrentStatsToMax()
        {
            currentHealth = maxHealth;
            currentMana = maxMana;
            currentDefense = maxDefense;
            currentAttack = maxAttack;
            currentAttackSpeed = maxAttackSpeed;
            currentCritical = maxCritical;
            currentLifeSteal = maxLifeSteal;
            currentRange = maxRange;
            currentElementalMastery = maxElementalMastery;
            currentCooldown = maxCooldown;
            currentKnockback = maxKnockback;
            currentSpeed = maxSpeed;
            currentRecovery = maxRecovery;
            currentEvade = maxEvade;
            currentFortune = maxFortune;

            // Reset the last recovery time to prevent immediate recovery
            lastRecoveryTime = Time.time;
        }

    public void AdjustStatsIfNeeded()
    {
        // Health
        int newMaxHealth = Mathf.RoundToInt(character.Health.Value);
        if (newMaxHealth < currentHealth)
        {
            currentHealth = newMaxHealth;
        }

        // Mana
        int newMaxMana = Mathf.RoundToInt(character.Mana.Value);
        if (newMaxMana < currentMana)
        {
            currentMana = newMaxMana;
        }

        // Defense
        int newMaxDefense = Mathf.RoundToInt(character.Defence.Value);
        if (newMaxDefense < currentDefense)
        {
            currentDefense = newMaxDefense;
        }

        // Attack
        int newMaxAttack = Mathf.RoundToInt(character.Attack.Value);
        if (newMaxAttack < currentAttack)
        {
            currentAttack = newMaxAttack;
        }

        // Attack Speed
        float newMaxAttackSpeed = character.AttackSpeed.Value;
        if (newMaxAttackSpeed < currentAttackSpeed)
        {
            currentAttackSpeed = newMaxAttackSpeed;
        }

        // Critical
        int newMaxCritical = Mathf.RoundToInt(character.Critical.Value);
        if (newMaxCritical < currentCritical)
        {
            currentCritical = newMaxCritical;
        }

        // LifeSteal
        int newMaxLifeSteal = Mathf.RoundToInt(character.LifeSteal.Value);
        if (newMaxLifeSteal < currentLifeSteal)
        {
            currentLifeSteal = newMaxLifeSteal;
        }

        // Range
        int newMaxRange = Mathf.RoundToInt(character.Range.Value);
        if (newMaxRange < currentRange)
        {
            currentRange = newMaxRange;
        }

        // ElementalMastery
        int newMaxElementalMastery = Mathf.RoundToInt(character.ElementalMastery.Value);
        if (newMaxElementalMastery < currentElementalMastery)
        {
            currentElementalMastery = newMaxElementalMastery;
        }

        // Speed
        float newMaxSpeed = character.Speed.Value;
        if (newMaxSpeed < currentSpeed)
        {
            currentSpeed = newMaxSpeed;
        }

        // Cooldown
        float newMaxCooldown = character.Cooldown.Value;
        if (newMaxCooldown < currentCooldown)
        {
            currentCooldown = newMaxCooldown;
        }

        // Knockback
        int newMaxKnockback = Mathf.RoundToInt(character.Knockback.Value);
        if (newMaxKnockback < currentKnockback)
        {
            currentKnockback = newMaxKnockback;
        }

        // Recovery
        float newMaxRecovery = character.Recovery.Value;
        if (newMaxRecovery < currentRecovery)
        {
            currentRecovery = newMaxRecovery;
        }

        // Evade
        float newMaxEvade = character.Evade.Value;
        if (newMaxEvade < currentEvade)
        {
            currentEvade = newMaxEvade;
        }

        // Fortune
        int newMaxFortune = Mathf.RoundToInt(character.Fortune.Value);
        if (newMaxFortune < currentFortune)
        {
            currentFortune = newMaxFortune;
        }

        CurrentStatsChange();
    }


        public void IncreaseExperience(int amount)
        {
            CurrentEXP += amount;
            while (CurrentEXP >= ExpToLevelUp)
            {
                LevelUp();
            }
        }

        public void AddStats(int healthToAdd, int defenseToAdd, int manaToAdd)
        {
            // Check if adding health would exceed the maximum
            if (currentHealth < maxHealth)
            {
                // Calculate the new health after adding
                int newHealth = currentHealth + healthToAdd;

                // Ensure the new health doesn't exceed the maximum
                newHealth = Mathf.Clamp(newHealth, 0, maxHealth);

                // If the new health is different from the current health, apply the change
                if (newHealth != currentHealth)
                {
                    currentHealth = newHealth;
                    CurrentStatsChange(); // Notify stats change if needed
                }
            }

            // Check if adding defense would exceed the maximum
            if (currentDefense < maxDefense)
            {
                // Calculate the new defense after adding
                int newDefense = currentDefense + defenseToAdd;

                // Ensure the new defense doesn't exceed the maximum
                newDefense = Mathf.Clamp(newDefense, 0, maxDefense);

                // If the new defense is different from the current defense, apply the change
                if (newDefense != currentDefense)
                {
                    currentDefense = newDefense;
                    CurrentStatsChange(); // Notify stats change if needed
                }
            }

            // Check if adding mana would exceed the maximum
            if (currentMana < maxMana)
            {
                // Calculate the new mana after adding
                int newMana = currentMana + manaToAdd;  

                // Ensure the new mana doesn't exceed the maximum
                newMana = Mathf.Clamp(newMana, 0, maxMana);

                // If the new mana is different from the current mana, apply the change
                if (newMana != currentMana)
                {
                    currentMana = newMana;
                    CurrentStatsChange(); // Notify stats change if needed
                }
            }
        }

        // This allows the UsableItem to start coroutines on the player
            public new Coroutine StartCoroutine(IEnumerator routine)
            {
                return base.StartCoroutine(routine);
            }


        public void SavePlayerData()
        {
            // Create a PlayerData object and populate it with current player state
            PlayerData data = new PlayerData();
            data.playerName = PlayerName;
            data.playerLevel = PlayerLevel;
            data.currentEXP = CurrentEXP;
            data.expToLevelUp = ExpToLevelUp;
            data.currentHealth = currentHealth;
            data.maxHealth = maxHealth;
            data.currentMana = currentMana;
            data.maxMana = maxMana;
            data.currentDefense = currentDefense;
            data.maxDefense = maxDefense;
            data.currentAttack = currentAttack;
            data.maxAttack = maxAttack;
            data.currentAttackSpeed = currentAttackSpeed;
            data.maxAttackSpeed = maxAttackSpeed;
            data.currentCritical = currentCritical;
            data.maxCritical = maxCritical;
            data.currentLifeSteal = currentLifeSteal;
            data.maxLifeSteal = maxLifeSteal;
            data.currentRange = currentRange;
            data.maxRange = maxRange;
            data.currentElementalMastery = currentElementalMastery;
            data.maxElementalMastery = maxElementalMastery;
            data.currentSpeed = currentSpeed;
            data.maxSpeed = maxSpeed;
            data.currentCooldown = currentCooldown;
            data.maxCooldown = maxCooldown;
            data.currentKnockback = currentKnockback;
            data.maxKnockback = maxKnockback;
            data.currentRecovery = currentRecovery;
            data.maxRecovery = maxRecovery;
            data.currentEvade = currentEvade;
            data.maxEvade = maxEvade;
            data.currentFortune = currentFortune;
            data.maxFortune = maxFortune;

            data.playerPosX = transform.position.x;
            data.playerPosY = transform.position.y;
            data.playerPosZ = transform.position.z;

            // Adjusted file path
            string saveDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "World Of Normies", "SAVE DATA", PlayerName);
            string fileName = $"{PlayerName}_Data.sav"; // Adjusted file name here
            string savePath = Path.Combine(saveDirectory, fileName);

            try
            {
                // Create directory if it doesn't exist
                Directory.CreateDirectory(saveDirectory);

                using (FileStream fileStream = new FileStream(savePath, FileMode.Create))
                {
                    BinaryFormatter formatter = new BinaryFormatter();
                    formatter.Serialize(fileStream, data);
                }

                Debug.Log($"<color=#ADD8E6><b>Player data saved successfully</b></color> to: {savePath}");

            }
            catch (Exception e)
            {
                Debug.LogError($"<color=red><b>Failed to save player data: {e.Message}</b></color>");

            }
        }

   public void LoadPlayerData(string playerName)
    {
        // Construct the base directory path
        string baseDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "World Of Normies", "SAVE DATA");

        // Check if the base directory exists
        if (!Directory.Exists(baseDirectory))
        {
            Debug.LogWarning("<color=red><b>No saved player data found.</b></color>");
            return;
        }

        // Append the player's folder based on PlayerName
        string playerDirectory = Path.Combine(baseDirectory, PlayerName);

        // Ensure the player's directory exists
        if (!Directory.Exists(playerDirectory))
        {
            Debug.LogWarning($"<color=red><b>No saved data found for player: {PlayerName}</b></color>");

            return;
        }

        // Construct the full file path
        string filePath = Path.Combine(playerDirectory, $"{PlayerName}_Data.sav");

        // Check if the file exists
        if (File.Exists(filePath))
        {
            BinaryFormatter formatter = new BinaryFormatter();

            try
            {
                using (FileStream fileStream = new FileStream(filePath, FileMode.Open))
                {
                    PlayerData data = formatter.Deserialize(fileStream) as PlayerData;

                    // Assign loaded data back to the player (optional, depends on your game's logic)
                    PlayerName = data.playerName;
                    PlayerLevel = data.playerLevel;
                    CurrentEXP = data.currentEXP;
                    ExpToLevelUp = data.expToLevelUp;
                    currentHealth = data.currentHealth;
                    maxHealth = data.maxHealth;
                    currentMana = data.currentMana;
                    maxMana = data.maxMana;
                    currentDefense = data.currentDefense;
                    maxDefense = data.maxDefense;
                    currentAttack = data.currentAttack;
                    maxAttack = data.maxAttack;
                    currentAttackSpeed = data.currentAttackSpeed;
                    maxAttackSpeed = data.maxAttackSpeed;
                    currentCritical = data.currentCritical;
                    maxCritical = data.maxCritical;
                    currentLifeSteal = data.currentLifeSteal;
                    maxLifeSteal = data.maxLifeSteal;
                    currentRange = data.currentRange;
                    maxRange = data.maxRange;
                    currentElementalMastery = data.currentElementalMastery;
                    maxElementalMastery = data.maxElementalMastery;
                    currentSpeed = data.currentSpeed;
                    maxSpeed = data.maxSpeed;
                    currentCooldown = data.currentCooldown;
                    maxCooldown = data.maxCooldown;
                    currentKnockback = data.currentKnockback;
                    maxKnockback = data.maxKnockback;
                    currentRecovery = data.currentRecovery;
                    maxRecovery = data.maxRecovery;
                    currentEvade = data.currentEvade;
                    maxEvade = data.maxEvade;
                    currentFortune = data.currentFortune;
                    maxFortune = data.maxFortune;

                    // Assuming 'character' is an instance of the Character class
                    character.LoadStatsFromData(data);
                    playerSkill.LoadSkillData(PlayerName);

                    // Position (example)
                    Vector3 playerPosition = new Vector3(data.playerPosX, data.playerPosY, data.playerPosZ);
                    transform.position = playerPosition;

                    Debug.Log($"<color=#00FF00><b>Loaded PlayerData</b></color>");

                }
            }
            catch (Exception e)
            {
                Debug.LogError($"<color=red><b>Failed to load player data: {e.Message}</b></color>");

            }
        }
        else
        {
            Debug.LogWarning("<color=red><b>No saved player data found.</b></color>");
        }
    }

}

tell me everything this script has please and be clear for everythng in the script each method and logics