using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MusicBeePlugin.Clouseau.Core;
using MusicBeePlugin.Clouseau.Introspection;
using MusicBeePlugin.Clouseau.Logging;
using MusicBeePlugin.Clouseau.Metrics;
using NLog;

namespace MusicBeePlugin.Clouseau.UI
{
    /// <summary>
    /// Full dashboard window for mbClouseau.
    /// Provides comprehensive view of events, metrics, plugins, and dumps.
    /// Dark theme consistent with MusicBee.
    /// </summary>
    public class DashboardForm : Form
    {
        private static readonly Logger Logger = NLog.LogManager.GetCurrentClassLogger();

        // Dark theme colors
        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 DarkSelection = Color.FromArgb(51, 51, 51);
        private static readonly Color DarkHover = Color.FromArgb(62, 62, 64);

        // UI Components
        private MenuStrip _menuStrip;
        private TabControl _tabControl;
        private StatusStrip _statusStrip;
        private ToolStripStatusLabel _sessionDurationLabel;
        private ToolStripStatusLabel _eventCountLabel;
        private Timer _statusTimer;

        // Tab pages
        private TabPage _overviewTab;
        private TabPage _eventsTab;
        private TabPage _metricsTab;
        private TabPage _pluginsTab;
        private TabPage _dumpsTab;
        private TabPage _spyTab;
        private TabPage _invokeTab;
        private TabPage _handlersTab;

        // Overview tab components
        private Label _sessionInfoLabel;
        private Label _eventStatsLabel;
        private Label _musicBeeInfoLabel;
        private Button _overviewExportButton;

        // Components on tabs
        private LogViewerPanel _logViewer;
        private ListView _pluginsListView;
        private ListView _dumpsListView;
        private Label _metricsLabel;
        private Button _metricsExportButton;
        private Button _pluginsExportButton;

        // Spy tab components
        private TreeView _spyTreeView;
        private ListView _spyMetadataList;
        private ListView _spyEventsList;
        private TextBox _spySearchBox;
        private ReflectionExplorer _reflectionExplorer;
        private SpyToolbar _spyToolbar;
        private SplitContainer _spyMainSplit;
        private SplitContainer _spyRightSplit;
        private ToolStripButton _spyOverlayButton;

        // Dependencies
        private readonly Plugin.MusicBeeApiInterface _mbApi;
        private readonly string _dataFolder;
        private readonly string _pluginsPath;
        private readonly ClouseauSettings _settings;
        private readonly StateManager _stateManager;
        private readonly MetricsCollector _metricsCollector;
        private readonly EventLogger _eventLogger;
        private readonly PluginDiscovery _pluginDiscovery;
        private readonly StateDumper _stateDumper;

        // State
        private readonly DateTime _sessionStartTime;

        /// <summary>
        /// Creates a new DashboardForm with full dependency injection.
        /// </summary>
        /// <param name="mbApi">MusicBee API interface.</param>
        /// <param name="dataFolder">Data folder for dumps.</param>
        /// <param name="pluginsPath">Path to MusicBee Plugins folder.</param>
        /// <param name="settings">Clouseau settings.</param>
        /// <param name="stateManager">State manager for session tracking.</param>
        /// <param name="metricsCollector">Metrics collector for system metrics.</param>
        /// <param name="eventLogger">Event logger for log entries.</param>
        /// <param name="pluginDiscovery">Plugin discovery for plugin enumeration.</param>
        public DashboardForm(
            Plugin.MusicBeeApiInterface mbApi,
            string dataFolder,
            string pluginsPath,
            ClouseauSettings settings = null,
            StateManager stateManager = null,
            MetricsCollector metricsCollector = null,
            EventLogger eventLogger = null,
            PluginDiscovery pluginDiscovery = null)
        {
            _mbApi = mbApi;
            _dataFolder = dataFolder;
            _pluginsPath = pluginsPath;
            _settings = settings ?? new ClouseauSettings();
            _stateManager = stateManager;
            _metricsCollector = metricsCollector;
            _eventLogger = eventLogger;
            _sessionStartTime = stateManager?.SessionStartTime ?? DateTime.Now;

            // Initialize helpers
            _stateDumper = new StateDumper(mbApi, Path.Combine(dataFolder, "dumps"), pluginsPath);
            _pluginDiscovery = pluginDiscovery ?? new PluginDiscovery(pluginsPath);

            // Subscribe to event logger if available
            if (_eventLogger != null)
            {
                _eventLogger.LogEntryAdded += OnEventLoggerEntryAdded;
            }

            // Form properties
            Text = "mbClouseau Dashboard";
            Size = new Size(1300, 920);
            MinimumSize = new Size(1000, 800);
            StartPosition = FormStartPosition.CenterScreen;
            Icon = null; // No icon in MVP

            // Apply dark theme to form
            BackColor = DarkBackground;
            ForeColor = DarkText;

            // Initialize components
            InitializeMenu();
            InitializeTabs();
            InitializeStatusBar();

            // Add controls in order
            Controls.Add(_tabControl);
            Controls.Add(_menuStrip);
            Controls.Add(_statusStrip);

            MainMenuStrip = _menuStrip;

            // Status update timer (1 second for real-time updates)
            _statusTimer = new Timer { Interval = 1000 };
            _statusTimer.Tick += OnStatusTimerTick;
            _statusTimer.Start();

            // Set splitter distances after form loads to avoid sizing errors
            Load += (s, e) =>
            {
                try
                {
                    if (_spyMainSplit != null && _spyMainSplit.Width > 400)
                        _spyMainSplit.SplitterDistance = (int)(_spyMainSplit.Width * 0.45); // 45% left
                    if (_spyRightSplit != null && _spyRightSplit.Height > 300)
                        _spyRightSplit.SplitterDistance = (int)(_spyRightSplit.Height * 0.45); // 45% top
                }
                catch { /* Ignore sizing errors */ }
            };

            // Load initial data
            RefreshPlugins();
            RefreshDumps();
            UpdateOverviewDisplay();
            UpdateMetricsDisplay();
        }

        /// <summary>
        /// Backward-compatible constructor.
        /// </summary>
        public DashboardForm(Plugin.MusicBeeApiInterface mbApi, string dataFolder, string pluginsPath)
            : this(mbApi, dataFolder, pluginsPath, null, null, null, null, null)
        {
        }

        /// <summary>
        /// Handles new log entries from EventLogger.
        /// </summary>
        private void OnEventLoggerEntryAdded(object sender, LogEntry entry)
        {
            if (entry != null)
            {
                AddLogEntry(entry);
            }
        }

        /// <summary>
        /// Applies dark theme to a control and its children.
        /// </summary>
        private void ApplyDarkTheme(Control control)
        {
            control.BackColor = DarkBackground;
            control.ForeColor = DarkText;

            if (control is ListView lv)
            {
                lv.BackColor = DarkPanel;
                lv.ForeColor = DarkText;
            }
            else if (control is TextBox tb)
            {
                tb.BackColor = DarkPanel;
                tb.ForeColor = DarkText;
                tb.BorderStyle = BorderStyle.FixedSingle;
            }
            else if (control is Button btn)
            {
                btn.BackColor = DarkPanel;
                btn.ForeColor = DarkText;
                btn.FlatStyle = FlatStyle.Flat;
                btn.FlatAppearance.BorderColor = DarkBorder;
                btn.FlatAppearance.MouseOverBackColor = DarkHover;
            }
            else if (control is ComboBox cb)
            {
                cb.BackColor = DarkPanel;
                cb.ForeColor = DarkText;
                cb.FlatStyle = FlatStyle.Flat;
            }
            else if (control is Label lbl)
            {
                lbl.ForeColor = DarkText;
            }
            else if (control is CheckBox chk)
            {
                chk.ForeColor = DarkText;
            }

            foreach (Control child in control.Controls)
            {
                ApplyDarkTheme(child);
            }
        }

        /// <summary>
        /// Initializes the menu bar with dark theme.
        /// </summary>
        private void InitializeMenu()
        {
            _menuStrip = new MenuStrip
            {
                BackColor = DarkPanel,
                ForeColor = DarkText,
                Renderer = new DarkMenuRenderer()
            };

            // File menu
            var fileMenu = new ToolStripMenuItem("File") { ForeColor = DarkText };

            var exportItem = new ToolStripMenuItem("Export Log...", null, OnExportLog) { ForeColor = DarkText };
            exportItem.ShortcutKeys = Keys.Control | Keys.E;
            fileMenu.DropDownItems.Add(exportItem);

            var createDumpItem = new ToolStripMenuItem("Create State Dump", null, OnCreateDump) { ForeColor = DarkText };
            createDumpItem.ShortcutKeys = Keys.Control | Keys.D;
            fileMenu.DropDownItems.Add(createDumpItem);

            fileMenu.DropDownItems.Add(new ToolStripSeparator());

            var closeItem = new ToolStripMenuItem("Close", null, (s, e) => Close()) { ForeColor = DarkText };
            closeItem.ShortcutKeys = Keys.Alt | Keys.F4;
            fileMenu.DropDownItems.Add(closeItem);

            _menuStrip.Items.Add(fileMenu);

            // View menu
            var viewMenu = new ToolStripMenuItem("View") { ForeColor = DarkText };

            var refreshItem = new ToolStripMenuItem("Refresh All", null, OnRefreshAll) { ForeColor = DarkText };
            refreshItem.ShortcutKeys = Keys.F5;
            viewMenu.DropDownItems.Add(refreshItem);

            var refreshPluginsItem = new ToolStripMenuItem("Refresh Plugins", null, (s, e) => RefreshPlugins()) { ForeColor = DarkText };
            viewMenu.DropDownItems.Add(refreshPluginsItem);

            var refreshDumpsItem = new ToolStripMenuItem("Refresh Dumps", null, (s, e) => RefreshDumps()) { ForeColor = DarkText };
            viewMenu.DropDownItems.Add(refreshDumpsItem);

            viewMenu.DropDownItems.Add(new ToolStripSeparator());

            var clearLogItem = new ToolStripMenuItem("Clear Log", null, OnClearLog) { ForeColor = DarkText };
            viewMenu.DropDownItems.Add(clearLogItem);

            viewMenu.DropDownItems.Add(new ToolStripSeparator());

            var uiGalleryItem = new ToolStripMenuItem("UI Gallery...", null, OnOpenUIGallery) { ForeColor = DarkText };
            uiGalleryItem.ShortcutKeys = Keys.Control | Keys.G;
            viewMenu.DropDownItems.Add(uiGalleryItem);

            var methodInvokerItem = new ToolStripMenuItem("Method Invoker...", null, OnOpenMethodInvoker) { ForeColor = DarkText };
            methodInvokerItem.ShortcutKeys = Keys.Control | Keys.I;
            viewMenu.DropDownItems.Add(methodInvokerItem);

            _menuStrip.Items.Add(viewMenu);

            // Help menu
            var helpMenu = new ToolStripMenuItem("Help") { ForeColor = DarkText };

            var checkUpdatesItem = new ToolStripMenuItem("Check for Updates", null, (s, args) =>
            {
                try { System.Diagnostics.Process.Start("https://halrad.com/mbClouseau/download.html"); }
                catch { }
            }) { ForeColor = DarkText };
            helpMenu.DropDownItems.Add(checkUpdatesItem);
            helpMenu.DropDownItems.Add(new ToolStripSeparator());

            var aboutItem = new ToolStripMenuItem("About mbClouseau", null, OnAbout) { ForeColor = DarkText };
            helpMenu.DropDownItems.Add(aboutItem);

            _menuStrip.Items.Add(helpMenu);
        }

        /// <summary>
        /// Initializes the tab control and pages with dark theme.
        /// </summary>
        private void InitializeTabs()
        {
            _tabControl = new TabControl
            {
                Dock = DockStyle.Fill,
                BackColor = DarkBackground,
                ForeColor = DarkText
            };

            // Create all tabs
            _overviewTab = CreateOverviewTab();
            _eventsTab = CreateEventsTab();
            _metricsTab = CreateMetricsTab();
            _pluginsTab = CreatePluginsTab();
            _dumpsTab = CreateDumpsTab();
            _spyTab = CreateSpyTab();
            _invokeTab = CreateInvokeTab();
            _handlersTab = CreateHandlersTab();

            _tabControl.TabPages.Add(_overviewTab);
            _tabControl.TabPages.Add(_eventsTab);
            _tabControl.TabPages.Add(_metricsTab);
            _tabControl.TabPages.Add(_pluginsTab);
            _tabControl.TabPages.Add(_dumpsTab);
            _tabControl.TabPages.Add(_spyTab);
            _tabControl.TabPages.Add(_invokeTab);
            _tabControl.TabPages.Add(_handlersTab);

            // Apply dark theme to tab control
            _tabControl.DrawMode = TabDrawMode.OwnerDrawFixed;
            _tabControl.DrawItem += OnDrawTabItem;
        }

        /// <summary>
        /// Custom draw for dark-themed tabs.
        /// </summary>
        private void OnDrawTabItem(object sender, DrawItemEventArgs e)
        {
            var tabControl = sender as TabControl;
            var tabPage = tabControl.TabPages[e.Index];
            var tabRect = tabControl.GetTabRect(e.Index);

            var isSelected = e.Index == tabControl.SelectedIndex;
            var backgroundColor = isSelected ? DarkAccent : DarkPanel;
            var textColor = isSelected ? Color.White : DarkText;

            using (var brush = new SolidBrush(backgroundColor))
            {
                e.Graphics.FillRectangle(brush, tabRect);
            }

            using (var brush = new SolidBrush(textColor))
            {
                var flags = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter;
                TextRenderer.DrawText(e.Graphics, tabPage.Text, e.Font, tabRect, textColor, flags);
            }
        }

        /// <summary>
        /// Creates the Overview tab with session info, uptime, and event counts.
        /// </summary>
        private TabPage CreateOverviewTab()
        {
            var tab = new TabPage("Overview")
            {
                BackColor = DarkBackground,
                ForeColor = DarkText
            };

            // Container for header + main content
            var container = new Panel
            {
                Dock = DockStyle.Fill,
                BackColor = DarkBackground
            };

            // Header panel with logo and version
            var headerPanel = new Panel
            {
                Dock = DockStyle.Top,
                Height = 80,
                BackColor = DarkPanel,
                Padding = new Padding(15, 10, 15, 10)
            };

            // Try to load the Clouseau icon from embedded resource
            var iconBox = new PictureBox
            {
                Size = new Size(60, 60),
                Location = new Point(15, 10),
                SizeMode = PictureBoxSizeMode.Zoom,
                BackColor = Color.Transparent
            };
            try
            {
                // Load from embedded resource
                var assembly = System.Reflection.Assembly.GetExecutingAssembly();
                using (var stream = assembly.GetManifestResourceStream("HALRAD_mb_Clouseau.png"))
                {
                    if (stream != null)
                    {
                        iconBox.Image = Image.FromStream(stream);
                    }
                }
            }
            catch { /* Icon is optional */ }
            headerPanel.Controls.Add(iconBox);

            var titleLabel = new Label
            {
                Text = "mbClouseau",
                Location = new Point(85, 12),
                AutoSize = true,
                Font = new Font("Segoe UI", 18F, FontStyle.Bold),
                ForeColor = Color.FromArgb(100, 180, 255)
            };
            headerPanel.Controls.Add(titleLabel);

            var taglineLabel = new Label
            {
                Text = "MusicBee Debug & Trace Utility",
                Location = new Point(585, 40),
                AutoSize = true,
                Font = new Font("Segoe UI", 9F, FontStyle.Italic),
                ForeColor = Color.FromArgb(180, 180, 180)
            };
            headerPanel.Controls.Add(taglineLabel);

            var versionLabel = new Label
            {
                Text = $"v{typeof(DashboardForm).Assembly.GetName().Version}",
                AutoSize = true,
                Font = new Font("Segoe UI", 9F),
                ForeColor = DarkText,
                Anchor = AnchorStyles.Top | AnchorStyles.Right
            };
            versionLabel.Location = new Point(headerPanel.Width - versionLabel.PreferredWidth - 20, 48);
            headerPanel.Controls.Add(versionLabel);

            var mainPanel = new TableLayoutPanel
            {
                Dock = DockStyle.Fill,
                ColumnCount = 2,
                RowCount = 2,
                BackColor = DarkBackground,
                Padding = new Padding(10)
            };

            mainPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
            mainPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
            mainPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
            mainPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));

            // Session Info Panel (top-left)
            var sessionPanel = CreateInfoPanel("Session Information");
            _sessionInfoLabel = new Label
            {
                Dock = DockStyle.Fill,
                Font = new Font("Consolas", 10F),
                ForeColor = DarkText,
                Text = "Loading...",
                Padding = new Padding(10)
            };
            sessionPanel.Controls.Add(_sessionInfoLabel);
            mainPanel.Controls.Add(sessionPanel, 0, 0);

            // Event Stats Panel (top-right)
            var eventPanel = CreateInfoPanel("Event Statistics");
            _eventStatsLabel = new Label
            {
                Dock = DockStyle.Fill,
                Font = new Font("Consolas", 10F),
                ForeColor = DarkText,
                Text = "Loading...",
                Padding = new Padding(10)
            };
            eventPanel.Controls.Add(_eventStatsLabel);
            mainPanel.Controls.Add(eventPanel, 1, 0);

            // MusicBee Info Panel (bottom-left)
            var mbPanel = CreateInfoPanel("MusicBee Information");
            _musicBeeInfoLabel = new Label
            {
                Dock = DockStyle.Fill,
                Font = new Font("Consolas", 10F),
                ForeColor = DarkText,
                Text = "Loading...",
                Padding = new Padding(10)
            };
            mbPanel.Controls.Add(_musicBeeInfoLabel);
            mainPanel.Controls.Add(mbPanel, 0, 1);

            // Actions Panel (bottom-right)
            var actionsPanel = CreateInfoPanel("Quick Actions");
            var actionsContent = new FlowLayoutPanel
            {
                Dock = DockStyle.Fill,
                FlowDirection = FlowDirection.TopDown,
                Padding = new Padding(10),
                BackColor = DarkPanel
            };

            var dumpButton = CreateDarkButton("Create State Dump", OnCreateDump);
            dumpButton.Width = 280;
            dumpButton.Height = 45;
            dumpButton.Margin = new Padding(5, 10, 5, 5);
            actionsContent.Controls.Add(dumpButton);

            var refreshButton = CreateDarkButton("Refresh All", OnRefreshAll);
            refreshButton.Width = 280;
            refreshButton.Height = 45;
            refreshButton.Margin = new Padding(5, 10, 5, 5);
            actionsContent.Controls.Add(refreshButton);

            _overviewExportButton = CreateDarkButton("Export Overview", OnExportOverview);
            _overviewExportButton.Width = 280;
            _overviewExportButton.Height = 45;
            _overviewExportButton.Margin = new Padding(5, 10, 5, 5);
            actionsContent.Controls.Add(_overviewExportButton);

            var uiGalleryButton = CreateDarkButton("UI Gallery", OnOpenUIGallery);
            uiGalleryButton.Width = 280;
            uiGalleryButton.Height = 45;
            uiGalleryButton.Margin = new Padding(5, 10, 5, 5);
            actionsContent.Controls.Add(uiGalleryButton);

            actionsPanel.Controls.Add(actionsContent);
            mainPanel.Controls.Add(actionsPanel, 1, 1);

            // Add header and main panel to container (order matters for docking)
            container.Controls.Add(mainPanel);
            container.Controls.Add(headerPanel);
            tab.Controls.Add(container);
            return tab;
        }

        /// <summary>
        /// Creates a styled info panel with a title.
        /// </summary>
        private GroupBox CreateInfoPanel(string title)
        {
            var panel = new GroupBox
            {
                Text = title,
                Dock = DockStyle.Fill,
                Margin = new Padding(5),
                BackColor = DarkPanel,
                ForeColor = DarkText,
                Font = new Font("Segoe UI", 9F, FontStyle.Bold)
            };
            return panel;
        }

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

        /// <summary>
        /// Creates the Events tab with full log viewer.
        /// </summary>
        private TabPage CreateEventsTab()
        {
            var tab = new TabPage("Events")
            {
                BackColor = DarkBackground
            };

            _logViewer = new LogViewerPanel(5000);
            _logViewer.Dock = DockStyle.Fill;
            _logViewer.ShowDashboardButton = false; // Already in Dashboard
            _logViewer.ShowStatusBar = false; // Dashboard has its own status bar
            ApplyDarkTheme(_logViewer);

            tab.Controls.Add(_logViewer);

            return tab;
        }

        /// <summary>
        /// Creates the Metrics tab with real-time metrics display.
        /// </summary>
        private TabPage CreateMetricsTab()
        {
            var tab = new TabPage("Metrics")
            {
                BackColor = DarkBackground
            };

            var panel = new Panel
            {
                Dock = DockStyle.Fill,
                Padding = new Padding(15),
                BackColor = DarkBackground
            };

            // Toolbar at top
            var toolbar = new Panel
            {
                Dock = DockStyle.Top,
                Height = 55,
                BackColor = DarkPanel,
                Padding = new Padding(10, 12, 10, 10)
            };

            _metricsExportButton = CreateDarkButton("Export Metrics", OnExportMetrics);
            _metricsExportButton.Dock = DockStyle.Left;
            _metricsExportButton.Width = 120;
            toolbar.Controls.Add(_metricsExportButton);

            var forceGcButton = CreateDarkButton("Force GC", OnForceGC);
            forceGcButton.Dock = DockStyle.Left;
            forceGcButton.Width = 100;
            toolbar.Controls.Add(forceGcButton);

            panel.Controls.Add(toolbar);

            _metricsLabel = new Label
            {
                AutoSize = false,
                Dock = DockStyle.Fill,
                Font = new Font("Consolas", 10F),
                ForeColor = DarkText,
                Text = "Metrics collection in progress...",
                TextAlign = ContentAlignment.TopLeft,
                Padding = new Padding(10)
            };

            panel.Controls.Add(_metricsLabel);

            tab.Controls.Add(panel);

            return tab;
        }

        /// <summary>
        /// Creates the Plugins tab.
        /// </summary>
        private TabPage CreatePluginsTab()
        {
            var tab = new TabPage("Plugins")
            {
                BackColor = DarkBackground
            };

            var panel = new Panel
            {
                Dock = DockStyle.Fill,
                BackColor = DarkBackground
            };

            // Toolbar
            var toolbar = new ToolStrip
            {
                BackColor = DarkPanel,
                ForeColor = DarkText,
                GripStyle = ToolStripGripStyle.Hidden,
                Renderer = new DarkToolStripRenderer()
            };

            var refreshBtn = new ToolStripButton("Refresh", null, (s, e) => RefreshPlugins())
            {
                ForeColor = DarkText
            };
            toolbar.Items.Add(refreshBtn);

            toolbar.Items.Add(new ToolStripSeparator());

            var exportBtn = new ToolStripButton("Export", null, OnExportPlugins)
            {
                ForeColor = DarkText
            };
            toolbar.Items.Add(exportBtn);

            toolbar.Items.Add(new ToolStripSeparator());

            var pathLabel = new ToolStripLabel($"Path: {_pluginsPath}")
            {
                ForeColor = DarkTextDim
            };
            toolbar.Items.Add(pathLabel);

            // Plugins list
            _pluginsListView = new ListView
            {
                Dock = DockStyle.Fill,
                View = View.Details,
                FullRowSelect = true,
                GridLines = true,
                BackColor = DarkPanel,
                ForeColor = DarkText,
                BorderStyle = BorderStyle.None
            };

            _pluginsListView.Columns.Add("Plugin Name", 200);
            _pluginsListView.Columns.Add("Version", 80);
            _pluginsListView.Columns.Add("Type", 100);
            _pluginsListView.Columns.Add("Author", 120);
            _pluginsListView.Columns.Add("File", 150);
            _pluginsListView.Columns.Add("Size", 80);
            _pluginsListView.Columns.Add("Modified", 130);

            // Context menu
            var contextMenu = new ContextMenuStrip
            {
                BackColor = DarkPanel,
                ForeColor = DarkText,
                Renderer = new DarkMenuRenderer()
            };
            var openFolderItem = new ToolStripMenuItem("Open Plugins Folder", null, (s, e) =>
            {
                try
                {
                    Process.Start("explorer.exe", _pluginsPath);
                }
                catch (Exception ex)
                {
                    Logger.Error(ex, "Error opening plugins folder");
                }
            })
            { ForeColor = DarkText };
            contextMenu.Items.Add(openFolderItem);

            var copyInfoItem = new ToolStripMenuItem("Copy Plugin Info", null, OnCopyPluginInfo)
            { ForeColor = DarkText };
            contextMenu.Items.Add(copyInfoItem);

            _pluginsListView.ContextMenuStrip = contextMenu;

            panel.Controls.Add(_pluginsListView);
            panel.Controls.Add(toolbar);

            tab.Controls.Add(panel);

            return tab;
        }

        /// <summary>
        /// Creates the Dumps tab.
        /// </summary>
        private TabPage CreateDumpsTab()
        {
            var tab = new TabPage("Dumps")
            {
                BackColor = DarkBackground
            };

            var panel = new Panel
            {
                Dock = DockStyle.Fill,
                BackColor = DarkBackground
            };

            // Toolbar
            var toolbar = new ToolStrip
            {
                BackColor = DarkPanel,
                ForeColor = DarkText,
                GripStyle = ToolStripGripStyle.Hidden,
                Renderer = new DarkToolStripRenderer()
            };

            var createDumpBtn = new ToolStripButton("Create New Dump", null, OnCreateDump)
            { ForeColor = DarkText };
            toolbar.Items.Add(createDumpBtn);

            var refreshBtn = new ToolStripButton("Refresh List", null, (s, e) => RefreshDumps())
            { ForeColor = DarkText };
            toolbar.Items.Add(refreshBtn);

            toolbar.Items.Add(new ToolStripSeparator());

            var openFolderBtn = new ToolStripButton("Open Dumps Folder", null, (s, e) =>
            {
                try
                {
                    var dumpsPath = Path.Combine(_dataFolder, "dumps");
                    if (!Directory.Exists(dumpsPath))
                    {
                        Directory.CreateDirectory(dumpsPath);
                    }
                    Process.Start("explorer.exe", dumpsPath);
                }
                catch (Exception ex)
                {
                    Logger.Error(ex, "Error opening dumps folder");
                }
            })
            { ForeColor = DarkText };
            toolbar.Items.Add(openFolderBtn);

            // Dumps list
            _dumpsListView = new ListView
            {
                Dock = DockStyle.Fill,
                View = View.Details,
                FullRowSelect = true,
                GridLines = true,
                BackColor = DarkPanel,
                ForeColor = DarkText,
                BorderStyle = BorderStyle.None
            };

            _dumpsListView.Columns.Add("File Name", 280);
            _dumpsListView.Columns.Add("Created", 150);
            _dumpsListView.Columns.Add("Size", 100);

            // Double-click to open
            _dumpsListView.DoubleClick += OnDumpDoubleClick;

            // Context menu
            var contextMenu = new ContextMenuStrip
            {
                BackColor = DarkPanel,
                ForeColor = DarkText,
                Renderer = new DarkMenuRenderer()
            };
            var openItem = new ToolStripMenuItem("Open in Editor", null, OnOpenDump)
            { ForeColor = DarkText };
            contextMenu.Items.Add(openItem);

            var deleteItem = new ToolStripMenuItem("Delete", null, OnDeleteDump)
            { ForeColor = DarkText };
            contextMenu.Items.Add(deleteItem);

            _dumpsListView.ContextMenuStrip = contextMenu;

            panel.Controls.Add(toolbar);
            panel.Controls.Add(_dumpsListView);

            tab.Controls.Add(panel);

            return tab;
        }

        /// <summary>
        /// Creates the Spy tab with UI Inspector (three-pane layout).
        /// </summary>
        private TabPage CreateSpyTab()
        {
            var tab = new TabPage("Spy")
            {
                BackColor = DarkBackground
            };

            // Initialize reflection explorer
            _reflectionExplorer = new ReflectionExplorer();

            // Main split container (left: tree, right: details)
            _spyMainSplit = new SplitContainer
            {
                Dock = DockStyle.Fill,
                Orientation = Orientation.Vertical,
                BackColor = DarkBackground,
                Panel1MinSize = 100,
                Panel2MinSize = 100
            };

            // Left panel: Toolbar + Tree View
            var leftPanel = new Panel { Dock = DockStyle.Fill, BackColor = DarkBackground };

            // Toolbar
            var toolbar = new ToolStrip
            {
                BackColor = DarkPanel,
                ForeColor = DarkText,
                GripStyle = ToolStripGripStyle.Hidden,
                Renderer = new DarkToolStripRenderer()
            };

            var refreshBtn = new ToolStripButton("Refresh", null, OnSpyRefresh) { ForeColor = DarkText };
            toolbar.Items.Add(refreshBtn);

            var expandBtn = new ToolStripButton("Expand All", null, OnSpyExpandAll) { ForeColor = DarkText };
            toolbar.Items.Add(expandBtn);

            var collapseBtn = new ToolStripButton("Collapse", null, OnSpyCollapseAll) { ForeColor = DarkText };
            toolbar.Items.Add(collapseBtn);

            toolbar.Items.Add(new ToolStripSeparator());

            // Spy Overlay button
            _spyOverlayButton = new ToolStripButton("Spy Overlay", null, OnSpyOverlayToggle)
            {
                ForeColor = DarkText,
                ToolTipText = "Start real-time UI element highlighting"
            };
            toolbar.Items.Add(_spyOverlayButton);

            toolbar.Items.Add(new ToolStripSeparator());

            var viewLabel = new ToolStripLabel("View:") { ForeColor = DarkText };
            toolbar.Items.Add(viewLabel);

            var viewCombo = new ToolStripComboBox { ForeColor = DarkText, Width = 120 };
            viewCombo.ComboBox.BackColor = DarkPanel;
            viewCombo.ComboBox.ForeColor = DarkText;
            viewCombo.ComboBox.FlatStyle = FlatStyle.Flat;
            viewCombo.Items.AddRange(new[] { "UI Controls", "Assemblies", "Forms", "Menus" });
            viewCombo.SelectedIndex = 0;
            viewCombo.SelectedIndexChanged += OnSpyViewChanged;
            toolbar.Items.Add(viewCombo);

            leftPanel.Controls.Add(toolbar);

            // Search box
            _spySearchBox = new TextBox
            {
                Dock = DockStyle.Top,
                BackColor = DarkPanel,
                ForeColor = DarkText,
                BorderStyle = BorderStyle.FixedSingle,
                Font = new Font("Segoe UI", 9F)
            };
            _spySearchBox.TextChanged += OnSpySearchChanged;
            _spySearchBox.GotFocus += (s, e) => { if (_spySearchBox.Text == "Search...") _spySearchBox.Text = ""; };
            _spySearchBox.LostFocus += (s, e) => { if (string.IsNullOrEmpty(_spySearchBox.Text)) _spySearchBox.Text = "Search..."; };
            _spySearchBox.Text = "Search...";
            _spySearchBox.ForeColor = DarkTextDim;

            // Tree view
            _spyTreeView = 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
            };
            _spyTreeView.AfterSelect += OnSpyTreeNodeSelected;
            _spyTreeView.NodeMouseDoubleClick += OnSpyTreeNodeDoubleClick;

            leftPanel.Controls.Add(_spyTreeView);
            leftPanel.Controls.Add(_spySearchBox);
            leftPanel.Controls.Add(toolbar);

            _spyMainSplit.Panel1.Controls.Add(leftPanel);

            // Right panel: Metadata + Events (vertical split)
            _spyRightSplit = new SplitContainer
            {
                Dock = DockStyle.Fill,
                Orientation = Orientation.Horizontal,
                BackColor = DarkBackground,
                Panel1MinSize = 100,
                Panel2MinSize = 100,
                SplitterWidth = 8
            };

            // Top-right: Metadata/Properties
            var metadataPanel = new Panel { Dock = DockStyle.Fill, BackColor = DarkBackground };

            var metadataLabel = new Label
            {
                Text = "Properties & Fields",
                Dock = DockStyle.Top,
                Height = 40,
                BackColor = DarkPanel,
                ForeColor = DarkText,
                Font = new Font("Segoe UI", 9F, FontStyle.Bold),
                TextAlign = ContentAlignment.MiddleLeft,
                Padding = new Padding(8, 0, 0, 0)
            };

            _spyMetadataList = new ListView
            {
                Dock = DockStyle.Fill,
                View = View.Details,
                FullRowSelect = true,
                GridLines = true,
                BackColor = DarkPanel,
                ForeColor = DarkText,
                BorderStyle = BorderStyle.None,
                Font = new Font("Consolas", 9F)
            };
            _spyMetadataList.Columns.Add("Name", 90);
            _spyMetadataList.Columns.Add("Type", 85);
            _spyMetadataList.Columns.Add("Value", 140);
            _spyMetadataList.Columns.Add("Access", 70);

            metadataPanel.Controls.Add(_spyMetadataList);
            metadataPanel.Controls.Add(metadataLabel);

            _spyRightSplit.Panel1.Controls.Add(metadataPanel);

            // Bottom-right: Events + Methods
            var eventsPanel = new Panel { Dock = DockStyle.Fill, BackColor = DarkBackground };

            var eventsToolbar = new Panel
            {
                Dock = DockStyle.Top,
                Height = 45,
                BackColor = DarkPanel
            };

            var eventsLabel = new Label
            {
                Text = "Event Handlers & Methods",
                Location = new Point(8, 0),
                Size = new Size(200, 45),
                TextAlign = ContentAlignment.MiddleLeft,
                ForeColor = DarkText,
                Font = new Font("Segoe UI", 9F, FontStyle.Bold)
            };

            var invokeBtn = CreateDarkButton("Invoke", OnSpyInvokeMethod);
            invokeBtn.Location = new Point(210, 8);
            invokeBtn.Size = new Size(90, 30);
            invokeBtn.BackColor = Color.FromArgb(70, 130, 180);

            eventsToolbar.Controls.Add(eventsLabel);
            eventsToolbar.Controls.Add(invokeBtn);

            _spyEventsList = new ListView
            {
                Dock = DockStyle.Fill,
                View = View.Details,
                FullRowSelect = true,
                GridLines = true,
                BackColor = DarkPanel,
                ForeColor = DarkText,
                BorderStyle = BorderStyle.None,
                Font = new Font("Consolas", 9F)
            };
            _spyEventsList.Columns.Add("Event/Method", 100);
            _spyEventsList.Columns.Add("Handler", 115);
            _spyEventsList.Columns.Add("Target Type", 100);
            _spyEventsList.Columns.Add("Visibility", 80);

            eventsPanel.Controls.Add(_spyEventsList);
            eventsPanel.Controls.Add(eventsToolbar);

            _spyRightSplit.Panel2.Controls.Add(eventsPanel);

            _spyMainSplit.Panel2.Controls.Add(_spyRightSplit);

            tab.Controls.Add(_spyMainSplit);

            // Initial population
            PopulateSpyTree("UI Controls");

            return tab;
        }

        /// <summary>
        /// Creates the Invoke tab with Method Invoker functionality.
        /// </summary>
        private TabPage CreateInvokeTab()
        {
            var tab = new TabPage("Invoke")
            {
                BackColor = DarkBackground
            };

            // Main panel with padding
            var mainPanel = new Panel
            {
                Dock = DockStyle.Fill,
                BackColor = DarkBackground,
                Padding = new Padding(10)
            };

            // Instructions panel with button - compact layout
            var instructionsPanel = new Panel
            {
                Dock = DockStyle.Top,
                Height = 90,
                BackColor = DarkPanel
            };

            var titleLabel = new Label
            {
                Text = "Method Invoker",
                Font = new Font("Segoe UI", 10F, FontStyle.Bold),
                ForeColor = DarkText,
                Location = new Point(10, 12),
                AutoSize = true
            };
            instructionsPanel.Controls.Add(titleLabel);

            var openInvokerButton = new Button
            {
                Text = "Open",
                Location = new Point(250, 8),
                Size = new Size(80, 28),
                BackColor = DarkAccent,
                ForeColor = Color.White,
                FlatStyle = FlatStyle.Flat,
                Font = new Font("Segoe UI", 8F, FontStyle.Bold)
            };
            openInvokerButton.FlatAppearance.BorderSize = 0;
            openInvokerButton.Click += OnOpenMethodInvoker;
            instructionsPanel.Controls.Add(openInvokerButton);

            // Assembly list - direct without GroupBox
            var assemblyListView = new ListView
            {
                Dock = DockStyle.Fill,
                View = View.Details,
                FullRowSelect = true,
                GridLines = true,
                BackColor = DarkPanel,
                ForeColor = DarkText,
                BorderStyle = BorderStyle.None,
                Font = new Font("Consolas", 9F)
            };
            assemblyListView.Columns.Add("Assembly", 250);
            assemblyListView.Columns.Add("Version", 100);
            assemblyListView.Columns.Add("Types", 80);
            assemblyListView.Columns.Add("Category", 100);

            // Populate with quick assembly info
            try
            {
                var reflectionExplorer = new ReflectionExplorer();
                var categories = new[] { "musicbee", "plugins" };

                foreach (var category in categories)
                {
                    var assemblies = reflectionExplorer.GetAssembliesByCategory(category);
                    foreach (var asm in assemblies.Take(20))
                    {
                        var item = new ListViewItem(new[]
                        {
                            asm.Name,
                            asm.Version ?? "?",
                            asm.TypeCount.ToString(),
                            category.ToUpper()
                        });
                        item.ForeColor = category == "musicbee" ? Color.FromArgb(100, 200, 255) : DarkText;
                        item.BackColor = DarkPanel;
                        assemblyListView.Items.Add(item);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex, "Error populating quick assembly list");
            }

            // Dock order: Fill first, Top last (so Top takes space first)
            mainPanel.Controls.Add(assemblyListView);
            mainPanel.Controls.Add(instructionsPanel);

            tab.Controls.Add(mainPanel);

            return tab;
        }

        /// <summary>
        /// Opens the Method Invoker form.
        /// </summary>
        private void OnOpenMethodInvoker(object sender, EventArgs e)
        {
            try
            {
                var invokerForm = new MethodInvokerForm(_eventLogger);
                invokerForm.Show();
                Logger.Info("Method Invoker form opened");
            }
            catch (Exception ex)
            {
                Logger.Error(ex, "Error opening Method Invoker form");
                MessageBox.Show($"Error opening Method Invoker:\n{ex.Message}", "Error",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// Creates the Handlers tab with Event and Menu inspection.
        /// </summary>
        private TabPage CreateHandlersTab()
        {
            var tab = new TabPage("Handlers")
            {
                BackColor = DarkBackground
            };

            // Main panel with padding
            var mainPanel = new Panel
            {
                Dock = DockStyle.Fill,
                BackColor = DarkBackground,
                Padding = new Padding(10)
            };

            // Instructions panel with buttons
            var instructionsPanel = new Panel
            {
                Dock = DockStyle.Top,
                Height = 130,
                BackColor = DarkPanel
            };

            var titleLabel = new Label
            {
                Text = "Event Handlers & Menus",
                Font = new Font("Segoe UI", 11F, FontStyle.Bold),
                ForeColor = DarkText,
                Location = new Point(15, 20),
                AutoSize = true
            };
            instructionsPanel.Controls.Add(titleLabel);

            var descLabel = new Label
            {
                Text = "Inspect event handlers attached to controls and explore the MusicBee menu system.",
                Font = new Font("Segoe UI", 8F),
                ForeColor = DarkTextDim,
                Location = new Point(15, 50),
                AutoSize = true,
                MaximumSize = new Size(800, 0)
            };
            instructionsPanel.Controls.Add(descLabel);

            var openEventInspectorButton = new Button
            {
                Text = "Event",
                Location = new Point(15, 85),
                Size = new Size(80, 32),
                BackColor = Color.FromArgb(70, 130, 180),
                ForeColor = Color.White,
                FlatStyle = FlatStyle.Flat,
                Font = new Font("Segoe UI", 8F, FontStyle.Bold)
            };
            openEventInspectorButton.FlatAppearance.BorderSize = 0;
            openEventInspectorButton.Click += OnOpenEventInspector;
            instructionsPanel.Controls.Add(openEventInspectorButton);

            var openMenuInspectorButton = new Button
            {
                Text = "Menu",
                Location = new Point(105, 85),
                Size = new Size(80, 32),
                BackColor = Color.FromArgb(130, 100, 180),
                ForeColor = Color.White,
                FlatStyle = FlatStyle.Flat,
                Font = new Font("Segoe UI", 8F, FontStyle.Bold),
                Margin = new Padding(5)
            };
            openMenuInspectorButton.FlatAppearance.BorderSize = 0;
            openMenuInspectorButton.Click += OnOpenMenuInspector;
            instructionsPanel.Controls.Add(openMenuInspectorButton);

            mainPanel.Controls.Add(instructionsPanel);

            // Quick stats panel
            var statsPanel = new GroupBox
            {
                Text = "Handler Statistics",
                Dock = DockStyle.Fill,
                ForeColor = DarkText,
                BackColor = DarkPanel,
                Font = new Font("Segoe UI", 9F, FontStyle.Bold),
                Padding = new Padding(10),
                Margin = new Padding(0, 10, 0, 0)
            };

            var statsLabel = new Label
            {
                Dock = DockStyle.Fill,
                Font = new Font("Consolas", 10F),
                ForeColor = DarkText,
                Text = "Loading statistics...",
                Padding = new Padding(10)
            };
            statsLabel.Tag = "handlersStatsLabel";
            statsPanel.Controls.Add(statsLabel);

            // Populate initial stats
            try
            {
                var eventInspector = new EventInspector();
                var menuWalker = new MenuWalker();
                var mainForm = _reflectionExplorer.FindMainForm();

                if (mainForm != null)
                {
                    var eventStats = eventInspector.GetEventStatistics(mainForm);
                    var menuStats = menuWalker.GetMenuStatistics(mainForm);

                    var sb = new StringBuilder();
                    sb.AppendLine("=== Event Handler Statistics ===");
                    sb.AppendLine($"Controls with handlers: {eventStats.TotalControlsWithHandlers}");
                    sb.AppendLine($"Total event handlers: {eventStats.TotalHandlers}");
                    sb.AppendLine();

                    if (eventStats.HandlersByEvent.Count > 0)
                    {
                        sb.AppendLine("Top Events:");
                        foreach (var kvp in eventStats.HandlersByEvent.OrderByDescending(x => x.Value).Take(5))
                        {
                            sb.AppendLine($"  {kvp.Key}: {kvp.Value}");
                        }
                    }

                    sb.AppendLine();
                    sb.AppendLine("=== Menu Statistics ===");
                    sb.AppendLine($"Total menu items: {menuStats.TotalMenuItems}");
                    sb.AppendLine($"Items with handlers: {menuStats.MenuItemsWithHandlers}");
                    sb.AppendLine($"Items with shortcuts: {menuStats.MenuItemsWithShortcuts}");
                    sb.AppendLine($"Context menus: {menuStats.ContextMenuCount}");
                    sb.AppendLine($"Context menu items: {menuStats.TotalContextMenuItems}");

                    statsLabel.Text = sb.ToString();
                }
                else
                {
                    statsLabel.Text = "Could not find MusicBee main form.\nOpen Event Inspector or Menu Inspector to refresh.";
                }
            }
            catch (Exception ex)
            {
                statsLabel.Text = $"Error loading statistics: {ex.Message}";
                Logger.Error(ex, "Error loading handler statistics");
            }

            mainPanel.Controls.Add(statsPanel);

            tab.Controls.Add(mainPanel);

            return tab;
        }

        /// <summary>
        /// Opens the Event Inspector form.
        /// </summary>
        private void OnOpenEventInspector(object sender, EventArgs e)
        {
            try
            {
                var eventInspectorForm = new EventInspectorForm();
                eventInspectorForm.Show();
                Logger.Info("Event Inspector form opened");
            }
            catch (Exception ex)
            {
                Logger.Error(ex, "Error opening Event Inspector form");
                MessageBox.Show($"Error opening Event Inspector:\n{ex.Message}", "Error",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// Opens the Menu Inspector form.
        /// </summary>
        private void OnOpenMenuInspector(object sender, EventArgs e)
        {
            try
            {
                var menuInspectorForm = new MenuInspectorForm();
                menuInspectorForm.Show();
                Logger.Info("Menu Inspector form opened");
            }
            catch (Exception ex)
            {
                Logger.Error(ex, "Error opening Menu Inspector form");
                MessageBox.Show($"Error opening Menu Inspector:\n{ex.Message}", "Error",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// Populates the spy tree based on view mode.
        /// </summary>
        private void PopulateSpyTree(string viewMode)
        {
            _spyTreeView.Nodes.Clear();

            try
            {
                switch (viewMode)
                {
                    case "UI Controls":
                        PopulateUIControlsTree();
                        break;
                    case "Assemblies":
                        PopulateAssembliesTree();
                        break;
                    case "Forms":
                        PopulateFormsTree();
                        break;
                    case "Menus":
                        PopulateMenusTree();
                        break;
                }
            }
            catch (Exception ex)
            {
                var errorNode = _spyTreeView.Nodes.Add($"Error: {ex.Message}");
                errorNode.ForeColor = Color.Red;
            }
        }

        private void PopulateUIControlsTree()
        {
            var mainForm = _reflectionExplorer.FindMainForm();
            if (mainForm == null)
            {
                _spyTreeView.Nodes.Add("Could not find main form");
                return;
            }

            var rootNode = _spyTreeView.Nodes.Add($"MainForm ({mainForm.GetType().Name})");
            rootNode.Tag = mainForm;
            rootNode.ForeColor = Color.FromArgb(100, 200, 255);

            PopulateControlNode(rootNode, mainForm);

            rootNode.Expand();
        }

        private void PopulateControlNode(TreeNode parentNode, Control control)
        {
            foreach (Control child in control.Controls)
            {
                var name = string.IsNullOrEmpty(child.Name) ? $"[{child.GetType().Name}]" : child.Name;
                var nodeText = $"{name} ({child.GetType().Name})";
                if (!child.Visible) nodeText += " [HIDDEN]";

                var node = parentNode.Nodes.Add(nodeText);
                node.Tag = child;

                // Color code by type
                if (child is MenuStrip) node.ForeColor = Color.FromArgb(255, 200, 100);
                else if (child is ToolStrip) node.ForeColor = Color.FromArgb(200, 150, 255);
                else if (child is Panel || child is SplitContainer) node.ForeColor = Color.FromArgb(150, 200, 150);
                else if (!child.Visible) node.ForeColor = DarkTextDim;
                else node.ForeColor = DarkText;

                // Recurse
                if (child.Controls.Count > 0)
                {
                    PopulateControlNode(node, child);
                }
            }
        }

        private void PopulateAssembliesTree()
        {
            var categories = new[] { "musicbee", "plugins", "ui", "system" };

            foreach (var category in categories)
            {
                var categoryNode = _spyTreeView.Nodes.Add(category.ToUpper());
                categoryNode.ForeColor = Color.FromArgb(100, 200, 255);

                var assemblies = _reflectionExplorer.GetAssembliesByCategory(category);
                foreach (var asm in assemblies.Take(50)) // Limit for performance
                {
                    var asmNode = categoryNode.Nodes.Add($"{asm.Name} v{asm.Version}");
                    asmNode.Tag = asm.Assembly;
                    asmNode.ForeColor = DarkText;

                    // Add placeholder for types
                    asmNode.Nodes.Add("Loading...");
                }
            }
        }

        private void PopulateFormsTree()
        {
            var forms = _reflectionExplorer.GetOpenForms();

            foreach (var form in forms)
            {
                var node = _spyTreeView.Nodes.Add($"{form.Text} ({form.Type})");
                node.Tag = form.Form;
                node.ForeColor = Color.FromArgb(100, 200, 255);

                // Add child count
                node.Nodes.Add($"{form.ControlCount} controls...");
            }
        }

        private void PopulateMenusTree()
        {
            var mainForm = _reflectionExplorer.FindMainForm();
            if (mainForm == null)
            {
                _spyTreeView.Nodes.Add("Could not find main form");
                return;
            }

            // Find all MenuStrips
            foreach (Control control in mainForm.Controls)
            {
                if (control is MenuStrip menuStrip)
                {
                    var menuNode = _spyTreeView.Nodes.Add($"Menu: {menuStrip.Name}");
                    menuNode.Tag = menuStrip;
                    menuNode.ForeColor = Color.FromArgb(255, 200, 100);

                    foreach (var item in _reflectionExplorer.GetMenuItems(menuStrip))
                    {
                        var itemNode = menuNode.Nodes.Add(item.Path);
                        itemNode.Tag = item;

                        if (item.ClickHandler != null)
                        {
                            itemNode.ForeColor = Color.FromArgb(100, 255, 100);
                            itemNode.Text += $" -> {item.ClickHandler.Name}()";
                        }
                        else
                        {
                            itemNode.ForeColor = DarkTextDim;
                        }
                    }

                    menuNode.Expand();
                }
            }
        }

        #region Spy Tab Event Handlers

        private void OnSpyOverlayToggle(object sender, EventArgs e)
        {
            try
            {
                if (_spyToolbar == null || _spyToolbar.IsDisposed)
                {
                    // Find MusicBee's main window to restrict spying
                    var mainForm = _reflectionExplorer?.FindMainForm();
                    IntPtr targetHandle = mainForm?.Handle ?? IntPtr.Zero;

                    _spyToolbar = new SpyToolbar(targetHandle);
                    _spyToolbar.ToolbarClosed += OnSpyToolbarClosed;
                    _spyToolbar.Show();

                    // Update button text
                    _spyOverlayButton.Text = "Stop Overlay";
                    _spyOverlayButton.ForeColor = Color.FromArgb(0, 174, 255);

                    // Auto-start spy mode
                    _spyToolbar.OverlayForm.StartSpyMode();

                    Logger.Info("Spy overlay started");
                }
                else
                {
                    // Stop and close
                    _spyToolbar.OverlayForm.StopSpyMode();
                    _spyToolbar.Close();
                    _spyToolbar = null;

                    _spyOverlayButton.Text = "Spy Overlay";
                    _spyOverlayButton.ForeColor = DarkText;

                    Logger.Info("Spy overlay stopped");
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex, "Error toggling spy overlay");
                MessageBox.Show($"Error toggling spy overlay:\n{ex.Message}", "Error",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void OnSpyToolbarClosed(object sender, EventArgs e)
        {
            _spyToolbar = null;
            _spyOverlayButton.Text = "Spy Overlay";
            _spyOverlayButton.ForeColor = DarkText;
        }

        private void OnSpyRefresh(object sender, EventArgs e)
        {
            var viewCombo = ((ToolStrip)((ToolStripButton)sender).Owner).Items
                .OfType<ToolStripComboBox>().FirstOrDefault();
            var viewMode = viewCombo?.SelectedItem?.ToString() ?? "UI Controls";
            PopulateSpyTree(viewMode);
        }

        private void OnSpyExpandAll(object sender, EventArgs e)
        {
            _spyTreeView.ExpandAll();
        }

        private void OnSpyCollapseAll(object sender, EventArgs e)
        {
            _spyTreeView.CollapseAll();
        }

        private void OnSpyViewChanged(object sender, EventArgs e)
        {
            var combo = sender as ToolStripComboBox;
            if (combo?.SelectedItem != null)
            {
                PopulateSpyTree(combo.SelectedItem.ToString());
            }
        }

        private void OnSpySearchChanged(object sender, EventArgs e)
        {
            var searchText = _spySearchBox.Text?.ToLower();
            if (string.IsNullOrEmpty(searchText) || searchText == "search...") return;

            // Find and select matching node
            foreach (TreeNode node in GetAllNodes(_spyTreeView.Nodes))
            {
                if (node.Text.ToLower().Contains(searchText))
                {
                    _spyTreeView.SelectedNode = node;
                    node.EnsureVisible();
                    break;
                }
            }
        }

        private IEnumerable<TreeNode> GetAllNodes(TreeNodeCollection nodes)
        {
            foreach (TreeNode node in nodes)
            {
                yield return node;
                foreach (var child in GetAllNodes(node.Nodes))
                {
                    yield return child;
                }
            }
        }

        private void OnSpyTreeNodeSelected(object sender, TreeViewEventArgs e)
        {
            _spyMetadataList.Items.Clear();
            _spyEventsList.Items.Clear();

            var tag = e.Node?.Tag;
            if (tag == null) return;

            if (tag is Control control)
            {
                // Show control properties and fields
                PopulateControlMetadata(control);
                PopulateControlEvents(control);
            }
            else if (tag is System.Reflection.Assembly assembly)
            {
                // Show assembly types
                PopulateAssemblyTypes(assembly, e.Node);
            }
            else if (tag is MenuItemInfo menuItem)
            {
                // Show menu item handler info
                PopulateMenuItemInfo(menuItem);
            }
        }

        private void OnSpyTreeNodeDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            // Expand assembly nodes on double-click
            var tag = e.Node?.Tag;
            if (tag is System.Reflection.Assembly assembly)
            {
                e.Node.Nodes.Clear();
                PopulateAssemblyTypes(assembly, e.Node);
                e.Node.Expand();
            }
        }

        private void PopulateControlMetadata(Control control)
        {
            // Basic properties
            AddMetadataItem("Name", "string", control.Name, "public");
            AddMetadataItem("Type", "Type", control.GetType().FullName, "public");
            AddMetadataItem("Visible", "bool", control.Visible.ToString(), "public");
            AddMetadataItem("Enabled", "bool", control.Enabled.ToString(), "public");
            AddMetadataItem("Bounds", "Rectangle", control.Bounds.ToString(), "public");
            AddMetadataItem("Dock", "DockStyle", control.Dock.ToString(), "public");
            AddMetadataItem("Anchor", "AnchorStyles", control.Anchor.ToString(), "public");

            // Private fields
            foreach (var field in _reflectionExplorer.GetPrivateFields(control).Take(30))
            {
                var access = field.IsPrivate ? "private" : (field.IsStatic ? "static" : "internal");
                var item = AddMetadataItem(field.Name, field.FieldType?.Name ?? "?", field.ValueString, access);
                if (field.IsPrivate) item.ForeColor = DarkTextDim;
            }
        }

        private void PopulateControlEvents(Control control)
        {
            // Get event handlers
            foreach (var handler in _reflectionExplorer.GetEventHandlers(control))
            {
                var visibility = handler.HandlerMethod?.IsPrivate == true ? "private" : "public";
                var item = new ListViewItem(new[]
                {
                    handler.EventName,
                    handler.HandlerMethod?.Name ?? "?",
                    handler.TargetType?.Name ?? "?",
                    visibility
                });
                item.Tag = handler;
                item.ForeColor = handler.HandlerMethod?.IsPrivate == true ? Color.FromArgb(255, 200, 100) : DarkText;
                item.BackColor = DarkPanel;
                _spyEventsList.Items.Add(item);
            }

            // Get methods (non-event)
            var controlType = control.GetType();
            var methods = controlType.GetMethods(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
                .Where(m => !m.IsSpecialName && m.GetParameters().Length == 0)
                .Take(20);

            foreach (var method in methods)
            {
                var item = new ListViewItem(new[]
                {
                    "[Method]",
                    method.Name + "()",
                    method.DeclaringType?.Name ?? "?",
                    method.IsPrivate ? "private" : "internal"
                });
                item.Tag = new MethodInvokeInfo { Target = control, Method = method };
                item.ForeColor = Color.FromArgb(150, 150, 255);
                item.BackColor = DarkPanel;
                _spyEventsList.Items.Add(item);
            }
        }

        private void PopulateAssemblyTypes(System.Reflection.Assembly assembly, TreeNode parentNode)
        {
            try
            {
                var types = _reflectionExplorer.GetTypes(assembly).Take(100);

                foreach (var typeInfo in types)
                {
                    var typeNode = parentNode.Nodes.Add(typeInfo.FullName);
                    typeNode.Tag = typeInfo.Type;
                    typeNode.ForeColor = typeInfo.IsPublic ? DarkText : DarkTextDim;
                }

                // Show in metadata list too
                _spyMetadataList.Items.Clear();
                AddMetadataItem("Assembly", "string", assembly.GetName().Name, "public");
                AddMetadataItem("Version", "string", assembly.GetName().Version?.ToString() ?? "?", "public");
                AddMetadataItem("Type Count", "int", types.Count().ToString(), "public");
            }
            catch (Exception ex)
            {
                AddMetadataItem("Error", "string", ex.Message, "error");
            }
        }

        private void PopulateMenuItemInfo(MenuItemInfo menuItem)
        {
            AddMetadataItem("Path", "string", menuItem.Path, "public");
            AddMetadataItem("Text", "string", menuItem.Text, "public");
            AddMetadataItem("Name", "string", menuItem.Name, "public");
            AddMetadataItem("Enabled", "bool", menuItem.Enabled.ToString(), "public");
            AddMetadataItem("Shortcut", "string", menuItem.ShortcutKeys ?? "None", "public");

            if (menuItem.ClickHandler != null)
            {
                AddMetadataItem("Handler", "MethodInfo", menuItem.ClickHandler.Name, "private");
                AddMetadataItem("Target", "Type", menuItem.HandlerTarget?.FullName ?? "?", "private");

                // Add to events list for invocation
                var item = new ListViewItem(new[]
                {
                    "Click",
                    menuItem.ClickHandler.Name + "()",
                    menuItem.HandlerTarget?.Name ?? "?",
                    menuItem.ClickHandler.IsPrivate ? "private" : "public"
                });
                item.Tag = menuItem;
                item.ForeColor = Color.FromArgb(100, 255, 100);
                item.BackColor = DarkPanel;
                _spyEventsList.Items.Add(item);
            }
        }

        private ListViewItem AddMetadataItem(string name, string type, string value, string access)
        {
            var item = new ListViewItem(new[] { name, type, value, access });
            item.ForeColor = DarkText;
            item.BackColor = DarkPanel;
            _spyMetadataList.Items.Add(item);
            return item;
        }

        private void OnSpyInvokeMethod(object sender, EventArgs e)
        {
            if (_spyEventsList.SelectedItems.Count == 0)
            {
                MessageBox.Show("Select a method or event handler to invoke.", "No Selection",
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            var tag = _spyEventsList.SelectedItems[0].Tag;

            try
            {
                if (tag is EventHandlerInfo handlerInfo && handlerInfo.Target != null && handlerInfo.HandlerMethod != null)
                {
                    var result = MessageBox.Show(
                        $"Invoke method: {handlerInfo.HandlerMethod.Name}?\n\n" +
                        $"Target: {handlerInfo.TargetType?.Name}\n" +
                        $"This may trigger UI actions.",
                        "Confirm Invoke",
                        MessageBoxButtons.YesNo,
                        MessageBoxIcon.Question);

                    if (result == DialogResult.Yes)
                    {
                        // Check parameter count
                        var parameters = handlerInfo.HandlerMethod.GetParameters();
                        object[] args = parameters.Length == 2
                            ? new object[] { null, EventArgs.Empty }
                            : null;

                        handlerInfo.HandlerMethod.Invoke(handlerInfo.Target, args);
                        Logger.Info($"Invoked: {handlerInfo.HandlerMethod.Name}");
                    }
                }
                else if (tag is MethodInvokeInfo methodInfo)
                {
                    var result = MessageBox.Show(
                        $"Invoke method: {methodInfo.Method.Name}()?\n\n" +
                        $"Target: {methodInfo.Target?.GetType().Name}\n" +
                        $"This may trigger UI actions.",
                        "Confirm Invoke",
                        MessageBoxButtons.YesNo,
                        MessageBoxIcon.Question);

                    if (result == DialogResult.Yes)
                    {
                        methodInfo.Method.Invoke(methodInfo.Target, null);
                        Logger.Info($"Invoked: {methodInfo.Method.Name}");
                    }
                }
                else if (tag is MenuItemInfo menuItem && menuItem.ClickHandler != null)
                {
                    var result = MessageBox.Show(
                        $"Invoke menu handler: {menuItem.ClickHandler.Name}?\n\n" +
                        $"Menu: {menuItem.Path}\n" +
                        $"This may trigger UI actions.",
                        "Confirm Invoke",
                        MessageBoxButtons.YesNo,
                        MessageBoxIcon.Question);

                    if (result == DialogResult.Yes)
                    {
                        // Menu click handlers typically take (object sender, EventArgs e)
                        var parameters = menuItem.ClickHandler.GetParameters();
                        object[] args = parameters.Length == 2
                            ? new object[] { null, EventArgs.Empty }
                            : null;

                        // Need to find the target instance - this is tricky
                        // For now, try to get it from reflection
                        var mainForm = _reflectionExplorer.FindMainForm();
                        if (mainForm != null && menuItem.HandlerTarget == mainForm.GetType())
                        {
                            menuItem.ClickHandler.Invoke(mainForm, args);
                            Logger.Info($"Invoked menu: {menuItem.Path}");
                        }
                        else
                        {
                            MessageBox.Show("Could not determine target instance for this handler.",
                                "Invoke Failed", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex, "Error invoking method");
                MessageBox.Show($"Error invoking method:\n{ex.Message}", "Invoke Error",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// Helper class for storing method invocation info.
        /// </summary>
        private class MethodInvokeInfo
        {
            public object Target { get; set; }
            public System.Reflection.MethodInfo Method { get; set; }
        }

        #endregion

        /// <summary>
        /// Initializes the status bar with dark theme.
        /// </summary>
        private void InitializeStatusBar()
        {
            _statusStrip = new StatusStrip
            {
                BackColor = DarkPanel,
                ForeColor = DarkText,
                SizingGrip = true
            };

            _sessionDurationLabel = new ToolStripStatusLabel
            {
                Text = "Session: 00:00:00",
                ForeColor = DarkText
            };

            _eventCountLabel = new ToolStripStatusLabel
            {
                Text = "Events: 0",
                ForeColor = DarkText
            };

            var springLabel = new ToolStripStatusLabel
            {
                Spring = true,
                Text = ""
            };

            var versionLabel = new ToolStripStatusLabel
            {
                Text = $"mbClouseau v{typeof(DashboardForm).Assembly.GetName().Version}",
                ForeColor = DarkTextDim
            };

            _statusStrip.Items.Add(_sessionDurationLabel);
            _statusStrip.Items.Add(new ToolStripSeparator());
            _statusStrip.Items.Add(_eventCountLabel);
            _statusStrip.Items.Add(springLabel);
            _statusStrip.Items.Add(versionLabel);
        }

        /// <summary>
        /// Updates the status bar periodically.
        /// </summary>
        private void OnStatusTimerTick(object sender, EventArgs e)
        {
            var duration = DateTime.Now - _sessionStartTime;
            _sessionDurationLabel.Text = $"Session: {duration:hh\\:mm\\:ss}";
            _eventCountLabel.Text = $"Events: {_logViewer?.EntryCount ?? 0}";

            // Update displays
            UpdateOverviewDisplay();
            UpdateMetricsDisplay();
        }

        /// <summary>
        /// Updates the overview display with current session information.
        /// </summary>
        private void UpdateOverviewDisplay()
        {
            if (_sessionInfoLabel == null) return;

            try
            {
                var duration = DateTime.Now - _sessionStartTime;
                var mbUptime = _stateManager?.GetMusicBeeUptime();

                var sessionText = new StringBuilder();
                sessionText.AppendLine($"Session Start:    {_sessionStartTime:yyyy-MM-dd HH:mm:ss}");
                if (mbUptime.HasValue)
                {
                    sessionText.AppendLine($"MusicBee Uptime:  {mbUptime.Value:hh\\:mm\\:ss}");
                }
                if (_stateManager != null)
                {
                    sessionText.AppendLine($"Process ID:       {_stateManager.MusicBeeProcessId}");
                    var persistedState = _stateManager.GetPersistedState();
                    sessionText.AppendLine($"Total Sessions:   {persistedState.TotalSessions}");
                }

                _sessionInfoLabel.Text = sessionText.ToString();

                // Event statistics
                var eventText = new StringBuilder();
                eventText.AppendLine($"Events/min:       {_stateManager?.GetEventsPerMinute():F1}");
                eventText.AppendLine();

                if (_stateManager?.EventCounts != null)
                {
                    eventText.AppendLine("Events by Type:");
                    foreach (var kvp in _stateManager.EventCounts.OrderByDescending(x => x.Value).Take(8))
                    {
                        eventText.AppendLine($"  {kvp.Key,-28} {kvp.Value,5}");
                    }
                }

                _eventStatsLabel.Text = eventText.ToString();

                // MusicBee information
                var mbText = new StringBuilder();
                mbText.AppendLine($"API Revision:     {_mbApi.ApiRevision}");
                mbText.AppendLine($"Version:          {_mbApi.MusicBeeVersion}");
                mbText.AppendLine($"Play State:       {_mbApi.Player_GetPlayState()}");
                mbText.AppendLine($"Volume:           {_mbApi.Player_GetVolume():P0}");
                mbText.AppendLine($"Shuffle:          {(_mbApi.Player_GetShuffle() ? "On" : "Off")}");
                mbText.AppendLine($"Repeat:           {_mbApi.Player_GetRepeat()}");
                mbText.AppendLine();

                var currentTrack = _mbApi.NowPlaying_GetFileTag(Plugin.MetaDataType.TrackTitle);
                var currentArtist = _mbApi.NowPlaying_GetFileTag(Plugin.MetaDataType.Artist);
                if (!string.IsNullOrEmpty(currentTrack))
                {
                    mbText.AppendLine($"Now Playing:");
                    mbText.AppendLine($"  {currentArtist}");
                    mbText.AppendLine($"  {currentTrack}");
                }

                _musicBeeInfoLabel.Text = mbText.ToString();
            }
            catch (Exception ex)
            {
                Logger.Trace($"Error updating overview display: {ex.Message}");
            }
        }

        /// <summary>
        /// Updates the metrics display with current values.
        /// </summary>
        private void UpdateMetricsDisplay()
        {
            if (_metricsLabel == null) return;

            try
            {
                var sb = new StringBuilder();
                sb.AppendLine("=== System Metrics ===");
                sb.AppendLine();

                // Use MetricsCollector if available, otherwise fall back to direct process metrics
                if (_metricsCollector != null)
                {
                    var snapshot = _metricsCollector.GetCurrentSnapshot();
                    if (snapshot != null)
                    {
                        sb.AppendLine($"Collection Count:     {_metricsCollector.CollectionCount}");
                        sb.AppendLine($"Collector Uptime:     {_metricsCollector.Uptime:hh\\:mm\\:ss}");
                        sb.AppendLine();

                        sb.AppendLine("--- Process ---");
                        sb.AppendLine($"Working Set:          {snapshot.MBWorkingSetMB:N0} MB");
                        sb.AppendLine($"Private Bytes:        {snapshot.MBPrivateBytesMB:N0} MB");
                        sb.AppendLine($"Managed Heap:         {snapshot.ManagedHeapMB:N1} MB");
                        sb.AppendLine($"Thread Count:         {snapshot.MBThreadCount}");
                        sb.AppendLine($"Handle Count:         {snapshot.MBHandleCount}");
                        sb.AppendLine();

                        sb.AppendLine("--- CLR / GC ---");
                        sb.AppendLine($"Gen 0 Collections:    {snapshot.GCGen0Collections}");
                        sb.AppendLine($"Gen 1 Collections:    {snapshot.GCGen1Collections}");
                        sb.AppendLine($"Gen 2 Collections:    {snapshot.GCGen2Collections}");
                        sb.AppendLine($"GC Time %:            {snapshot.GCTimePercent:F1}%");
                        sb.AppendLine();

                        sb.AppendLine("--- System ---");
                        sb.AppendLine($"CPU Usage:            {snapshot.CpuPercent:F1}%");
                        sb.AppendLine($"Memory Used:          {snapshot.MemoryPercent:F1}%");
                        sb.AppendLine($"Available Memory:     {snapshot.AvailableMemoryMB:N0} MB");
                        sb.AppendLine();

                        // Alerts
                        if (snapshot.HandleLeakSuspected || snapshot.MemoryLeakSuspected || snapshot.GCPressureHigh || snapshot.LowMemoryWarning)
                        {
                            sb.AppendLine("--- ALERTS ---");
                            if (snapshot.HandleLeakSuspected)
                                sb.AppendLine("[!] Handle leak suspected");
                            if (snapshot.MemoryLeakSuspected)
                                sb.AppendLine("[!] Memory leak suspected");
                            if (snapshot.GCPressureHigh)
                                sb.AppendLine("[!] High GC pressure");
                            if (snapshot.LowMemoryWarning)
                                sb.AppendLine("[!] Low system memory");
                        }
                    }
                    else
                    {
                        sb.AppendLine("Waiting for first metrics collection...");
                    }
                }
                else
                {
                    // Fallback to basic process metrics
                    var process = Process.GetCurrentProcess();
                    var workingSet = process.WorkingSet64 / (1024 * 1024);
                    var privateBytes = process.PrivateMemorySize64 / (1024 * 1024);
                    var threads = process.Threads.Count;
                    var handles = process.HandleCount;
                    var gcTotal = GC.GetTotalMemory(false) / (1024 * 1024);

                    var duration = DateTime.Now - _sessionStartTime;

                    sb.AppendLine($"Session Duration:     {duration:hh\\:mm\\:ss}");
                    sb.AppendLine($"Events Logged:        {_logViewer?.EntryCount ?? 0}");
                    sb.AppendLine();
                    sb.AppendLine("--- Process Metrics ---");
                    sb.AppendLine($"Working Set:          {workingSet:N0} MB");
                    sb.AppendLine($"Private Bytes:        {privateBytes:N0} MB");
                    sb.AppendLine($"Managed Heap:         {gcTotal:N0} MB");
                    sb.AppendLine($"Thread Count:         {threads}");
                    sb.AppendLine($"Handle Count:         {handles}");
                    sb.AppendLine();
                    sb.AppendLine("--- GC Statistics ---");
                    sb.AppendLine($"Gen 0 Collections:    {GC.CollectionCount(0)}");
                    sb.AppendLine($"Gen 1 Collections:    {GC.CollectionCount(1)}");
                    sb.AppendLine($"Gen 2 Collections:    {GC.CollectionCount(2)}");
                    sb.AppendLine();
                    sb.AppendLine("--- MusicBee ---");
                    sb.AppendLine($"API Revision:         {_mbApi.ApiRevision}");
                    sb.AppendLine($"MusicBee Version:     {_mbApi.MusicBeeVersion}");
                    sb.AppendLine($"Play State:           {_mbApi.Player_GetPlayState()}");
                    sb.AppendLine($"Volume:               {_mbApi.Player_GetVolume():P0}");
                }

                _metricsLabel.Text = sb.ToString();
            }
            catch (Exception ex)
            {
                Logger.Trace($"Error updating metrics display: {ex.Message}");
            }
        }

        /// <summary>
        /// Refreshes the plugins list.
        /// </summary>
        private void RefreshPlugins()
        {
            try
            {
                _pluginsListView.Items.Clear();

                var plugins = _pluginDiscovery.DiscoverPlugins();

                foreach (var plugin in plugins.OrderBy(p => p.PluginName ?? p.FileName))
                {
                    var item = new ListViewItem(new[]
                    {
                        plugin.PluginName ?? plugin.FileName,
                        plugin.IsValidPlugin ? $"{plugin.VersionMajor}.{plugin.VersionMinor}.{plugin.Revision}" : "N/A",
                        plugin.PluginType ?? (plugin.IsValidPlugin ? "Unknown" : "Not a Plugin"),
                        plugin.PluginAuthor ?? "",
                        plugin.FileName,
                        FormatFileSize(plugin.FileSizeBytes),
                        plugin.LastModified.ToString("yyyy-MM-dd HH:mm")
                    });

                    if (!plugin.IsValidPlugin)
                    {
                        item.ForeColor = DarkTextDim;
                    }
                    else
                    {
                        item.ForeColor = DarkText;
                    }

                    item.BackColor = DarkPanel;
                    item.Tag = plugin;
                    _pluginsListView.Items.Add(item);
                }

                // Auto-resize columns to fit content
                foreach (ColumnHeader column in _pluginsListView.Columns)
                {
                    column.Width = -2; // Auto-size to header and content
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex, "Error refreshing plugins");
                MessageBox.Show($"Error refreshing plugins:\n{ex.Message}", "Error",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// Refreshes the dumps list.
        /// </summary>
        private void RefreshDumps()
        {
            try
            {
                _dumpsListView.Items.Clear();

                var dumps = _stateDumper.GetExistingDumps();

                foreach (var dump in dumps)
                {
                    var item = new ListViewItem(new[]
                    {
                        dump.FileName,
                        dump.CreatedTime.ToString("yyyy-MM-dd HH:mm:ss"),
                        FormatFileSize(dump.FileSizeBytes)
                    });

                    item.ForeColor = DarkText;
                    item.BackColor = DarkPanel;
                    item.Tag = dump;
                    _dumpsListView.Items.Add(item);
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex, "Error refreshing dumps");
            }
        }

        /// <summary>
        /// Adds a log entry to the dashboard log viewer.
        /// </summary>
        public void AddLogEntry(LogEntry entry)
        {
            _logViewer?.AddEntry(entry);
        }

        /// <summary>
        /// Adds a log entry with parameters.
        /// </summary>
        public void AddLogEntry(string category, string level, string eventType, string details)
        {
            _logViewer?.AddEntry(category, level, eventType, details);
        }

        #region Event Handlers

        private void OnExportLog(object sender, EventArgs e)
        {
            // Trigger the log viewer's export
            _tabControl.SelectedTab = _eventsTab;
        }

        private void OnExportOverview(object sender, EventArgs e)
        {
            using (var dialog = new SaveFileDialog())
            {
                dialog.Filter = "Text Files (*.txt)|*.txt";
                dialog.DefaultExt = "txt";
                dialog.FileName = $"clouseau_overview_{DateTime.Now:yyyyMMdd_HHmmss}";

                if (dialog.ShowDialog() == DialogResult.OK)
                {
                    try
                    {
                        var sb = new StringBuilder();
                        sb.AppendLine("mbClouseau Overview Export");
                        sb.AppendLine($"Generated: {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
                        sb.AppendLine(new string('=', 60));
                        sb.AppendLine();
                        sb.AppendLine("=== Session Information ===");
                        sb.AppendLine(_sessionInfoLabel?.Text ?? "N/A");
                        sb.AppendLine();
                        sb.AppendLine("=== Event Statistics ===");
                        sb.AppendLine(_eventStatsLabel?.Text ?? "N/A");
                        sb.AppendLine();
                        sb.AppendLine("=== MusicBee Information ===");
                        sb.AppendLine(_musicBeeInfoLabel?.Text ?? "N/A");

                        File.WriteAllText(dialog.FileName, sb.ToString());
                        MessageBox.Show($"Overview exported to:\n{dialog.FileName}", "Export Complete",
                            MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                    catch (Exception ex)
                    {
                        Logger.Error(ex, "Error exporting overview");
                        MessageBox.Show($"Error exporting overview:\n{ex.Message}", "Error",
                            MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            }
        }

        private void OnExportMetrics(object sender, EventArgs e)
        {
            using (var dialog = new SaveFileDialog())
            {
                dialog.Filter = "Text Files (*.txt)|*.txt|JSON Files (*.json)|*.json";
                dialog.DefaultExt = "txt";
                dialog.FileName = $"clouseau_metrics_{DateTime.Now:yyyyMMdd_HHmmss}";

                if (dialog.ShowDialog() == DialogResult.OK)
                {
                    try
                    {
                        if (dialog.FileName.EndsWith(".json") && _metricsCollector != null)
                        {
                            var snapshot = _metricsCollector.GetCurrentSnapshot();
                            var json = Newtonsoft.Json.JsonConvert.SerializeObject(snapshot, Newtonsoft.Json.Formatting.Indented);
                            File.WriteAllText(dialog.FileName, json);
                        }
                        else
                        {
                            var content = _metricsCollector?.GetDiagnosticSummary() ?? _metricsLabel?.Text ?? "No metrics available";
                            File.WriteAllText(dialog.FileName, content);
                        }

                        MessageBox.Show($"Metrics exported to:\n{dialog.FileName}", "Export Complete",
                            MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                    catch (Exception ex)
                    {
                        Logger.Error(ex, "Error exporting metrics");
                        MessageBox.Show($"Error exporting metrics:\n{ex.Message}", "Error",
                            MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            }
        }

        private void OnExportPlugins(object sender, EventArgs e)
        {
            using (var dialog = new SaveFileDialog())
            {
                dialog.Filter = "Text Files (*.txt)|*.txt";
                dialog.DefaultExt = "txt";
                dialog.FileName = $"clouseau_plugins_{DateTime.Now:yyyyMMdd_HHmmss}";

                if (dialog.ShowDialog() == DialogResult.OK)
                {
                    try
                    {
                        var content = _pluginDiscovery.GetDiscoverySummary();
                        File.WriteAllText(dialog.FileName, content);

                        MessageBox.Show($"Plugins exported to:\n{dialog.FileName}", "Export Complete",
                            MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                    catch (Exception ex)
                    {
                        Logger.Error(ex, "Error exporting plugins");
                        MessageBox.Show($"Error exporting plugins:\n{ex.Message}", "Error",
                            MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            }
        }

        private void OnForceGC(object sender, EventArgs e)
        {
            try
            {
                Cursor = Cursors.WaitCursor;
                string report;

                if (_metricsCollector != null)
                {
                    report = _metricsCollector.ForceGCAndReport();
                }
                else
                {
                    var before = GC.GetTotalMemory(false);
                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                    GC.Collect();
                    var after = GC.GetTotalMemory(true);
                    var freed = (before - after) / (1024 * 1024);
                    report = $"Forced GC complete.\nFreed: {freed}MB";
                }

                Cursor = Cursors.Default;
                UpdateMetricsDisplay();
                MessageBox.Show(report, "GC Complete", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                Cursor = Cursors.Default;
                Logger.Error(ex, "Error forcing GC");
                MessageBox.Show($"Error: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void OnCreateDump(object sender, EventArgs e)
        {
            try
            {
                Cursor = Cursors.WaitCursor;
                var path = _stateDumper.DumpState();
                RefreshDumps();
                Cursor = Cursors.Default;

                var result = MessageBox.Show(
                    $"State dump created:\n{path}\n\nOpen in editor?",
                    "Dump Created",
                    MessageBoxButtons.YesNo,
                    MessageBoxIcon.Information);

                if (result == DialogResult.Yes)
                {
                    Process.Start("notepad.exe", path);
                }
            }
            catch (Exception ex)
            {
                Cursor = Cursors.Default;
                Logger.Error(ex, "Error creating state dump");
                MessageBox.Show($"Error creating dump:\n{ex.Message}", "Error",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void OnRefreshAll(object sender, EventArgs e)
        {
            RefreshPlugins();
            RefreshDumps();
            UpdateOverviewDisplay();
            UpdateMetricsDisplay();
        }

        private void OnClearLog(object sender, EventArgs e)
        {
            // The log viewer handles its own clear
        }

        private void OnAbout(object sender, EventArgs e)
        {
            var aboutForm = new Form
            {
                Text = "About mbClouseau",
                Size = new Size(430, 450),
                FormBorderStyle = FormBorderStyle.FixedDialog,
                StartPosition = FormStartPosition.CenterParent,
                MaximizeBox = false,
                MinimizeBox = false,
                BackColor = Color.White
            };

            var titleLabel = new Label
            {
                Text = "mbClouseau",
                Location = new Point(20, 20),
                AutoSize = true,
                Font = new Font("Segoe UI", 16F, FontStyle.Bold),
                ForeColor = Color.FromArgb(0, 102, 204)
            };
            aboutForm.Controls.Add(titleLabel);

            var version = typeof(DashboardForm).Assembly.GetName().Version;
            var infoLabel = new Label
            {
                Text = $"Version: {version}\n\n" +
                       "Uncovering clues with MusicBee Clouseau\n\n" +
                       "A trace/debug utility for MusicBee plugin developers.\n\n" +
                       "by HALRAD 2026",
                Location = new Point(20, 90),
                Size = new Size(290, 250),
                Font = new Font("Segoe UI", 8F),
                ForeColor = Color.Black
            };
            aboutForm.Controls.Add(infoLabel);

            // Logo in upper right - add after other controls so it's positioned correctly
            var logoBox = new PictureBox
            {
                Size = new Size(80, 80),
                Location = new Point(310, 15),
                SizeMode = PictureBoxSizeMode.Zoom,
                BackColor = Color.Transparent
            };
            try
            {
                var assembly = System.Reflection.Assembly.GetExecutingAssembly();
                using (var stream = assembly.GetManifestResourceStream("HALRAD_mb_Clouseau.png"))
                {
                    if (stream != null)
                        logoBox.Image = Image.FromStream(stream);
                }
            }
            catch { }
            aboutForm.Controls.Add(logoBox);
            logoBox.BringToFront();

            var updatesLink = new LinkLabel
            {
                Text = "Check for updates",
                Location = new Point(20, 335),
                AutoSize = true,
                Font = new Font("Segoe UI", 9F),
                LinkColor = Color.FromArgb(0, 102, 204)
            };
            updatesLink.LinkClicked += (s, args) =>
            {
                try { System.Diagnostics.Process.Start("https://halrad.com/mbClouseau/download.html"); }
                catch { }
            };
            aboutForm.Controls.Add(updatesLink);

            var okButton = new Button
            {
                Text = "OK",
                Size = new Size(80, 28),
                Location = new Point(310, 335),
                DialogResult = DialogResult.OK
            };
            aboutForm.Controls.Add(okButton);
            aboutForm.AcceptButton = okButton;

            aboutForm.ShowDialog(this);
        }

        private void OnOpenUIGallery(object sender, EventArgs e)
        {
            try
            {
                // Check if gallery is already open
                foreach (Form form in Application.OpenForms)
                {
                    if (form is UIGalleryForm existingGallery && !form.IsDisposed)
                    {
                        existingGallery.BringToFront();
                        existingGallery.Focus();
                        return;
                    }
                }

                // Open new UI Gallery
                var gallery = new UIGalleryForm(
                    _mbApi,
                    _dataFolder,
                    _pluginsPath,
                    _settings,
                    _stateManager,
                    _metricsCollector,
                    _eventLogger);
                gallery.Show();
            }
            catch (Exception ex)
            {
                Logger.Error(ex, "Error opening UI Gallery");
                MessageBox.Show($"Error opening UI Gallery:\n{ex.Message}", "Error",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void OnCopyPluginInfo(object sender, EventArgs e)
        {
            if (_pluginsListView.SelectedItems.Count == 0) return;

            var plugin = _pluginsListView.SelectedItems[0].Tag as DiscoveredPlugin;
            if (plugin != null)
            {
                Clipboard.SetText(plugin.ToDisplayString());
            }
        }

        private void OnDumpDoubleClick(object sender, EventArgs e)
        {
            OnOpenDump(sender, e);
        }

        private void OnOpenDump(object sender, EventArgs e)
        {
            if (_dumpsListView.SelectedItems.Count == 0) return;

            var dump = _dumpsListView.SelectedItems[0].Tag as DumpFileInfo;
            if (dump != null && File.Exists(dump.FilePath))
            {
                try
                {
                    Process.Start("notepad.exe", dump.FilePath);
                }
                catch (Exception ex)
                {
                    Logger.Error(ex, "Error opening dump file");
                }
            }
        }

        private void OnDeleteDump(object sender, EventArgs e)
        {
            if (_dumpsListView.SelectedItems.Count == 0) return;

            var dump = _dumpsListView.SelectedItems[0].Tag as DumpFileInfo;
            if (dump != null)
            {
                var result = MessageBox.Show(
                    $"Delete dump file?\n{dump.FileName}",
                    "Confirm Delete",
                    MessageBoxButtons.YesNo,
                    MessageBoxIcon.Question);

                if (result == DialogResult.Yes)
                {
                    try
                    {
                        File.Delete(dump.FilePath);
                        RefreshDumps();
                    }
                    catch (Exception ex)
                    {
                        Logger.Error(ex, "Error deleting dump file");
                        MessageBox.Show($"Error deleting file:\n{ex.Message}", "Error",
                            MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            }
        }

        #endregion

        /// <summary>
        /// Formats file size in human-readable format.
        /// </summary>
        private static string FormatFileSize(long bytes)
        {
            string[] sizes = { "B", "KB", "MB", "GB" };
            double len = bytes;
            int order = 0;
            while (len >= 1024 && order < sizes.Length - 1)
            {
                order++;
                len = len / 1024;
            }
            return $"{len:0.##} {sizes[order]}";
        }

        /// <summary>
        /// Cleanup on form close.
        /// </summary>
        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            _statusTimer?.Stop();
            _statusTimer?.Dispose();

            // Clean up spy overlay
            if (_spyToolbar != null && !_spyToolbar.IsDisposed)
            {
                _spyToolbar.OverlayForm?.StopSpyMode();
                _spyToolbar.Close();
                _spyToolbar = null;
            }

            if (_eventLogger != null)
            {
                _eventLogger.LogEntryAdded -= OnEventLoggerEntryAdded;
            }

            base.OnFormClosing(e);
        }
    }

    #region Dark Theme Renderers

    /// <summary>
    /// Custom renderer for dark-themed menus.
    /// </summary>
    internal class DarkMenuRenderer : ToolStripProfessionalRenderer
    {
        private static readonly Color DarkBackground = 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 DarkHover = Color.FromArgb(62, 62, 64);
        private static readonly Color DarkSelected = Color.FromArgb(51, 51, 51);

        public DarkMenuRenderer() : base(new DarkColorTable()) { }

        protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e)
        {
            var item = e.Item;
            var g = e.Graphics;
            var rect = new Rectangle(Point.Empty, item.Size);

            if (item.Selected || item.Pressed)
            {
                using (var brush = new SolidBrush(DarkHover))
                {
                    g.FillRectangle(brush, rect);
                }
            }
            else
            {
                using (var brush = new SolidBrush(DarkBackground))
                {
                    g.FillRectangle(brush, rect);
                }
            }
        }

        protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e)
        {
            using (var brush = new SolidBrush(DarkBackground))
            {
                e.Graphics.FillRectangle(brush, e.AffectedBounds);
            }
        }

        protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)
        {
            using (var pen = new Pen(DarkBorder))
            {
                e.Graphics.DrawRectangle(pen, 0, 0, e.AffectedBounds.Width - 1, e.AffectedBounds.Height - 1);
            }
        }

        protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e)
        {
            var g = e.Graphics;
            var bounds = new Rectangle(Point.Empty, e.Item.Size);

            using (var pen = new Pen(DarkBorder))
            {
                var y = bounds.Height / 2;
                g.DrawLine(pen, 4, y, bounds.Width - 4, y);
            }
        }
    }

    /// <summary>
    /// Custom color table for dark theme.
    /// </summary>
    internal class DarkColorTable : ProfessionalColorTable
    {
        private static readonly Color DarkBackground = Color.FromArgb(45, 45, 48);
        private static readonly Color DarkBorder = Color.FromArgb(67, 67, 70);
        private static readonly Color DarkHover = Color.FromArgb(62, 62, 64);

        public override Color MenuItemSelected => DarkHover;
        public override Color MenuItemSelectedGradientBegin => DarkHover;
        public override Color MenuItemSelectedGradientEnd => DarkHover;
        public override Color MenuItemBorder => DarkBorder;
        public override Color MenuBorder => DarkBorder;
        public override Color MenuStripGradientBegin => DarkBackground;
        public override Color MenuStripGradientEnd => DarkBackground;
        public override Color ToolStripDropDownBackground => DarkBackground;
        public override Color ImageMarginGradientBegin => DarkBackground;
        public override Color ImageMarginGradientMiddle => DarkBackground;
        public override Color ImageMarginGradientEnd => DarkBackground;
        public override Color SeparatorDark => DarkBorder;
        public override Color SeparatorLight => DarkBorder;
    }

    /// <summary>
    /// Custom renderer for dark-themed toolstrips.
    /// </summary>
    internal class DarkToolStripRenderer : ToolStripProfessionalRenderer
    {
        private static readonly Color DarkBackground = Color.FromArgb(45, 45, 48);
        private static readonly Color DarkBorder = Color.FromArgb(67, 67, 70);
        private static readonly Color DarkHover = Color.FromArgb(62, 62, 64);

        public DarkToolStripRenderer() : base(new DarkColorTable()) { }

        protected override void OnRenderButtonBackground(ToolStripItemRenderEventArgs e)
        {
            var btn = e.Item as ToolStripButton;
            var g = e.Graphics;
            var bounds = new Rectangle(Point.Empty, e.Item.Size);

            if (btn != null && (btn.Selected || btn.Pressed))
            {
                using (var brush = new SolidBrush(DarkHover))
                {
                    g.FillRectangle(brush, bounds);
                }
            }
        }

        protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e)
        {
            using (var brush = new SolidBrush(DarkBackground))
            {
                e.Graphics.FillRectangle(brush, e.AffectedBounds);
            }
        }

        protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)
        {
            // No border for toolstrip
        }

        protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e)
        {
            var g = e.Graphics;
            var bounds = new Rectangle(Point.Empty, e.Item.Size);

            using (var pen = new Pen(DarkBorder))
            {
                if (e.Vertical)
                {
                    var x = bounds.Width / 2;
                    g.DrawLine(pen, x, 4, x, bounds.Height - 4);
                }
                else
                {
                    var y = bounds.Height / 2;
                    g.DrawLine(pen, 4, y, bounds.Width - 4, y);
                }
            }
        }
    }

    #endregion
}
