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

/// <summary>
/// Central manager for quest system - handles active quests, progress tracking, and rewards
/// </summary>
public class QuestManager : MonoBehaviour
{
    public static QuestManager Instance { get; private set; }

    [Header("Quest Configuration")]
    [Tooltip("Maximum number of active quests")]
    public int maxActiveQuests = 5;

    [Tooltip("Game time speed multiplier (how fast time passes)")]
    public float gameTimeSpeed = 1f;

    [Header("Active Quests")]
    [SerializeField] private List<ActiveQuest> activeQuests = new List<ActiveQuest>();
    [SerializeField] private List<ActiveQuest> completedQuests = new List<ActiveQuest>();
    [SerializeField] private List<ActiveQuest> failedQuests = new List<ActiveQuest>();

    [Header("Renown System")]
    [SerializeField] private int currentRenown = 0;

    [Header("Debug")]
    public bool enableDebugLogs = true;

    // Events
    public event Action<ActiveQuest> OnQuestAccepted;
    public event Action<ActiveQuest, List<QuestReward>> OnQuestCompleted;
    public event Action<ActiveQuest> OnQuestFailed;
    public event Action<ActiveQuest> OnQuestAbandoned;
    public event Action<ActiveQuest, QuestGoal> OnQuestGoalCompleted;
    public event Action<int> OnRenownChanged;

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

    private void Update()
    {
        UpdateActiveQuests();
    }

    private void UpdateActiveQuests()
    {
        if (activeQuests.Count == 0) return;

        float deltaTimeHours = Time.deltaTime * gameTimeSpeed;

        // Update each active quest
        for (int i = activeQuests.Count - 1; i >= 0; i--)
        {
            var quest = activeQuests[i];
            quest.UpdateQuest(deltaTimeHours);

            // Remove completed or failed quests from active list
            if (quest.status != QuestStatus.Active)
            {
                activeQuests.RemoveAt(i);
            }
        }
    }

    /// <summary>
    /// Accept a new quest
    /// </summary>
    public bool AcceptQuest(Quest questData)
    {
        if (questData == null)
        {
            LogDebug("Cannot accept null quest");
            return false;
        }

        if (activeQuests.Count >= maxActiveQuests)
        {
            LogDebug($"Cannot accept quest: Maximum active quests reached ({maxActiveQuests})");
            return false;
        }

        // Check if already have this quest active
        if (activeQuests.Any(q => q.questData == questData))
        {
            LogDebug($"Quest '{questData.questTitle}' is already active");
            return false;
        }

        // Check requirements
        if (!MeetsRequirements(questData))
        {
            LogDebug($"Does not meet requirements for quest '{questData.questTitle}'");
            return false;
        }

        var activeQuest = questData.CreateActiveQuest();
        activeQuests.Add(activeQuest);

        LogDebug($"✅ Accepted quest: {questData.questTitle}");
        OnQuestAccepted?.Invoke(activeQuest);
        SaveQuestData();

        return true;
    }

    /// <summary>
    /// Abandon an active quest
    /// </summary>
    public bool AbandonQuest(string questId)
    {
        var quest = activeQuests.FirstOrDefault(q => q.questId == questId);
        if (quest == null) return false;

        quest.status = QuestStatus.Abandoned;
        activeQuests.Remove(quest);

        LogDebug($"🚫 Abandoned quest: {quest.questData.questTitle}");
        OnQuestAbandoned?.Invoke(quest);
        SaveQuestData();

        return true;
    }

    /// <summary>
    /// Progress quest goals - called by game events
    /// </summary>
    public void ProgressQuest(QuestGoalType goalType, string targetName = "", int amount = 1)
    {
        foreach (var quest in activeQuests)
        {
            if (quest.ProgressGoal(goalType, targetName, amount))
            {
                // Check if any goals were just completed
                foreach (var goal in quest.activeGoals)
                {
                    if (goal.IsCompleted && goal.currentProgress == goal.targetCount)
                    {
                        OnQuestGoalCompleted?.Invoke(quest, goal);
                    }
                }
            }
        }
        SaveQuestData();
    }

    /// <summary>
    /// Try to complete quests at current position
    /// </summary>
    public List<ActiveQuest> TryCompleteQuestsAtPosition(Vector2Int position)
    {
        var completedQuests = new List<ActiveQuest>();

        foreach (var quest in activeQuests.ToList())
        {
            if (quest.TryCompleteQuest(position))
            {
                completedQuests.Add(quest);
            }
        }

        return completedQuests;
    }

    /// <summary>
    /// Called when a quest is completed
    /// </summary>
    public void CompleteQuest(ActiveQuest quest)
    {
        if (quest == null) return;

        // Move to completed list
        completedQuests.Add(quest);

        // Generate rewards list
        var rewards = GenerateQuestRewards(quest);

        // Award rewards
        AwardQuestRewards(quest);

        // Trigger event with rewards
        OnQuestCompleted?.Invoke(quest, rewards);
        SaveQuestData();
    }

    /// <summary>
    /// Called when a quest fails
    /// </summary>
    public void FailQuest(ActiveQuest quest)
    {
        if (quest == null) return;

        // Move to failed list
        failedQuests.Add(quest);

        // Apply penalties
        ApplyQuestPenalties(quest);

        // Trigger event
        OnQuestFailed?.Invoke(quest);
        SaveQuestData();
    }

    private List<QuestReward> GenerateQuestRewards(ActiveQuest quest)
    {
        var rewards = new List<QuestReward>();
        var questData = quest.questData;

        // Add gold reward
        if (questData.goldReward > 0)
        {
            rewards.Add(new QuestReward
            {
                type = QuestRewardType.Gold,
                amount = questData.goldReward
            });
        }

        // Add silver reward
        if (questData.silverReward > 0)
        {
            rewards.Add(new QuestReward
            {
                type = QuestRewardType.Silver,
                amount = questData.silverReward
            });
        }

        // Add copper reward
        if (questData.copperReward > 0)
        {
            rewards.Add(new QuestReward
            {
                type = QuestRewardType.Copper,
                amount = questData.copperReward
            });
        }

        // Add renown reward
        if (questData.renownReward > 0)
        {
            rewards.Add(new QuestReward
            {
                type = QuestRewardType.Renown,
                amount = questData.renownReward
            });
        }

        // Add item rewards
        foreach (var itemName in questData.itemRewards)
        {
            if (!string.IsNullOrEmpty(itemName))
            {
                rewards.Add(new QuestReward
                {
                    type = QuestRewardType.Item,
                    amount = 1,
                    itemName = itemName
                });
            }
        }

        return rewards;
    }

    private void AwardQuestRewards(ActiveQuest quest)
    {
        var questData = quest.questData;

        // Award money to team
        var gameStateManager = GameStateManager.Instance;
        if (gameStateManager?.savedTeam != null)
        {
            foreach (var character in gameStateManager.savedTeam)
            {
                if (character != null)
                {
                    character.gold += questData.goldReward;
                    character.silver += questData.silverReward;
                    character.copper += questData.copperReward;
                }
            }
        }

        // Award renown
        ChangeRenown(questData.renownReward);

        // Award items (TODO: implement item reward system)
        foreach (var itemName in questData.itemRewards)
        {
            LogDebug($"🎁 Reward item: {itemName} (TODO: implement item awards)");
        }

        LogDebug($"💰 Quest rewards: {questData.goldReward}g, {questData.silverReward}s, {questData.copperReward}c, {questData.renownReward} renown");
    }

    private void ApplyQuestPenalties(ActiveQuest quest)
    {
        var questData = quest.questData;

        // Apply renown penalty
        ChangeRenown(-questData.renownPenalty);

        LogDebug($"💔 Quest penalties: -{questData.renownPenalty} renown");
    }

    private void ChangeRenown(int amount)
    {
        currentRenown = Mathf.Max(0, currentRenown + amount);
        OnRenownChanged?.Invoke(currentRenown);

        // Save to GameStateManager
        if (GameStateManager.Instance != null)
        {
            // TODO: Add renown field to GameStateManager
        }
    }

    private bool MeetsRequirements(Quest questData)
    {
        // Check renown requirement
        if (currentRenown < questData.minimumRenown)
            return false;

        // Check prerequisite quests
        foreach (var prereq in questData.prerequisiteQuests)
        {
            if (!completedQuests.Any(q => q.questData.questTitle == prereq))
                return false;
        }

        return true;
    }

    /// <summary>
    /// Get all active quests
    /// </summary>
    public List<ActiveQuest> GetActiveQuests() => new List<ActiveQuest>(activeQuests);

    /// <summary>
    /// Get quest by ID
    /// </summary>
    public ActiveQuest GetQuestById(string questId) => activeQuests.FirstOrDefault(q => q.questId == questId);

    /// <summary>
    /// Get current renown level
    /// </summary>
    public int GetRenown() => currentRenown;

    /// <summary>
    /// Check if can accept more quests
    /// </summary>
    public bool CanAcceptMoreQuests() => activeQuests.Count < maxActiveQuests;

    private void SaveQuestData()
    {
        try
        {
            var saveData = new QuestSaveData
            {
                currentRenown = this.currentRenown,
                activeQuests = this.activeQuests.Select(q => q.ToSaveData()).ToList(),
                completedQuests = this.completedQuests.Select(q => q.ToSaveData()).ToList(),
                failedQuests = this.failedQuests.Select(q => q.ToSaveData()).ToList()
            };

            string json = JsonUtility.ToJson(saveData, true);
            PlayerPrefs.SetString("QuestManager_SaveData", json);
            PlayerPrefs.Save();

            LogDebug("Quest data saved successfully");
        }
        catch (System.Exception ex)
        {
            Debug.LogError($"Failed to save quest data: {ex.Message}");
        }
    }

    public void LoadQuestData()
    {
        try
        {
            string json = PlayerPrefs.GetString("QuestManager_SaveData", "");
            if (string.IsNullOrEmpty(json))
            {
                LogDebug("No quest save data found, starting fresh");
                currentRenown = 0;
                return;
            }

            var saveData = JsonUtility.FromJson<QuestSaveData>(json);
            if (saveData != null)
            {
                currentRenown = saveData.currentRenown;

                // Load active quests
                activeQuests.Clear();
                foreach (var questSave in saveData.activeQuests)
                {
                    var activeQuest = ActiveQuest.FromSaveData(questSave);
                    if (activeQuest != null)
                    {
                        activeQuests.Add(activeQuest);
                    }
                }

                // Load completed quests
                completedQuests.Clear();
                foreach (var questSave in saveData.completedQuests)
                {
                    var activeQuest = ActiveQuest.FromSaveData(questSave);
                    if (activeQuest != null)
                    {
                        completedQuests.Add(activeQuest);
                    }
                }

                // Load failed quests
                failedQuests.Clear();
                foreach (var questSave in saveData.failedQuests)
                {
                    var activeQuest = ActiveQuest.FromSaveData(questSave);
                    if (activeQuest != null)
                    {
                        failedQuests.Add(activeQuest);
                    }
                }

                LogDebug($"Loaded quest data: {activeQuests.Count} active, {completedQuests.Count} completed, {failedQuests.Count} failed, {currentRenown} renown");

                // Trigger renown update event
                OnRenownChanged?.Invoke(currentRenown);

                // Refresh quest markers on map
                StartCoroutine(RefreshMarkersAfterLoad());
            }
        }
        catch (System.Exception ex)
        {
            Debug.LogError($"Failed to load quest data: {ex.Message}");
            currentRenown = 0;
        }
    }

    private System.Collections.IEnumerator RefreshMarkersAfterLoad()
    {
        // Wait a frame to ensure all systems are initialized
        yield return null;

        var markerManager = FindFirstObjectByType<QuestMapMarkerManager>();
        if (markerManager != null)
        {
            markerManager.RefreshAllMarkers();
        }
    }

    private void LogDebug(string message)
    {
        if (enableDebugLogs)
        {
            Debug.Log($"[QuestManager] {message}");
        }
    }

    #region Context Menu Debug Methods
    [ContextMenu("Add Test Combat Quest")]
    private void AddTestCombatQuest()
    {
        var testQuest = CreateTestCombatQuest();
        AcceptQuest(testQuest);
    }

    [ContextMenu("Progress Test Quest")]
    private void ProgressTestQuest()
    {
        ProgressQuest(QuestGoalType.KillEnemies, "Bandit", 1);
    }

    [ContextMenu("Complete Quest at (50,50)")]
    private void CompleteQuestAtTestPosition()
    {
        TryCompleteQuestsAtPosition(new Vector2Int(50, 50));
    }

    private Quest CreateTestCombatQuest()
    {
        var quest = ScriptableObject.CreateInstance<Quest>();
        quest.questTitle = "Clear the Bandit Camp";
        quest.questDescription = "Bandits have been attacking merchants on the road. Clear out their camp and make the roads safe again.";
        quest.questType = QuestType.Combat;
        quest.difficulty = QuestDifficulty.Normal;
        quest.timeLimitDays = 3;
        quest.targetAreaName = "Bandit Camp";
        quest.targetMapPosition = new Vector2Int(50, 50);
        quest.goldReward = 100;
        quest.renownReward = 15;
        quest.renownPenalty = 10;

        quest.goals.Add(new QuestGoal
        {
            description = "Defeat 5 Bandits",
            goalType = QuestGoalType.KillEnemies,
            targetName = "Bandit",
            targetCount = 5
        });

        return quest;
    }
    #endregion
}

/// <summary>
/// Save data structure for quest system
/// </summary>
[System.Serializable]
public class QuestSaveData
{
    public int currentRenown;
    public List<ActiveQuestSaveData> activeQuests = new List<ActiveQuestSaveData>();
    public List<ActiveQuestSaveData> completedQuests = new List<ActiveQuestSaveData>();
    public List<ActiveQuestSaveData> failedQuests = new List<ActiveQuestSaveData>();
}

/// <summary>
/// Save data structure for individual active quests
/// </summary>
[System.Serializable]
public class ActiveQuestSaveData
{
    public string questId;
    public string questAssetName; // To find the original Quest asset
    public string questTitle; // Fallback identification
    public QuestStatus status;
    public float elapsedTimeHours;
    public List<QuestGoalSaveData> goals = new List<QuestGoalSaveData>();
}

/// <summary>
/// Save data structure for quest goals
/// </summary>
[System.Serializable]
public class QuestGoalSaveData
{
    public string description;
    public QuestGoalType goalType;
    public string targetName;
    public int targetCount;
    public int currentProgress;
    public bool isHidden;
    public bool isOptional;
}
