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

/// <summary>
/// Runtime instance of a quest that tracks progress and time
/// </summary>
[System.Serializable]
public class ActiveQuest
{
    [Header("Quest Reference")]
    public Quest questData;
    public string questId; // Unique identifier

    [Header("Progress Tracking")]
    public List<QuestGoal> activeGoals;
    public QuestStatus status = QuestStatus.Active;

    [Header("Time Tracking")]
    public float timeStarted; // Game time when quest was accepted
    public float timeRemaining; // Hours remaining

    [Header("Completion Data")]
    public float timeCompleted = -1f;
    public Vector2Int completionPosition;

    public ActiveQuest(Quest quest)
    {
        questData = quest;
        questId = System.Guid.NewGuid().ToString();

        // Copy goals from quest data
        activeGoals = new List<QuestGoal>();
        foreach (var goal in quest.goals)
        {
            activeGoals.Add(new QuestGoal
            {
                description = goal.description,
                goalType = goal.goalType,
                targetName = goal.targetName,
                targetCount = goal.targetCount,
                currentProgress = 0,
                isHidden = goal.isHidden,
                isOptional = goal.isOptional
            });
        }

        timeStarted = Time.time;
        timeRemaining = quest.GetTotalTimeLimitHours();
        status = QuestStatus.Active;
    }

    /// <summary>
    /// Update quest progress (called every frame or game tick)
    /// </summary>
    public void UpdateQuest(float deltaTimeHours)
    {
        if (status != QuestStatus.Active) return;

        timeRemaining -= deltaTimeHours;

        // Check if time has run out
        if (timeRemaining <= 0f && questData.canFail)
        {
            status = QuestStatus.Failed;
            OnQuestFailed();
            return;
        }

        // Check if all required goals are completed
        if (AreAllRequiredGoalsCompleted())
        {
            status = QuestStatus.Completed;
            timeCompleted = Time.time;
            OnQuestCompleted();
        }
    }

    /// <summary>
    /// Progress a specific goal
    /// </summary>
    public bool ProgressGoal(QuestGoalType goalType, string targetName = "", int amount = 1)
    {
        bool progressMade = false;

        foreach (var goal in activeGoals)
        {
            if (goal.goalType == goalType &&
                (string.IsNullOrEmpty(targetName) || goal.targetName.Equals(targetName, StringComparison.OrdinalIgnoreCase)))
            {
                int oldProgress = goal.currentProgress;
                goal.currentProgress = Mathf.Min(goal.currentProgress + amount, goal.targetCount);

                if (goal.currentProgress > oldProgress)
                {
                    progressMade = true;
                    Debug.Log($"🎯 Quest Progress: {goal.description} ({goal.currentProgress}/{goal.targetCount})");
                }
            }
        }

        return progressMade;
    }

    /// <summary>
    /// Check if quest can be completed at current position
    /// </summary>
    public bool CanCompleteAtPosition(Vector2Int position)
    {
        return questData.CanCompleteAtPosition(position) && AreAllRequiredGoalsCompleted();
    }

    /// <summary>
    /// Attempt to complete the quest at given position
    /// </summary>
    public bool TryCompleteQuest(Vector2Int position)
    {
        if (!CanCompleteAtPosition(position)) return false;

        status = QuestStatus.Completed;
        timeCompleted = Time.time;
        completionPosition = position;
        OnQuestCompleted();
        return true;
    }

    private bool AreAllRequiredGoalsCompleted()
    {
        foreach (var goal in activeGoals)
        {
            if (!goal.isOptional && !goal.IsCompleted)
                return false;
        }
        return true;
    }

    private void OnQuestCompleted()
    {
        Debug.Log($"✅ Quest Completed: {questData.questTitle}");
        QuestManager.Instance?.CompleteQuest(this);
    }

    private void OnQuestFailed()
    {
        Debug.Log($"❌ Quest Failed: {questData.questTitle} (Time's up!)");
        QuestManager.Instance?.FailQuest(this);
    }

    /// <summary>
    /// Get time remaining as formatted string
    /// </summary>
    public string GetTimeRemainingString()
    {
        if (timeRemaining <= 0) return "EXPIRED";

        int days = Mathf.FloorToInt(timeRemaining / 24f);
        int hours = Mathf.FloorToInt(timeRemaining % 24f);
        int minutes = Mathf.FloorToInt((timeRemaining % 1f) * 60f);

        if (days > 0)
            return $"{days}d {hours}h {minutes}m";
        else if (hours > 0)
            return $"{hours}h {minutes}m";
        else
            return $"{minutes}m";
    }

    /// <summary>
    /// Get progress percentage (0-1)
    /// </summary>
    public float GetOverallProgress()
    {
        if (activeGoals.Count == 0) return 1f;

        float totalProgress = 0f;
        int requiredGoals = 0;

        foreach (var goal in activeGoals)
        {
            if (!goal.isOptional)
            {
                totalProgress += goal.ProgressPercent;
                requiredGoals++;
            }
        }

        return requiredGoals > 0 ? totalProgress / requiredGoals : 1f;
    }

    /// <summary>
    /// Get urgency level based on time remaining
    /// </summary>
    public QuestUrgency GetUrgency()
    {
        float totalTime = questData.GetTotalTimeLimitHours();
        float timePercent = timeRemaining / totalTime;

        if (timePercent > 0.75f) return QuestUrgency.Low;
        if (timePercent > 0.5f) return QuestUrgency.Medium;
        if (timePercent > 0.25f) return QuestUrgency.High;
        return QuestUrgency.Critical;
    }

    /// <summary>
    /// Get time remaining in hours (used by UI)
    /// </summary>
    public float GetTimeRemaining()
    {
        return timeRemaining;
    }

    /// <summary>
    /// Get urgency level (compatibility method)
    /// </summary>
    public QuestUrgency GetUrgencyLevel()
    {
        return GetUrgency();
    }

    /// <summary>
    /// Get number of completed objectives
    /// </summary>
    public int GetCompletedObjectivesCount()
    {
        int completed = 0;
        foreach (var goal in activeGoals)
        {
            if (goal.currentProgress >= goal.targetCount)
                completed++;
        }
        return completed;
    }

    /// <summary>
    /// Get progress of a specific objective
    /// </summary>
    public int GetObjectiveProgress(int objectiveIndex)
    {
        if (objectiveIndex >= 0 && objectiveIndex < activeGoals.Count)
            return activeGoals[objectiveIndex].currentProgress;
        return 0;
    }

    /// <summary>
    /// Convert this active quest to save data
    /// </summary>
    public ActiveQuestSaveData ToSaveData()
    {
        var saveData = new ActiveQuestSaveData
        {
            questId = this.questId,
            questAssetName = questData?.name ?? "",
            questTitle = questData?.questTitle ?? "Unknown Quest",
            status = this.status,
            elapsedTimeHours = (questData?.GetTotalTimeLimitHours() ?? 0) - timeRemaining
        };

        // Save goal progress
        foreach (var goal in activeGoals)
        {
            saveData.goals.Add(new QuestGoalSaveData
            {
                description = goal.description,
                goalType = goal.goalType,
                targetName = goal.targetName,
                targetCount = goal.targetCount,
                currentProgress = goal.currentProgress,
                isHidden = goal.isHidden,
                isOptional = goal.isOptional
            });
        }

        return saveData;
    }

    /// <summary>
    /// Create an ActiveQuest from save data
    /// </summary>
    public static ActiveQuest FromSaveData(ActiveQuestSaveData saveData)
    {
        // Try to find the original quest asset
        Quest questAsset = null;

        if (!string.IsNullOrEmpty(saveData.questAssetName))
        {
            questAsset = Resources.Load<Quest>($"Quests/{saveData.questAssetName}");
            if (questAsset == null)
            {
                questAsset = Resources.Load<Quest>(saveData.questAssetName);
            }
        }

        // If we can't find the asset, create a minimal one
        if (questAsset == null)
        {
            Debug.LogWarning($"Could not find quest asset '{saveData.questAssetName}' for saved quest '{saveData.questTitle}'. Creating placeholder.");
            questAsset = ScriptableObject.CreateInstance<Quest>();
            questAsset.questTitle = saveData.questTitle;
            questAsset.questDescription = "This quest was loaded from save data but the original asset is missing.";
            questAsset.timeLimitDays = 7; // Default
        }

        // Create the active quest
        var activeQuest = new ActiveQuest(questAsset);
        activeQuest.questId = saveData.questId;
        activeQuest.status = saveData.status;

        // Calculate time remaining from elapsed time
        float totalTime = questAsset.GetTotalTimeLimitHours();
        activeQuest.timeRemaining = Mathf.Max(0, totalTime - saveData.elapsedTimeHours);

        // Restore goal progress
        for (int i = 0; i < activeQuest.activeGoals.Count && i < saveData.goals.Count; i++)
        {
            var goal = activeQuest.activeGoals[i];
            var savedGoal = saveData.goals[i];

            goal.currentProgress = savedGoal.currentProgress;
        }

        return activeQuest;
    }
}

public enum QuestStatus
{
    Active,
    Completed,
    Failed,
    Abandoned
}

public enum QuestUrgency
{
    Low,
    Medium,
    High,
    Critical
}
