using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
using MusicBeePlugin.Clouseau.Introspection;
using MusicBeePlugin.Clouseau.Logging;
using NLog;

// Alias to avoid conflict with System.Windows.Forms.MethodInvoker
using ReflectionMethodInvoker = MusicBeePlugin.Clouseau.Introspection.MethodInvoker;

namespace MusicBeePlugin.Clouseau.UI
{
    /// <summary>
    /// Form for browsing and invoking methods on objects via reflection.
    /// Provides a TreeView browser for assemblies, types, and methods with
    /// a details panel for parameter input and invocation.
    /// </summary>
    public class MethodInvokerForm : Form
    {
        private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

        // Dark theme colors (matching DashboardForm)
        private static readonly Color DarkBackground = Color.FromArgb(30, 30, 30);
        private static readonly Color DarkPanel = Color.FromArgb(45, 45, 48);
        private static readonly Color DarkBorder = Color.FromArgb(67, 67, 70);
        private static readonly Color DarkText = Color.FromArgb(241, 241, 241);
        private static readonly Color DarkTextDim = Color.FromArgb(153, 153, 153);
        private static readonly Color DarkAccent = Color.FromArgb(0, 122, 204);
        private static readonly Color DarkHover = Color.FromArgb(62, 62, 64);
        private static readonly Color DarkSuccess = Color.FromArgb(76, 175, 80);
        private static readonly Color DarkError = Color.FromArgb(244, 67, 54);

        // UI Components
        private SplitContainer _mainSplitContainer;
        private TreeView _browseTreeView;
        private Panel _detailsPanel;
        private Label _signatureLabel;
        private Panel _parametersPanel;
        private Button _invokeButton;
        private RichTextBox _resultTextBox;
        private CheckBox _showPrivateCheckbox;
        private TextBox _searchBox;
        private ComboBox _filterComboBox;
        private StatusStrip _statusStrip;
        private ToolStripStatusLabel _statusLabel;

        // Current state
        private readonly ReflectionExplorer _reflectionExplorer;
        private readonly ReflectionMethodInvoker _methodInvoker;
        private readonly EventLogger _eventLogger;
        private ReflectionMethodInvoker.MethodDisplayInfo _selectedMethod;
        private object _selectedInstance;
        private Type _selectedType;
        private List<TextBox> _parameterInputs;
        private Dictionary<TreeNode, object> _nodeTagCache;

        /// <summary>
        /// Creates a new MethodInvokerForm.
        /// </summary>
        /// <param name="eventLogger">Optional event logger for logging invocations.</param>
        public MethodInvokerForm(EventLogger eventLogger = null)
        {
            _reflectionExplorer = new ReflectionExplorer();
            _methodInvoker = new ReflectionMethodInvoker();
            _eventLogger = eventLogger;
            _parameterInputs = new List<TextBox>();
            _nodeTagCache = new Dictionary<TreeNode, object>();

            InitializeForm();
            InitializeComponents();
            PopulateAssemblyTree();
        }

        /// <summary>
        /// Initializes form properties.
        /// </summary>
        private void InitializeForm()
        {
            Text = "Method Invoker - mb_clouseau";
            Size = new Size(1100, 750);
            MinimumSize = new Size(800, 500);
            StartPosition = FormStartPosition.CenterScreen;
            BackColor = DarkBackground;
            ForeColor = DarkText;
        }

        /// <summary>
        /// Initializes all UI components.
        /// </summary>
        private void InitializeComponents()
        {
            SuspendLayout();

            // Main split container - don't set min sizes or splitter distance until Shown
            _mainSplitContainer = new SplitContainer
            {
                Dock = DockStyle.Fill,
                Orientation = Orientation.Vertical,
                BackColor = DarkBackground
            };
            Shown += (s, e) => {
                try {
                    _mainSplitContainer.SplitterDistance = 400;
                    _mainSplitContainer.Panel1MinSize = 200;
                    _mainSplitContainer.Panel2MinSize = 250;
                } catch { }
            };

            // === Left Panel: TreeView with toolbar ===
            var leftPanel = new Panel
            {
                Dock = DockStyle.Fill,
                BackColor = DarkBackground
            };

            // Toolbar
            var toolbar = CreateToolbar();
            leftPanel.Controls.Add(toolbar);

            // TreeView
            _browseTreeView = new TreeView
            {
                Dock = DockStyle.Fill,
                BackColor = DarkPanel,
                ForeColor = DarkText,
                BorderStyle = BorderStyle.None,
                Font = new Font("Consolas", 9F),
                ShowLines = true,
                ShowPlusMinus = true,
                ShowRootLines = true,
                FullRowSelect = true,
                HideSelection = false
            };
            _browseTreeView.AfterSelect += OnTreeNodeSelected;
            _browseTreeView.BeforeExpand += OnTreeNodeExpanding;
            _browseTreeView.NodeMouseDoubleClick += OnTreeNodeDoubleClick;
            leftPanel.Controls.Add(_browseTreeView);

            _mainSplitContainer.Panel1.Controls.Add(leftPanel);

            // === Right Panel: Details and Invocation ===
            _detailsPanel = new Panel
            {
                Dock = DockStyle.Fill,
                BackColor = DarkBackground,
                Padding = new Padding(15)
            };

            CreateDetailsPanel();

            _mainSplitContainer.Panel2.Controls.Add(_detailsPanel);

            Controls.Add(_mainSplitContainer);

            // Status bar
            CreateStatusBar();
            Controls.Add(_statusStrip);

            ResumeLayout(false);
        }

        /// <summary>
        /// Creates the toolbar for the tree view.
        /// </summary>
        private Panel CreateToolbar()
        {
            var toolbar = new Panel
            {
                Dock = DockStyle.Top,
                Height = 80,
                BackColor = DarkPanel,
                Padding = new Padding(10)
            };

            // Row 1: Filter combo, Refresh button
            var filterLabel = new Label
            {
                Text = "Filter:",
                Location = new Point(5, 8),
                AutoSize = true,
                ForeColor = DarkText
            };
            toolbar.Controls.Add(filterLabel);

            _filterComboBox = new ComboBox
            {
                Location = new Point(60, 5),
                Width = 100,
                DropDownStyle = ComboBoxStyle.DropDownList,
                BackColor = DarkPanel,
                ForeColor = DarkText,
                FlatStyle = FlatStyle.Flat
            };
            _filterComboBox.Items.AddRange(new[] { "All", "MusicBee", "Plugins", "UI", "System" });
            _filterComboBox.SelectedIndex = 0;
            _filterComboBox.SelectedIndexChanged += OnFilterChanged;
            toolbar.Controls.Add(_filterComboBox);

            _showPrivateCheckbox = new CheckBox
            {
                Text = "Private",
                Location = new Point(175, 7),
                AutoSize = true,
                ForeColor = DarkText,
                Checked = false
            };
            _showPrivateCheckbox.CheckedChanged += OnShowPrivateChanged;
            toolbar.Controls.Add(_showPrivateCheckbox);

            var refreshButton = CreateDarkButton("Refresh", OnRefreshClick);
            refreshButton.Location = new Point(285, 4);
            refreshButton.Height = 30;
            refreshButton.Width = 80;
            toolbar.Controls.Add(refreshButton);

            // Row 2: Search box
            var searchLabel = new Label
            {
                Text = "Search:",
                Location = new Point(5, 45),
                AutoSize = true,
                ForeColor = DarkText
            };
            toolbar.Controls.Add(searchLabel);

            _searchBox = new TextBox
            {
                Location = new Point(75, 42),
                Width = 180,
                BackColor = DarkPanel,
                ForeColor = DarkText,
                BorderStyle = BorderStyle.FixedSingle
            };
            _searchBox.TextChanged += OnSearchChanged;
            toolbar.Controls.Add(_searchBox);

            var clearSearchButton = CreateDarkButton("X", (s, e) => { _searchBox.Text = ""; });
            clearSearchButton.Location = new Point(260, 43);
            clearSearchButton.Width = 30;
            toolbar.Controls.Add(clearSearchButton);

            return toolbar;
        }

        /// <summary>
        /// Creates the details panel with method info, parameters, and result display.
        /// </summary>
        private void CreateDetailsPanel()
        {
            // WinForms Dock order: Top controls first (in visual order), Fill control last

            // Title (Top - added first, appears at top)
            var titleLabel = new Label
            {
                Text = "Method Details",
                Dock = DockStyle.Top,
                Height = 30,
                Font = new Font("Segoe UI", 10F, FontStyle.Bold),
                ForeColor = DarkText,
                BackColor = DarkPanel
            };
            _detailsPanel.Controls.Add(titleLabel);

            // Signature display (Top - below title)
            _signatureLabel = new Label
            {
                Dock = DockStyle.Top,
                Height = 60,
                Font = new Font("Consolas", 9F),
                ForeColor = DarkAccent,
                BackColor = DarkPanel,
                Text = "Select a method from the tree to see its signature",
                AutoEllipsis = true,
                Padding = new Padding(10, 10, 10, 5)
            };
            _detailsPanel.Controls.Add(_signatureLabel);

            // Parameters section (Top - below signature)
            var parametersGroupBox = new GroupBox
            {
                Text = "Parameters",
                Dock = DockStyle.Top,
                Height = 160,
                ForeColor = DarkText,
                BackColor = DarkPanel,
                Font = new Font("Segoe UI", 9F, FontStyle.Bold)
            };

            _parametersPanel = new Panel
            {
                Dock = DockStyle.Fill,
                AutoScroll = true,
                BackColor = DarkPanel
            };
            parametersGroupBox.Controls.Add(_parametersPanel);
            _detailsPanel.Controls.Add(parametersGroupBox);

            // Invoke button panel (Top - below parameters)
            var invokePanel = new Panel
            {
                Dock = DockStyle.Top,
                Height = 45,
                BackColor = DarkBackground
            };

            _invokeButton = new Button
            {
                Text = "Invoke Method",
                Width = 120,
                Height = 30,
                Location = new Point(10, 8),
                BackColor = DarkSuccess,
                ForeColor = Color.White,
                FlatStyle = FlatStyle.Flat,
                Enabled = false
            };
            _invokeButton.FlatAppearance.BorderSize = 0;
            _invokeButton.Click += OnInvokeClick;
            invokePanel.Controls.Add(_invokeButton);

            var copySignatureButton = CreateDarkButton("Copy", OnCopySignature);
            copySignatureButton.Location = new Point(140, 8);
            copySignatureButton.Width = 70;
            copySignatureButton.Height = 30;
            invokePanel.Controls.Add(copySignatureButton);

            _detailsPanel.Controls.Add(invokePanel);

            // Result section (Fill - added last, takes remaining space)
            var resultGroupBox = new GroupBox
            {
                Text = "Result",
                Dock = DockStyle.Fill,
                ForeColor = DarkText,
                BackColor = DarkPanel,
                Font = new Font("Segoe UI", 9F, FontStyle.Bold)
            };

            _resultTextBox = new RichTextBox
            {
                Dock = DockStyle.Fill,
                BackColor = Color.FromArgb(25, 25, 25),
                ForeColor = DarkText,
                Font = new Font("Consolas", 9F),
                ReadOnly = true,
                BorderStyle = BorderStyle.None,
                Text = "Results will be displayed here after invocation."
            };
            resultGroupBox.Controls.Add(_resultTextBox);
            _detailsPanel.Controls.Add(resultGroupBox);
        }

        /// <summary>
        /// Creates the status bar.
        /// </summary>
        private void CreateStatusBar()
        {
            _statusStrip = new StatusStrip
            {
                BackColor = DarkPanel,
                ForeColor = DarkText,
                SizingGrip = true
            };

            _statusLabel = new ToolStripStatusLabel
            {
                Text = "Ready",
                ForeColor = DarkText
            };
            _statusStrip.Items.Add(_statusLabel);

            var versionLabel = new ToolStripStatusLabel
            {
                Text = $"Method Invoker v{typeof(MethodInvokerForm).Assembly.GetName().Version}",
                ForeColor = DarkTextDim,
                Spring = true,
                TextAlign = ContentAlignment.MiddleRight
            };
            _statusStrip.Items.Add(versionLabel);
        }

        /// <summary>
        /// Creates a dark-themed button.
        /// </summary>
        private Button CreateDarkButton(string text, EventHandler onClick)
        {
            var button = new Button
            {
                Text = text,
                Height = 24,
                BackColor = DarkPanel,
                ForeColor = DarkText,
                FlatStyle = FlatStyle.Flat
            };
            button.FlatAppearance.BorderColor = DarkBorder;
            button.FlatAppearance.MouseOverBackColor = DarkHover;
            button.Click += onClick;
            return button;
        }

        /// <summary>
        /// Populates the assembly tree with loaded assemblies.
        /// </summary>
        private void PopulateAssemblyTree()
        {
            _browseTreeView.BeginUpdate();
            _browseTreeView.Nodes.Clear();
            _nodeTagCache.Clear();

            var filter = _filterComboBox.SelectedItem?.ToString() ?? "All";

            try
            {
                var assemblies = filter == "All"
                    ? _reflectionExplorer.GetLoadedAssemblies()
                    : _reflectionExplorer.GetAssembliesByCategory(filter.ToLower());

                foreach (var asmInfo in assemblies)
                {
                    var asmNode = new TreeNode($"{asmInfo.Name} ({asmInfo.TypeCount} types)")
                    {
                        Tag = new NodeTag { TagType = NodeTagType.Assembly, Assembly = asmInfo.Assembly },
                        ForeColor = Color.FromArgb(100, 200, 255),
                        ImageIndex = 0
                    };

                    // Add placeholder for lazy loading
                    asmNode.Nodes.Add(new TreeNode("Loading...") { ForeColor = DarkTextDim });
                    _browseTreeView.Nodes.Add(asmNode);
                }

                UpdateStatus($"Loaded {assemblies.Count()} assemblies");
            }
            catch (Exception ex)
            {
                Logger.Error(ex, "Error populating assembly tree");
                UpdateStatus($"Error: {ex.Message}");
            }

            _browseTreeView.EndUpdate();
        }

        /// <summary>
        /// Handles tree node expansion (lazy loading).
        /// </summary>
        private void OnTreeNodeExpanding(object sender, TreeViewCancelEventArgs e)
        {
            var node = e.Node;
            var tag = node.Tag as NodeTag;

            if (tag == null) return;

            // Check if already loaded
            if (node.Nodes.Count == 1 && node.Nodes[0].Text == "Loading...")
            {
                node.Nodes.Clear();
                _browseTreeView.BeginUpdate();

                try
                {
                    switch (tag.TagType)
                    {
                        case NodeTagType.Assembly:
                            LoadAssemblyTypes(node, tag.Assembly);
                            break;

                        case NodeTagType.Type:
                            LoadTypeMethods(node, tag.Type);
                            break;
                    }
                }
                catch (Exception ex)
                {
                    Logger.Error(ex, "Error expanding node");
                    node.Nodes.Add(new TreeNode($"Error: {ex.Message}") { ForeColor = DarkError });
                }

                _browseTreeView.EndUpdate();
            }
        }

        /// <summary>
        /// Loads types from an assembly into a tree node.
        /// </summary>
        private void LoadAssemblyTypes(TreeNode parentNode, Assembly assembly)
        {
            var showPrivate = _showPrivateCheckbox.Checked;
            var searchText = _searchBox.Text?.ToLowerInvariant() ?? "";

            try
            {
                var types = _reflectionExplorer.GetTypes(assembly)
                    .Where(t => showPrivate || t.IsPublic)
                    .Where(t => string.IsNullOrEmpty(searchText) ||
                                t.FullName.ToLowerInvariant().Contains(searchText))
                    .Take(500); // Limit for performance

                // Group by namespace
                var namespaces = types
                    .GroupBy(t => t.Namespace ?? "(no namespace)")
                    .OrderBy(g => g.Key);

                foreach (var nsGroup in namespaces)
                {
                    var nsNode = new TreeNode(nsGroup.Key)
                    {
                        Tag = new NodeTag { TagType = NodeTagType.Namespace },
                        ForeColor = Color.FromArgb(200, 200, 100)
                    };

                    foreach (var typeInfo in nsGroup.OrderBy(t => t.Name))
                    {
                        var icon = GetTypeIcon(typeInfo.Type);
                        var typeNode = new TreeNode($"{icon} {typeInfo.Name}")
                        {
                            Tag = new NodeTag { TagType = NodeTagType.Type, Type = typeInfo.Type },
                            ForeColor = typeInfo.IsPublic ? DarkText : DarkTextDim
                        };

                        // Add placeholder for methods
                        typeNode.Nodes.Add(new TreeNode("Loading...") { ForeColor = DarkTextDim });
                        nsNode.Nodes.Add(typeNode);
                    }

                    if (nsNode.Nodes.Count > 0)
                        parentNode.Nodes.Add(nsNode);
                }

                UpdateStatus($"Loaded {types.Count()} types from {assembly.GetName().Name}");
            }
            catch (ReflectionTypeLoadException ex)
            {
                // Load what we can
                var loadedTypes = ex.Types.Where(t => t != null);
                Logger.Warn("Some types could not be loaded from {0}", assembly.GetName().Name);

                foreach (var type in loadedTypes.Take(100))
                {
                    var typeNode = new TreeNode(type.FullName)
                    {
                        Tag = new NodeTag { TagType = NodeTagType.Type, Type = type },
                        ForeColor = DarkTextDim
                    };
                    parentNode.Nodes.Add(typeNode);
                }
            }
        }

        /// <summary>
        /// Loads methods from a type into a tree node.
        /// </summary>
        private void LoadTypeMethods(TreeNode parentNode, Type type)
        {
            var showPrivate = _showPrivateCheckbox.Checked;
            var methods = _methodInvoker.GetMethods(type, showPrivate, includeInherited: false).ToList();

            // Group by static vs instance
            var staticMethods = methods.Where(m => m.IsStatic).ToList();
            var instanceMethods = methods.Where(m => !m.IsStatic).ToList();

            if (staticMethods.Any())
            {
                var staticNode = new TreeNode("Static Methods")
                {
                    ForeColor = Color.FromArgb(150, 200, 255),
                    NodeFont = new Font(_browseTreeView.Font, FontStyle.Bold)
                };

                foreach (var method in staticMethods)
                {
                    AddMethodNode(staticNode, method);
                }
                parentNode.Nodes.Add(staticNode);
            }

            if (instanceMethods.Any())
            {
                var instanceNode = new TreeNode("Instance Methods")
                {
                    ForeColor = Color.FromArgb(150, 255, 150),
                    NodeFont = new Font(_browseTreeView.Font, FontStyle.Bold)
                };

                foreach (var method in instanceMethods)
                {
                    AddMethodNode(instanceNode, method);
                }
                parentNode.Nodes.Add(instanceNode);
            }

            UpdateStatus($"Loaded {methods.Count} methods from {type.Name}");
        }

        /// <summary>
        /// Adds a method node to the tree.
        /// </summary>
        private void AddMethodNode(TreeNode parentNode, ReflectionMethodInvoker.MethodDisplayInfo method)
        {
            var paramCount = method.Parameters?.Length ?? 0;
            var paramSummary = paramCount == 0 ? "()" : $"({paramCount} params)";
            var displayText = $"{method.Name}{paramSummary} : {method.ReturnType}";

            var methodNode = new TreeNode(displayText)
            {
                Tag = new NodeTag
                {
                    TagType = NodeTagType.Method,
                    Method = method,
                    Type = method.DeclaringType
                },
                ForeColor = method.IsPublic ? DarkText : DarkTextDim,
                ToolTipText = method.Signature
            };

            parentNode.Nodes.Add(methodNode);
        }

        /// <summary>
        /// Handles tree node selection.
        /// </summary>
        private void OnTreeNodeSelected(object sender, TreeViewEventArgs e)
        {
            var tag = e.Node?.Tag as NodeTag;
            if (tag == null) return;

            switch (tag.TagType)
            {
                case NodeTagType.Method:
                    SelectMethod(tag.Method, tag.Type);
                    break;

                case NodeTagType.Type:
                    _selectedType = tag.Type;
                    _selectedMethod = null;
                    _selectedInstance = null;
                    _signatureLabel.Text = $"Type: {tag.Type.FullName}\n\nExpand this node to see methods.";
                    _invokeButton.Enabled = false;
                    ClearParametersPanel();
                    break;

                default:
                    _selectedMethod = null;
                    _selectedType = null;
                    _selectedInstance = null;
                    _signatureLabel.Text = "Select a method from the tree to see its signature";
                    _invokeButton.Enabled = false;
                    ClearParametersPanel();
                    break;
            }
        }

        /// <summary>
        /// Selects a method and updates the details panel.
        /// </summary>
        private void SelectMethod(ReflectionMethodInvoker.MethodDisplayInfo method, Type declaringType)
        {
            _selectedMethod = method;
            _selectedType = declaringType;
            _selectedInstance = null;

            // Update signature display
            _signatureLabel.Text = method.Signature;

            // Build parameters UI
            BuildParametersUI(method);

            // Enable invoke button for static methods
            // Instance methods need additional handling
            if (method.IsStatic)
            {
                _invokeButton.Enabled = true;
                _invokeButton.Text = "Invoke Static Method";
            }
            else
            {
                _invokeButton.Enabled = false;
                _invokeButton.Text = "Invoke (instance required)";
            }

            UpdateStatus($"Selected: {method.Name}");
        }

        /// <summary>
        /// Builds the parameters input UI for a method.
        /// </summary>
        private void BuildParametersUI(ReflectionMethodInvoker.MethodDisplayInfo method)
        {
            ClearParametersPanel();

            if (method.Parameters == null || method.Parameters.Length == 0)
            {
                var noParamsLabel = new Label
                {
                    Text = "This method has no parameters.",
                    Location = new Point(10, 10),
                    AutoSize = true,
                    ForeColor = DarkTextDim
                };
                _parametersPanel.Controls.Add(noParamsLabel);
                return;
            }

            int yPos = 10;
            foreach (var param in method.Parameters)
            {
                // Parameter label
                var label = new Label
                {
                    Text = $"{param.TypeName} {param.Name}" + (param.IsOptional ? " (optional)" : ""),
                    Location = new Point(10, yPos),
                    AutoSize = true,
                    ForeColor = DarkText,
                    Font = new Font("Segoe UI", 9F)
                };
                _parametersPanel.Controls.Add(label);

                yPos += 20;

                // Input control - use ComboBox for enums
                Control inputControl;
                if (param.EnumValues != null && param.EnumValues.Length > 0)
                {
                    var combo = new ComboBox
                    {
                        Location = new Point(10, yPos),
                        Width = 300,
                        DropDownStyle = ComboBoxStyle.DropDownList,
                        BackColor = DarkPanel,
                        ForeColor = DarkText,
                        FlatStyle = FlatStyle.Flat,
                        Tag = param
                    };
                    combo.Items.AddRange(param.EnumValues);
                    if (param.HasDefaultValue && param.DefaultValue != null)
                    {
                        var defaultName = param.DefaultValue.ToString();
                        var idx = combo.Items.IndexOf(defaultName);
                        if (idx >= 0) combo.SelectedIndex = idx;
                    }
                    else if (combo.Items.Count > 0)
                    {
                        combo.SelectedIndex = 0;
                    }
                    inputControl = combo;
                }
                else if (param.ParameterType == typeof(bool))
                {
                    var checkbox = new CheckBox
                    {
                        Location = new Point(10, yPos),
                        Text = "true",
                        Checked = param.HasDefaultValue && param.DefaultValue is bool b && b,
                        ForeColor = DarkText,
                        Tag = param
                    };
                    inputControl = checkbox;
                }
                else
                {
                    var textBox = new TextBox
                    {
                        Location = new Point(10, yPos),
                        Width = 300,
                        BackColor = DarkPanel,
                        ForeColor = DarkText,
                        BorderStyle = BorderStyle.FixedSingle,
                        Tag = param
                    };

                    // Set default value if available
                    if (param.HasDefaultValue && param.DefaultValue != null)
                    {
                        textBox.Text = param.DefaultValue.ToString();
                    }

                    // Add placeholder text
                    if (string.IsNullOrEmpty(textBox.Text))
                    {
                        textBox.ForeColor = DarkTextDim;
                        textBox.Text = $"Enter {param.TypeName}...";
                        textBox.GotFocus += (s, e) =>
                        {
                            var tb = s as TextBox;
                            if (tb.ForeColor == DarkTextDim)
                            {
                                tb.Text = "";
                                tb.ForeColor = DarkText;
                            }
                        };
                    }

                    inputControl = textBox;
                    _parameterInputs.Add(textBox);
                }

                _parametersPanel.Controls.Add(inputControl);
                yPos += 30;
            }
        }

        /// <summary>
        /// Clears the parameters panel.
        /// </summary>
        private void ClearParametersPanel()
        {
            _parametersPanel.Controls.Clear();
            _parameterInputs.Clear();
        }

        /// <summary>
        /// Handles the Invoke button click.
        /// </summary>
        private void OnInvokeClick(object sender, EventArgs e)
        {
            if (_selectedMethod == null)
            {
                ShowError("No method selected.");
                return;
            }

            try
            {
                // Collect and parse parameters
                var args = CollectParameters();
                if (args == null) return; // Error already shown

                // Invoke the method
                _resultTextBox.Clear();
                _resultTextBox.SelectionColor = DarkText;
                _resultTextBox.AppendText($"Invoking: {_selectedMethod.Name}...\n\n");

                ReflectionMethodInvoker.InvocationResult result;

                if (_selectedMethod.IsStatic)
                {
                    result = _methodInvoker.InvokeStaticMethod(_selectedType, _selectedMethod.Name, args);
                }
                else if (_selectedInstance != null)
                {
                    result = _methodInvoker.InvokeInstanceMethod(_selectedInstance, _selectedMethod.Name, args);
                }
                else
                {
                    ShowError("Instance method requires an object instance. Static methods only for now.");
                    return;
                }

                // Display results
                DisplayResult(result);

                // Log the invocation
                LogInvocation(result);
            }
            catch (Exception ex)
            {
                Logger.Error(ex, "Error invoking method");
                ShowError($"Error: {ex.Message}");
            }
        }

        /// <summary>
        /// Collects parameter values from the UI.
        /// </summary>
        private object[] CollectParameters()
        {
            if (_selectedMethod?.Parameters == null || _selectedMethod.Parameters.Length == 0)
                return Array.Empty<object>();

            var args = new object[_selectedMethod.Parameters.Length];

            for (int i = 0; i < _selectedMethod.Parameters.Length; i++)
            {
                var param = _selectedMethod.Parameters[i];
                var control = FindParameterControl(param);

                if (control == null)
                {
                    if (param.HasDefaultValue)
                    {
                        args[i] = param.DefaultValue;
                        continue;
                    }
                    ShowError($"Could not find input for parameter: {param.Name}");
                    return null;
                }

                string inputValue = GetControlValue(control);

                // Handle empty optional parameters
                if (string.IsNullOrEmpty(inputValue) || inputValue.StartsWith("Enter "))
                {
                    if (param.HasDefaultValue)
                    {
                        args[i] = param.DefaultValue;
                        continue;
                    }
                    else if (!param.ParameterType.IsValueType)
                    {
                        args[i] = null;
                        continue;
                    }
                }

                // Parse the value
                if (!_methodInvoker.TryParseParameter(inputValue, param.ParameterType, out var parsed, out var error))
                {
                    ShowError($"Invalid value for {param.Name}: {error}");
                    return null;
                }

                args[i] = parsed;
            }

            return args;
        }

        /// <summary>
        /// Finds the input control for a parameter.
        /// </summary>
        private Control FindParameterControl(ReflectionMethodInvoker.ParameterDisplayInfo param)
        {
            foreach (Control control in _parametersPanel.Controls)
            {
                var tag = control.Tag as ReflectionMethodInvoker.ParameterDisplayInfo;
                if (tag?.Name == param.Name)
                    return control;
            }
            return null;
        }

        /// <summary>
        /// Gets the string value from a control.
        /// </summary>
        private string GetControlValue(Control control)
        {
            if (control is TextBox tb)
                return tb.Text;
            if (control is ComboBox cb)
                return cb.SelectedItem?.ToString() ?? "";
            if (control is CheckBox chk)
                return chk.Checked.ToString();
            return "";
        }

        /// <summary>
        /// Displays the invocation result.
        /// </summary>
        private void DisplayResult(ReflectionMethodInvoker.InvocationResult result)
        {
            _resultTextBox.Clear();

            if (result.Success)
            {
                _resultTextBox.SelectionColor = DarkSuccess;
                _resultTextBox.AppendText("SUCCESS\n\n");

                _resultTextBox.SelectionColor = DarkText;
                _resultTextBox.AppendText($"Execution Time: {result.ExecutionTimeMs:F3} ms\n\n");

                _resultTextBox.SelectionColor = DarkAccent;
                _resultTextBox.AppendText($"Return Type: {_methodInvoker.GetTypeName(result.ReturnType)}\n\n");

                _resultTextBox.SelectionColor = DarkText;
                _resultTextBox.AppendText("Return Value:\n");
                _resultTextBox.SelectionColor = Color.FromArgb(150, 255, 150);
                _resultTextBox.AppendText(result.FormattedReturnValue ?? "(null)");

                UpdateStatus("Invocation successful");
            }
            else
            {
                _resultTextBox.SelectionColor = DarkError;
                _resultTextBox.AppendText("FAILED\n\n");

                _resultTextBox.SelectionColor = DarkText;
                _resultTextBox.AppendText($"Error: {result.ErrorMessage}\n");

                if (result.Exception != null)
                {
                    _resultTextBox.SelectionColor = DarkTextDim;
                    _resultTextBox.AppendText($"\nStack Trace:\n{result.Exception.StackTrace}");
                }

                UpdateStatus("Invocation failed");
            }
        }

        /// <summary>
        /// Logs the invocation to the event logger.
        /// </summary>
        private void LogInvocation(ReflectionMethodInvoker.InvocationResult result)
        {
            if (_eventLogger == null) return;

            var entry = new LogEntry(
                EventCategory.System,
                "MethodInvocation",
                0,
                $"Invoked {_selectedType?.Name}.{_selectedMethod?.Name}: {(result.Success ? "Success" : "Failed")}",
                result.Success ? Logging.LogLevel.Info : Logging.LogLevel.Error
            );

            entry.WithContext("MethodName", _selectedMethod?.Name)
                 .WithContext("TypeName", _selectedType?.FullName)
                 .WithContext("Success", result.Success)
                 .WithContext("ExecutionTimeMs", result.ExecutionTimeMs);

            if (!result.Success)
            {
                entry.WithContext("ErrorMessage", result.ErrorMessage);
            }
        }

        /// <summary>
        /// Shows an error message in the result panel.
        /// </summary>
        private void ShowError(string message)
        {
            _resultTextBox.Clear();
            _resultTextBox.SelectionColor = DarkError;
            _resultTextBox.AppendText("ERROR\n\n");
            _resultTextBox.SelectionColor = DarkText;
            _resultTextBox.AppendText(message);
        }

        /// <summary>
        /// Updates the status bar.
        /// </summary>
        private void UpdateStatus(string message)
        {
            if (_statusLabel != null)
                _statusLabel.Text = message;
        }

        /// <summary>
        /// Gets an icon character for a type.
        /// </summary>
        private string GetTypeIcon(Type type)
        {
            if (type.IsInterface) return "[I]";
            if (type.IsEnum) return "[E]";
            if (type.IsValueType) return "[S]";
            if (type.IsAbstract && type.IsSealed) return "[S]"; // Static class
            if (type.IsAbstract) return "[A]";
            return "[C]";
        }

        #region Event Handlers

        private void OnFilterChanged(object sender, EventArgs e)
        {
            PopulateAssemblyTree();
        }

        private void OnShowPrivateChanged(object sender, EventArgs e)
        {
            // Refresh current view
            if (_browseTreeView.SelectedNode?.Tag is NodeTag tag && tag.TagType == NodeTagType.Type)
            {
                var node = _browseTreeView.SelectedNode;
                node.Nodes.Clear();
                node.Nodes.Add(new TreeNode("Loading...") { ForeColor = DarkTextDim });
                node.Collapse();
                node.Expand();
            }
        }

        private void OnSearchChanged(object sender, EventArgs e)
        {
            // Debounce search
            var searchText = _searchBox.Text?.ToLowerInvariant() ?? "";
            if (searchText.Length >= 2 || string.IsNullOrEmpty(searchText))
            {
                PopulateAssemblyTree();
            }
        }

        private void OnRefreshClick(object sender, EventArgs e)
        {
            PopulateAssemblyTree();
        }

        private void OnTreeNodeDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            var tag = e.Node?.Tag as NodeTag;
            if (tag?.TagType == NodeTagType.Method && tag.Method.IsStatic)
            {
                OnInvokeClick(sender, e);
            }
        }

        private void OnCopySignature(object sender, EventArgs e)
        {
            if (_selectedMethod != null)
            {
                Clipboard.SetText(_selectedMethod.Signature);
                UpdateStatus("Signature copied to clipboard");
            }
        }

        #endregion

        #region Helper Classes

        private enum NodeTagType
        {
            Assembly,
            Namespace,
            Type,
            Method
        }

        private class NodeTag
        {
            public NodeTagType TagType { get; set; }
            public Assembly Assembly { get; set; }
            public Type Type { get; set; }
            public ReflectionMethodInvoker.MethodDisplayInfo Method { get; set; }
        }

        #endregion
    }
}
