// ==============================================
// AchievementManager.cs - Achievement System
// ==============================================
// Handles achievement display and notifications.

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

namespace BreakpilotDrive
{
    [Serializable]
    public class Achievement
    {
        public string id;
        public string name;
        public string description;
        public string icon;
        public string category;
        public int threshold;
        public int progress;
        public bool unlocked;
    }

    [Serializable]
    public class AchievementResponse
    {
        public string user_id;
        public int total;
        public int unlocked_count;
        public Achievement[] achievements;
    }

    [Serializable]
    private class AchievementArrayWrapper
    {
        public Achievement[] achievements;
    }

    public class AchievementManager : MonoBehaviour
    {
        public static AchievementManager Instance { get; private set; }

        [Header("UI References")]
        [SerializeField] private GameObject achievementPopupPrefab;
        [SerializeField] private Transform popupContainer;
        [SerializeField] private float popupDuration = 3f;

        [Header("Audio")]
        [SerializeField] private AudioClip unlockSound;

        // Events
        public UnityEvent<Achievement> OnAchievementUnlocked;

        // Cached data
        private List<Achievement> achievements = new List<Achievement>();
        private HashSet<string> previouslyUnlocked = new HashSet<string>();
        private Queue<Achievement> popupQueue = new Queue<Achievement>();
        private bool isShowingPopup = false;

        void Awake()
        {
            if (Instance == null)
            {
                Instance = this;
                DontDestroyOnLoad(gameObject);
            }
            else
            {
                Destroy(gameObject);
            }
        }

        // ==============================================
        // Load Achievements from API
        // ==============================================

        public IEnumerator LoadAchievements(string userId, Action<AchievementResponse> onComplete = null)
        {
            string url = $"{GetBaseUrl()}/achievements/{userId}";

            using (var request = UnityEngine.Networking.UnityWebRequest.Get(url))
            {
                // Add auth header if available
                string authHeader = AuthManager.Instance?.GetAuthHeader();
                if (!string.IsNullOrEmpty(authHeader))
                {
                    request.SetRequestHeader("Authorization", authHeader);
                }

                yield return request.SendWebRequest();

                if (request.result == UnityEngine.Networking.UnityWebRequest.Result.Success)
                {
                    var response = JsonUtility.FromJson<AchievementResponse>(request.downloadHandler.text);

                    // Store previously unlocked for comparison
                    previouslyUnlocked.Clear();
                    foreach (var a in achievements)
                    {
                        if (a.unlocked)
                            previouslyUnlocked.Add(a.id);
                    }

                    // Update achievements
                    achievements.Clear();
                    if (response.achievements != null)
                    {
                        achievements.AddRange(response.achievements);
                    }

                    onComplete?.Invoke(response);
                }
                else
                {
                    Debug.LogWarning($"Failed to load achievements: {request.error}");
                    onComplete?.Invoke(null);
                }
            }
        }

        // ==============================================
        // Check for New Achievements
        // ==============================================

        public void CheckForNewUnlocks()
        {
            foreach (var achievement in achievements)
            {
                if (achievement.unlocked && !previouslyUnlocked.Contains(achievement.id))
                {
                    // New unlock!
                    ShowAchievementPopup(achievement);
                    OnAchievementUnlocked?.Invoke(achievement);
                }
            }
        }

        // Call after each game session to check for new achievements
        public IEnumerator RefreshAndCheckAchievements(string userId)
        {
            yield return LoadAchievements(userId, (response) =>
            {
                if (response != null)
                {
                    CheckForNewUnlocks();
                }
            });
        }

        // ==============================================
        // Achievement Popup
        // ==============================================

        public void ShowAchievementPopup(Achievement achievement)
        {
            popupQueue.Enqueue(achievement);

            if (!isShowingPopup)
            {
                StartCoroutine(ProcessPopupQueue());
            }
        }

        private IEnumerator ProcessPopupQueue()
        {
            isShowingPopup = true;

            while (popupQueue.Count > 0)
            {
                var achievement = popupQueue.Dequeue();
                yield return ShowSinglePopup(achievement);
                yield return new WaitForSeconds(0.3f); // Gap between popups
            }

            isShowingPopup = false;
        }

        private IEnumerator ShowSinglePopup(Achievement achievement)
        {
            Debug.Log($"[Achievement] Unlocked: {achievement.name}");

            // Play sound
            if (unlockSound != null && AudioManager.Instance != null)
            {
                AudioManager.Instance.PlaySFX(unlockSound);
            }

            // Create popup UI
            if (achievementPopupPrefab != null && popupContainer != null)
            {
                var popup = Instantiate(achievementPopupPrefab, popupContainer);
                var popupScript = popup.GetComponent<AchievementPopup>();

                if (popupScript != null)
                {
                    popupScript.Setup(achievement);
                }

                yield return new WaitForSeconds(popupDuration);

                if (popup != null)
                {
                    Destroy(popup);
                }
            }
            else
            {
                // Fallback: just wait
                yield return new WaitForSeconds(popupDuration);
            }
        }

        // ==============================================
        // Public API
        // ==============================================

        public List<Achievement> GetAllAchievements()
        {
            return new List<Achievement>(achievements);
        }

        public List<Achievement> GetUnlockedAchievements()
        {
            return achievements.FindAll(a => a.unlocked);
        }

        public List<Achievement> GetLockedAchievements()
        {
            return achievements.FindAll(a => !a.unlocked);
        }

        public List<Achievement> GetAchievementsByCategory(string category)
        {
            return achievements.FindAll(a => a.category == category);
        }

        public int GetUnlockedCount()
        {
            int count = 0;
            foreach (var a in achievements)
            {
                if (a.unlocked) count++;
            }
            return count;
        }

        public int GetTotalCount()
        {
            return achievements.Count;
        }

        public float GetCompletionPercentage()
        {
            if (achievements.Count == 0) return 0f;
            return (float)GetUnlockedCount() / achievements.Count * 100f;
        }

        public Achievement GetAchievement(string id)
        {
            return achievements.Find(a => a.id == id);
        }

        // ==============================================
        // Icon Mapping
        // ==============================================

        public Sprite GetIconSprite(string iconName)
        {
            // Load from Resources/Icons/Achievements/
            string path = $"Icons/Achievements/{iconName}";
            var sprite = Resources.Load<Sprite>(path);

            if (sprite == null)
            {
                // Fallback icon
                sprite = Resources.Load<Sprite>("Icons/Achievements/default");
            }

            return sprite;
        }

        // ==============================================
        // Helpers
        // ==============================================

        private string GetBaseUrl()
        {
            if (BreakpilotAPI.Instance != null)
            {
                return "http://localhost:8000/api/game"; // TODO: Get from BreakpilotAPI
            }
            return "http://localhost:8000/api/game";
        }
    }

    // ==============================================
    // Achievement Popup Component
    // ==============================================

    public class AchievementPopup : MonoBehaviour
    {
        [SerializeField] private UnityEngine.UI.Text titleText;
        [SerializeField] private UnityEngine.UI.Text descriptionText;
        [SerializeField] private UnityEngine.UI.Image iconImage;

        public void Setup(Achievement achievement)
        {
            if (titleText != null)
                titleText.text = achievement.name;

            if (descriptionText != null)
                descriptionText.text = achievement.description;

            if (iconImage != null)
            {
                var sprite = AchievementManager.Instance?.GetIconSprite(achievement.icon);
                if (sprite != null)
                    iconImage.sprite = sprite;
            }

            // Animate in
            StartCoroutine(AnimateIn());
        }

        private IEnumerator AnimateIn()
        {
            var canvasGroup = GetComponent<CanvasGroup>();
            if (canvasGroup != null)
            {
                canvasGroup.alpha = 0f;
                float duration = 0.3f;
                float elapsed = 0f;

                while (elapsed < duration)
                {
                    elapsed += Time.deltaTime;
                    canvasGroup.alpha = Mathf.Lerp(0f, 1f, elapsed / duration);
                    yield return null;
                }

                canvasGroup.alpha = 1f;
            }
        }
    }
}
