using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Decal.Adapter;
using Decal.Adapter.Wrappers;
using Harmony;  // UtilityBelt's Harmony 1.2.0.1 uses old Harmony namespace

namespace MosswartMassacre
{
    /// <summary>
    /// Clean Harmony implementation using UtilityBelt's exact pattern
    /// Uses same namespace convention, same API, same Harmony package (Lib.Harmony 2.2.2)
    /// </summary>
    public static class DecalHarmonyClean
    {
        // Use UtilityBelt's namespace pattern
        private static readonly string harmonyNamespace = "com.mosswartmassacre.decal";
        private static HarmonyInstance harmonyDecal;
        private static bool patchesApplied = false;
        internal static int messagesIntercepted = 0;
        
        // Debug logging for troubleshooting
        private static readonly Queue<string> debugLog = new Queue<string>();
        private const int MAX_DEBUG_ENTRIES = 50;

        /// <summary>
        /// Initialize Harmony patches using UtilityBelt's exact pattern
        /// </summary>
        public static bool Initialize()
        {
            try
            {
                // Use UtilityBelt's exact pattern: lazy initialization check + new Harmony()
                if (harmonyDecal == null)
                    harmonyDecal = HarmonyInstance.Create(harmonyNamespace + ".patches");
                
                // Apply patches using UtilityBelt's approach
                ApplyDecalPatches();
                
                return patchesApplied;
            }
            catch (Exception ex)
            {
                // Only log critical initialization failures
                PluginCore.WriteToChat($"[DECAL] Critical initialization error: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// Apply patches to DECAL's AddChatText methods using UtilityBelt approach
        /// </summary>
        private static void ApplyDecalPatches()
        {
            try
            {
                // PATHWAY 1: Target HooksWrapper.AddChatText 
                PatchHooksWrapper();
                
                // PATHWAY 2: Target Host.Actions.AddChatText (what our plugin uses)
                PatchHostActions();
            }
            catch (Exception ex)
            {
                AddDebugLog($"ApplyDecalPatches failed: {ex.Message}");
            }
        }

        /// <summary>
        /// Patch HooksWrapper.AddChatText methods
        /// </summary>
        private static void PatchHooksWrapper()
        {
            try
            {
                Type hooksWrapperType = typeof(HooksWrapper);

                var allAddChatTextMethods = hooksWrapperType.GetMethods(BindingFlags.Public | BindingFlags.Instance)
                    .Where(m => m.Name == "AddChatText" || m.Name == "AddChatTextRaw").ToArray();
                
                foreach (var method in allAddChatTextMethods)
                {
                    var parameters = method.GetParameters();
                    
                    string prefixMethodName = parameters.Length == 2 ? "AddChatTextPrefixHooks" : 
                                            parameters.Length == 3 ? "AddChatTextPrefixHooks3" : 
                                            "AddChatTextPrefixHooksGeneric";
                    
                    try
                    {
                        ApplySinglePatch(method, prefixMethodName);
                    }
                    catch (Exception ex)
                    {
                        AddDebugLog($"PatchHooksWrapper single patch failed ({prefixMethodName}): {ex.Message}");
                    }
                }
            }
            catch (Exception ex)
            {
                AddDebugLog($"PatchHooksWrapper failed: {ex.Message}");
            }
        }

        /// <summary>
        /// Patch Host.Actions.AddChatText methods (what our plugin uses)
        /// </summary>
        private static void PatchHostActions()
        {
            try
            {
                if (PluginCore.MyHost?.Actions == null)
                {
                    return;
                }

                Type actionsType = PluginCore.MyHost.Actions.GetType();

                // Check if Host.Actions is already a HooksWrapper (to avoid double patching)
                if (actionsType == typeof(HooksWrapper))
                {
                    // PATHWAY 3: Try to patch at PluginHost level
                    PatchPluginHost();
                    return;
                }
                
                var hostAddChatTextMethods = actionsType.GetMethods(BindingFlags.Public | BindingFlags.Instance)
                    .Where(m => m.Name == "AddChatText" || m.Name == "AddChatTextRaw").ToArray();
                
                foreach (var method in hostAddChatTextMethods)
                {
                    var parameters = method.GetParameters();
                    
                    string prefixMethodName = parameters.Length == 3 ? "AddChatTextPrefixHost" : 
                                            parameters.Length == 4 ? "AddChatTextPrefixHost4" : 
                                            "AddChatTextPrefixHostGeneric";
                    
                    try
                    {
                        ApplySinglePatch(method, prefixMethodName);
                    }
                    catch (Exception ex)
                    {
                        AddDebugLog($"PatchHostActions single patch failed ({prefixMethodName}): {ex.Message}");
                    }
                }

                // PATHWAY 3: Try to patch at PluginHost level
                PatchPluginHost();
            }
            catch (Exception ex)
            {
                AddDebugLog($"PatchHostActions failed: {ex.Message}");
            }
        }

        /// <summary>
        /// Try a different approach - patch the actual chat system or find global instances
        /// </summary>
        private static void PatchPluginHost()
        {
            try
            {
                var coreActions = CoreManager.Current?.Actions;
                if (coreActions != null && coreActions != PluginCore.MyHost?.Actions)
                {
                    var coreActionsMethods = coreActions.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance)
                        .Where(m => m.Name == "AddChatText" || m.Name == "AddChatTextRaw" || m.Name == "AddStatusText").ToArray();

                    foreach (var method in coreActionsMethods)
                    {
                        var parameters = method.GetParameters();

                        try
                        {
                            string prefixMethodName = "AddChatTextPrefixCore" + parameters.Length;
                            ApplySinglePatch(method, prefixMethodName);
                        }
                        catch (Exception ex)
                        {
                            AddDebugLog($"PatchPluginHost single patch failed: {ex.Message}");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                AddDebugLog($"PatchPluginHost failed: {ex.Message}");
            }
        }

        /// <summary>
        /// Apply a single patch using UtilityBelt's method
        /// </summary>
        private static void ApplySinglePatch(MethodInfo targetMethod, string prefixMethodName)
        {
            try
            {
                // Get our prefix method
                var prefixMethod = typeof(DecalPatchMethods).GetMethod(prefixMethodName,
                    BindingFlags.Static | BindingFlags.Public);

                if (prefixMethod != null)
                {
                    // Use UtilityBelt's exact approach
                    harmonyDecal.Patch(targetMethod, new HarmonyMethod(prefixMethod));
                    patchesApplied = true;
                }
            }
            catch (Exception ex)
            {
                AddDebugLog($"ApplySinglePatch failed ({prefixMethodName}): {ex.Message}");
            }
        }

        /// <summary>
        /// List available methods for debugging
        /// </summary>
        private static void ListAvailableMethods(Type type)
        {
            var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance)
                .Where(m => m.Name == "AddChatText").ToArray();
            
            foreach (var method in methods)
            {
                var parameters = method.GetParameters();
                string paramInfo = string.Join(", ", parameters.Select(p => p.ParameterType.Name));
            }
        }

        /// <summary>
        /// Clean up patches using UtilityBelt's pattern
        /// </summary>
        public static void Cleanup()
        {
            try
            {
                if (harmonyDecal != null && patchesApplied)
                {
                    // Use UtilityBelt's cleanup pattern
                    harmonyDecal.UnpatchAll(harmonyNamespace + ".patches");
                }
                patchesApplied = false;
            }
            catch (Exception ex)
            {
                AddDebugLog($"Cleanup failed: {ex.Message}");
            }
        }

        /// <summary>
        /// Status checks
        /// </summary>
        public static bool IsActive() => patchesApplied && harmonyDecal != null;
        public static int GetMessagesIntercepted() => messagesIntercepted;

        /// <summary>
        /// Add debug log entry
        /// </summary>
        public static void AddDebugLog(string message)
        {
            lock (debugLog)
            {
                debugLog.Enqueue($"{DateTime.Now:HH:mm:ss.fff} {message}");
                while (debugLog.Count > MAX_DEBUG_ENTRIES)
                {
                    debugLog.Dequeue();
                }
            }
        }

        /// <summary>
        /// Get debug log entries
        /// </summary>
        public static string[] GetDebugLog()
        {
            lock (debugLog)
            {
                return debugLog.ToArray();
            }
        }
    }

    /// <summary>
    /// Patch methods for DECAL interception using UtilityBelt's approach
    /// </summary>
    public static class DecalPatchMethods
    {
        /// <summary>
        /// Prefix method for HooksWrapper.AddChatText(string, int) - intercepts plugin messages via HooksWrapper
        /// </summary>
        public static bool AddChatTextPrefixHooks(string text, int color)
        {
            try
            {
                // Always increment to verify patch is working
                DecalHarmonyClean.messagesIntercepted++;
                
                if (PluginCore.AggressiveChatStreamingEnabled)
                {
                }
                
                // Process ALL messages (including our own) for streaming
                if (!string.IsNullOrEmpty(text))
                {
                    // Process the intercepted message
                    ProcessInterceptedMessage(text, color, "HooksWrapper-2param");
                    
                    // Silent operation - debug output removed
                }
                
                // Always return true to let the original AddChatText continue
                return true;
            }
            catch
            {
                // Never let our interception break other plugins
                return true;
            }
        }

        /// <summary>
        /// Prefix method for HooksWrapper.AddChatText(string, int, int) - 3-parameter version
        /// </summary>
        public static bool AddChatTextPrefixHooks3(string text, int color, int target)
        {
            try
            {
                DecalHarmonyClean.messagesIntercepted++;
                
                if (!string.IsNullOrEmpty(text))
                {
                    ProcessInterceptedMessage(text, color, $"HooksWrapper-3param(target={target})");
                    
                    // Silent operation - debug output removed
                }
                
                return true;
            }
            catch
            {
                return true;
            }
        }

        /// <summary>
        /// Generic prefix method for any other HooksWrapper AddChatText overloads
        /// </summary>
        public static bool AddChatTextPrefixHooksGeneric(string text)
        {
            try
            {
                DecalHarmonyClean.messagesIntercepted++;
                
                if (!string.IsNullOrEmpty(text))
                {
                    ProcessInterceptedMessage(text, 0, "HooksWrapper-generic");
                    
                    // Silent operation - debug output removed
                }
                
                return true;
            }
            catch
            {
                return true;
            }
        }

        /// <summary>
        /// Process intercepted plugin messages
        /// </summary>
        private static void ProcessInterceptedMessage(string text, int color, string source)
        {
            try
            {
                // Identify source plugin
                string sourcePlugin = IdentifySourcePlugin(text);
                
                // Add timestamp
                var timestamp = DateTime.Now.ToString("HH:mm:ss");
                var fullMessage = $"{timestamp} [{sourcePlugin}] {text}";
                
                // Debug logging
                
                // Stream to WebSocket if both debug streaming AND WebSocket are enabled
                if (PluginCore.AggressiveChatStreamingEnabled && PluginCore.WebSocketEnabled)
                {
                    Task.Run(() => WebSocket.SendChatTextAsync(color, text));
                }
            }
            catch (Exception ex)
            {
                DecalHarmonyClean.AddDebugLog($"ProcessInterceptedMessage failed: {ex.Message}");
            }
        }

        /// <summary>
        /// Identify which plugin sent the message using UtilityBelt's patterns
        /// </summary>
        private static string IdentifySourcePlugin(string text)
        {
            // Known plugin prefixes
            if (text.StartsWith("[VTank]")) return "VTank";
            if (text.StartsWith("[UB]") || text.Contains("UtilityBelt")) return "UtilityBelt";
            if (text.StartsWith("[VGI]")) return "VGI";
            if (text.StartsWith("[VI]")) return "VirindiIntegrator";
            if (text.StartsWith("[GoArrow]")) return "GoArrow";
            if (text.StartsWith("[Meta]")) return "Meta";
            if (text.StartsWith("[VTClassic]")) return "VTClassic";
            
            // Pattern-based detection for messages without prefixes
            if (text.Contains("Macro started") || text.Contains("Macro stopped")) return "VTank";
            if (text.Contains("Quest data updated")) return "UtilityBelt";
            if (text.Contains("Database read complete")) return "VGI";
            if (text.Contains("Disconnected, retry")) return "VI";
            
            return "Unknown";
        }

        // ===== HOST.ACTIONS PREFIX METHODS =====

        /// <summary>
        /// Prefix method for Host.Actions.AddChatText(string, int, int) - 3-parameter version
        /// </summary>
        public static bool AddChatTextPrefixHost(string text, int color, int target)
        {
            try
            {
                DecalHarmonyClean.messagesIntercepted++;
                
                if (PluginCore.AggressiveChatStreamingEnabled)
                {
                }
                
                if (!string.IsNullOrEmpty(text) && !text.Contains("[Mosswart Massacre]"))
                {
                    ProcessInterceptedMessage(text, color, $"Host.Actions-3param(target={target})");
                    
                    // Silent operation - debug output removed
                }
                
                return true;
            }
            catch
            {
                return true;
            }
        }

        /// <summary>
        /// Prefix method for Host.Actions.AddChatText(string, int, int, int) - 4-parameter version
        /// </summary>
        public static bool AddChatTextPrefixHost4(string text, int color, int target, int window)
        {
            try
            {
                DecalHarmonyClean.messagesIntercepted++;
                
                if (!string.IsNullOrEmpty(text) && !text.Contains("[Mosswart Massacre]"))
                {
                    ProcessInterceptedMessage(text, color, $"Host.Actions-4param(target={target},window={window})");
                    
                    // Silent operation - debug output removed
                }
                
                return true;
            }
            catch
            {
                return true;
            }
        }

        /// <summary>
        /// Generic prefix method for any other Host.Actions.AddChatText overloads
        /// </summary>
        public static bool AddChatTextPrefixHostGeneric(string text)
        {
            try
            {
                DecalHarmonyClean.messagesIntercepted++;
                
                if (!string.IsNullOrEmpty(text) && !text.Contains("[Mosswart Massacre]"))
                {
                    ProcessInterceptedMessage(text, 0, "Host.Actions-generic");
                    
                    // Silent operation - debug output removed
                }
                
                return true;
            }
            catch
            {
                return true;
            }
        }

        // ===== COREMANAGER.ACTIONS PREFIX METHODS =====

        /// <summary>
        /// Prefix method for CoreManager.Actions methods - trying different instances
        /// </summary>
        public static bool AddChatTextPrefixCore2(string text, int color)
        {
            try
            {
                DecalHarmonyClean.messagesIntercepted++;
                
                if (PluginCore.AggressiveChatStreamingEnabled)
                {
                }
                
                if (!string.IsNullOrEmpty(text) && !text.Contains("[Mosswart Massacre]"))
                {
                    ProcessInterceptedMessage(text, color, "CoreActions-2param");
                    
                    // Silent operation - debug output removed
                }
                
                return true;
            }
            catch
            {
                return true;
            }
        }

        /// <summary>
        /// Prefix method for CoreManager.Actions 3-param methods
        /// </summary>
        public static bool AddChatTextPrefixCore3(string text, int color, int target)
        {
            try
            {
                DecalHarmonyClean.messagesIntercepted++;
                
                if (PluginCore.AggressiveChatStreamingEnabled)
                {
                }
                
                if (!string.IsNullOrEmpty(text) && !text.Contains("[Mosswart Massacre]"))
                {
                    ProcessInterceptedMessage(text, color, $"CoreActions-3param(target={target})");
                    
                    // Silent operation - debug output removed
                }
                
                return true;
            }
            catch
            {
                return true;
            }
        }
    }
}