using UnityEngine;
using System.Collections.Generic;

namespace MaskShop
{
    /// <summary>
    /// Manages player progression, XP, and unlocks
    /// </summary>
    public class ProgressionSystem : MonoBehaviour
    {
        [Header("Level Settings")]
        [SerializeField] private int currentLevel = 1;
        [SerializeField] private int currentXP = 0;
        [SerializeField] private int baseXPRequired = 100;
        [SerializeField] private float xpScalingFactor = 1.5f;

        [Header("XP Rewards by Rank")]
        [SerializeField] private int rankSXP = 500;
        [SerializeField] private int rankAXP = 350;
        [SerializeField] private int rankBXP = 250;
        [SerializeField] private int rankCXP = 150;
        [SerializeField] private int rankDXP = 75;

        [Header("Unlockables")]
        [SerializeField] private List<MaskMold> allMolds = new List<MaskMold>();
        [SerializeField] private List<DecorationItem> allDecorations = new List<DecorationItem>();

        [Header("References")]
        [SerializeField] private MaskMoldSelector moldSelector;
        [SerializeField] private DecorationSelector decorationSelector;

        [Header("Debug")]
        [SerializeField] private bool showDebugInfo = true;

        // Events
        public static event System.Action<int> OnLevelUp;
        public static event System.Action<int, int> OnXPGained; // gained XP, total XP
        public static event System.Action<UnlockableItem> OnItemUnlocked;

        private void Start()
        {
            LoadProgression();
        }

        /// <summary>
        /// Awards XP based on mask evaluation
        /// </summary>
        public void AwardXP(MaskEvaluation evaluation)
        {
            int xpReward = GetXPForRank(evaluation.rank);

            // Bonus XP for perfect performance
            if (evaluation.earnedAllParametersBonus)
            {
                xpReward = Mathf.RoundToInt(xpReward * 1.2f);
            }

            if (evaluation.earnedAllPerfectBonus)
            {
                xpReward = Mathf.RoundToInt(xpReward * 1.15f);
            }

            AddXP(xpReward);

            if (showDebugInfo)
            {
                Debug.Log($"ProgressionSystem: Awarded {xpReward} XP for {evaluation.rank} rank mask");
            }
        }

        /// <summary>
        /// Gets XP reward for a specific rank
        /// </summary>
        private int GetXPForRank(MaskRank rank)
        {
            return rank switch
            {
                MaskRank.S => rankSXP,
                MaskRank.A => rankAXP,
                MaskRank.B => rankBXP,
                MaskRank.C => rankCXP,
                MaskRank.D => rankDXP,
                _ => 0
            };
        }

        /// <summary>
        /// Adds XP and checks for level up
        /// </summary>
        public void AddXP(int amount)
        {
            currentXP += amount;

            // Fire XP gained event
            OnXPGained?.Invoke(amount, currentXP);

            // Check for level up
            int xpRequired = GetXPRequiredForNextLevel();

            while (currentXP >= xpRequired)
            {
                LevelUp();
                currentXP -= xpRequired;
                xpRequired = GetXPRequiredForNextLevel();
            }

            SaveProgression();
        }

        /// <summary>
        /// Calculates XP required for next level
        /// </summary>
        public int GetXPRequiredForNextLevel()
        {
            return Mathf.RoundToInt(baseXPRequired * Mathf.Pow(xpScalingFactor, currentLevel - 1));
        }

        /// <summary>
        /// Levels up the player
        /// </summary>
        private void LevelUp()
        {
            currentLevel++;

            if (showDebugInfo)
            {
                Debug.Log($"ProgressionSystem: LEVEL UP! Now level {currentLevel}");
            }

            // Fire level up event
            OnLevelUp?.Invoke(currentLevel);

            // Check for unlocks
            CheckForUnlocks();
        }

        /// <summary>
        /// Checks and unlocks items based on level
        /// </summary>
        private void CheckForUnlocks()
        {
            bool needsRefresh = false;

            // Check molds
            foreach (MaskMold mold in allMolds)
            {
                if (!mold.IsUnlocked && mold.RequiredLevel <= currentLevel)
                {
                    mold.Unlock();
                    needsRefresh = true;

                    // Fire unlock event
                    OnItemUnlocked?.Invoke(new UnlockableItem
                    {
                        itemName = mold.MoldName,
                        itemType = UnlockableType.Mold
                    });

                    if (showDebugInfo)
                    {
                        Debug.Log($"ProgressionSystem: Unlocked mold '{mold.MoldName}'!");
                    }
                }
            }

            // Check decorations
            foreach (DecorationItem decoration in allDecorations)
            {
                if (!decoration.IsUnlocked && decoration.RequiredLevel <= currentLevel)
                {
                    decoration.Unlock();
                    needsRefresh = true;

                    // Fire unlock event
                    OnItemUnlocked?.Invoke(new UnlockableItem
                    {
                        itemName = decoration.DecorationName,
                        itemType = UnlockableType.Decoration
                    });

                    if (showDebugInfo)
                    {
                        Debug.Log($"ProgressionSystem: Unlocked decoration '{decoration.DecorationName}'!");
                    }
                }
            }

            // Refresh displays if needed
            if (needsRefresh)
            {
                RefreshDisplays();
            }
        }

        /// <summary>
        /// Refreshes all item displays
        /// </summary>
        private void RefreshDisplays()
        {
            if (moldSelector != null)
            {
                moldSelector.RefreshMoldDisplay();
            }

            if (decorationSelector != null)
            {
                decorationSelector.RefreshDecorationDisplay();
            }
        }

        /// <summary>
        /// Saves progression data
        /// </summary>
        private void SaveProgression()
        {
            PlayerPrefs.SetInt("CurrentLevel", currentLevel);
            PlayerPrefs.SetInt("CurrentXP", currentXP);
            PlayerPrefs.Save();
        }

        /// <summary>
        /// Loads progression data
        /// </summary>
        private void LoadProgression()
        {
            currentLevel = PlayerPrefs.GetInt("CurrentLevel", 1);
            currentXP = PlayerPrefs.GetInt("CurrentXP", 0);

            // Unlock items based on loaded level
            CheckForUnlocks();

            if (showDebugInfo)
            {
                Debug.Log($"ProgressionSystem: Loaded - Level {currentLevel}, XP {currentXP}");
            }
        }

        /// <summary>
        /// Resets progression (for testing)
        /// </summary>
        [ContextMenu("Reset Progression")]
        public void ResetProgression()
        {
            currentLevel = 1;
            currentXP = 0;

            // Lock all items
            foreach (MaskMold mold in allMolds)
            {
                // Reset unlock status via reflection or add a Lock() method
            }

            foreach (DecorationItem decoration in allDecorations)
            {
                // Reset unlock status
            }

            SaveProgression();
            RefreshDisplays();

            if (showDebugInfo)
            {
                Debug.Log("ProgressionSystem: Progression reset!");
            }
        }

        // Public getters
        public int GetCurrentLevel() => currentLevel;
        public int GetCurrentXP() => currentXP;
        public float GetLevelProgress()
        {
            int xpRequired = GetXPRequiredForNextLevel();
            return (float)currentXP / xpRequired;
        }
    }

    /// <summary>
    /// Types of unlockable items
    /// </summary>
    public enum UnlockableType
    {
        Mold,
        Decoration
    }

    /// <summary>
    /// Represents an unlocked item
    /// </summary>
    public struct UnlockableItem
    {
        public string itemName;
        public UnlockableType itemType;
    }
}