using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Decal.Adapter;
using Decal.Adapter.Wrappers;

namespace MosswartMassacre
{
    /// <summary>
    /// Quest tracking and management system
    /// Ported from UBS Lua quest system
    /// </summary>
    public class QuestManager : IDisposable
    {
        #region Quest Data Structures
        public class Quest
        {
            public string Id { get; set; }
            public int Solves { get; set; }
            public int Timestamp { get; set; }
            public string Description { get; set; }
            public int MaxSolves { get; set; }
            public int Delta { get; set; }
            public int ExpireTime { get; set; }
        }
        #endregion

        #region Properties
        public List<Quest> QuestList { get; private set; }
        public Dictionary<string, Quest> QuestDictionary { get; private set; }
        #endregion

        #region Events and State
        private bool isRefreshing = false;
        private DateTime lastRefreshTime = DateTime.MinValue;
        #endregion

        public QuestManager()
        {
            QuestList = new List<Quest>();
            QuestDictionary = new Dictionary<string, Quest>();
            
            // Hook into chat events for quest parsing
            InitializeChatHooks();
        }

        #region Initialization
        private void InitializeChatHooks()
        {
            try
            {
                if (CoreManager.Current != null)
                {
                    CoreManager.Current.ChatBoxMessage += OnChatBoxMessage;
                }
            }
            catch (Exception ex)
            {
                PluginCore.WriteToChat($"Error initializing quest chat hooks: {ex.Message}");
            }
        }
        #endregion

        #region Quest Name Mapping
        public string GetFriendlyQuestName(string questStamp)
        {
            return QuestNames.GetFriendlyName(questStamp);
        }
        
        public string GetQuestDisplayName(string questStamp)
        {
            return QuestNames.GetDisplayName(questStamp);
        }
        
        public int GetQuestNameMappingsCount()
        {
            return QuestNames.QuestStampToName.Count;
        }
        #endregion

        #region Quest Parsing
        private void OnChatBoxMessage(object sender, ChatTextInterceptEventArgs e)
        {
            try
            {
                if (!isRefreshing || string.IsNullOrEmpty(e.Text))
                    return;

                // Parse quest information from /myquests output
                ParseQuestLine(e.Text);
            }
            catch (Exception ex)
            {
                PluginCore.WriteToChat($"Error parsing quest line: {ex.Message}");
            }
        }

        private void ParseQuestLine(string text)
        {
            try
            {
                // Quest line format: TaskName - Solves solves (Timestamp)"Description" MaxSolves Delta
                // Example: "SomeQuest - 5 solves (1640995200)"Quest description here" 10 3600
                var pattern = @"([^\-]+) - (\d+) solves \((\d+)\)""([^""]+)"" (-?\d+) (\d+)";
                var match = Regex.Match(text, pattern);

                if (match.Success)
                {
                    var quest = new Quest
                    {
                        Id = match.Groups[1].Value.Trim(),
                        Solves = int.Parse(match.Groups[2].Value),
                        Timestamp = int.Parse(match.Groups[3].Value),
                        Description = match.Groups[4].Value,
                        MaxSolves = int.Parse(match.Groups[5].Value),
                        Delta = int.Parse(match.Groups[6].Value)
                    };
                    
                    quest.ExpireTime = quest.Timestamp + quest.Delta;

                    // Add to collections
                    QuestList.Add(quest);
                    QuestDictionary[quest.Id] = quest;
                }
            }
            catch (Exception ex)
            {
                PluginCore.WriteToChat($"Error parsing quest line '{text}': {ex.Message}");
            }
        }
        #endregion

        #region Quest Management
        public void RefreshQuests()
        {
            try
            {
                if (isRefreshing)
                    return;

                ClearQuests();
                isRefreshing = true;
                
                // Issue /myquests command to refresh quest data
                CoreManager.Current.Actions.InvokeChatParser("/myquests");
                
                // Stop listening after a delay
                System.Threading.Timer stopTimer = null;
                stopTimer = new System.Threading.Timer(_ =>
                {
                    isRefreshing = false;
                    stopTimer?.Dispose();
                    lastRefreshTime = DateTime.Now;
                }, null, 3000, System.Threading.Timeout.Infinite);
            }
            catch (Exception ex)
            {
                isRefreshing = false;
                PluginCore.WriteToChat($"Error refreshing quests: {ex.Message}");
            }
        }

        public void ClearQuests()
        {
            QuestList.Clear();
            QuestDictionary.Clear();
        }

        public bool IsQuestAvailable(string questStamp)
        {
            if (!QuestDictionary.TryGetValue(questStamp, out Quest quest))
                return true; // If quest not found, assume available
                
            var currentTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
            return quest.ExpireTime < currentTime;
        }

        public bool IsQuestMaxSolved(string questStamp)
        {
            if (!QuestDictionary.TryGetValue(questStamp, out Quest quest))
                return false;
                
            return quest.Solves >= quest.MaxSolves;
        }

        public bool HasQuestFlag(string questStamp)
        {
            return QuestDictionary.ContainsKey(questStamp);
        }

        public string GetTimeUntilExpire(Quest quest)
        {
            if (quest == null)
                return "Unknown";
                
            var currentTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
            var timeLeft = quest.ExpireTime - currentTime;
            
            if (timeLeft <= 0)
                return "Ready";
                
            return FormatSeconds((int)timeLeft);
        }

        public string FormatTimeStamp(int timestamp)
        {
            try
            {
                var dateTime = DateTimeOffset.FromUnixTimeSeconds(timestamp).DateTime;
                return dateTime.ToString("MM/dd/yyyy HH:mm:ss");
            }
            catch
            {
                return "Invalid";
            }
        }

        public string FormatSeconds(int seconds)
        {
            if (seconds <= 0)
                return "0s";
                
            var days = seconds / 86400;
            seconds %= 86400;
            var hours = seconds / 3600;
            seconds %= 3600;
            var minutes = seconds / 60;
            seconds %= 60;
            
            var result = "";
            if (days > 0) result += $"{days}d ";
            if (hours > 0) result += $"{hours}h ";
            if (minutes > 0) result += $"{minutes}m ";
            if (seconds > 0 || string.IsNullOrEmpty(result)) result += $"{seconds}s";
            
            return result.Trim();
        }

        public object GetFieldByID(Quest quest, int id)
        {
            if (quest == null)
                return null;
                
            switch (id)
            {
                case 1: return quest.Id;
                case 2: return quest.Solves;
                case 3: return quest.Timestamp;
                case 4: return quest.MaxSolves;
                case 5: return quest.Delta;
                case 6: return quest.ExpireTime;
                default: return quest.Id;
            }
        }
        #endregion

        #region Society Quest Helpers
        public string GetSocietyName(int factionBits)
        {
            switch (factionBits)
            {
                case 1: return "Celestial Hand";
                case 2: return "Eldrytch Web";
                case 4: return "Radiant Blood";
                default: return "Unknown";
            }
        }

        public string GetSocietyRank(int ribbons)
        {
            if (ribbons >= 1001) return "Master";
            if (ribbons >= 601) return "Lord";
            if (ribbons >= 301) return "Knight";
            if (ribbons >= 101) return "Adept";
            if (ribbons >= 1) return "Initiate";
            return "None";
        }

        public int GetMaxRibbonsPerDay(string rank)
        {
            switch (rank)
            {
                case "Initiate": return 50;
                case "Adept": return 100;
                case "Knight": return 150;
                case "Lord": return 200;
                case "Master": return 250;
                default: return 0;
            }
        }
        #endregion

        #region Cleanup
        public void Dispose()
        {
            try
            {
                if (CoreManager.Current != null)
                {
                    CoreManager.Current.ChatBoxMessage -= OnChatBoxMessage;
                }
                
                ClearQuests();
            }
            catch (Exception ex)
            {
                PluginCore.WriteToChat($"Error disposing quest manager: {ex.Message}");
            }
        }
        #endregion
    }
}