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

namespace MusicBeePlugin.Clouseau.UI
{
    /// <summary>
    /// Dockable panel for viewing real-time log entries.
    /// Supports filtering by category and level, search, and export.
    /// Dark theme with color coding by category and level.
    /// </summary>
    public class LogViewerPanel : UserControl
    {
        private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

        // Dark theme colors
        private static readonly Color DarkBackground = Color.FromArgb(30, 30, 30);
        private static readonly Color DarkForeground = Color.FromArgb(220, 220, 220);
        private static readonly Color DarkControlBackground = Color.FromArgb(45, 45, 45);
        private static readonly Color DarkBorder = Color.FromArgb(60, 60, 60);
        private static readonly Color DarkListBackground = Color.FromArgb(25, 25, 25);
        private static readonly Color DarkHeaderBackground = Color.FromArgb(40, 40, 40);
        private static readonly Color AccentColor = Color.FromArgb(76, 175, 80);

        // UI Components
        private ListView _logListView;
        private ComboBox _categoryFilter;
        private ComboBox _levelFilter;
        private TextBox _searchBox;
        private CheckBox _autoScrollCheckbox;
        private CheckBox _pauseCheckbox;
        private Button _clearButton;
        private Button _exportButton;
        private Button _dashboardButton;
        private Panel _headerPanel;
        private Panel _toolbarPanel;
        private Panel _statusBarPanel;
        private Label _titleLabel;
        private Label _statusLabel;
        private ContextMenuStrip _contextMenu;
        private Timer _refreshTimer;

        // State
        private readonly List<LogEntry> _allEntries;
        private readonly List<LogEntry> _filteredEntries;
        private readonly object _lockObject = new object();
        private readonly int _maxEntries;
        private bool _autoScroll;
        private bool _isPaused;
        private DateTime? _sessionStartTime;
        private LogBuffer _boundBuffer;
        private EventLogger _boundEventLogger;

        /// <summary>
        /// Event fired when dashboard button is clicked.
        /// </summary>
        public event EventHandler DashboardRequested;

        /// <summary>
        /// Gets or sets whether to show the Dashboard button. Set to false when embedded in Dashboard.
        /// </summary>
        public bool ShowDashboardButton
        {
            get => _dashboardButton?.Visible ?? false;
            set { if (_dashboardButton != null) _dashboardButton.Visible = value; }
        }

        /// <summary>
        /// Gets or sets whether to show the status bar. Set to false when embedded in Dashboard.
        /// </summary>
        public bool ShowStatusBar
        {
            get => _statusBarPanel?.Visible ?? false;
            set { if (_statusBarPanel != null) _statusBarPanel.Visible = value; }
        }

        // Category colors (adjusted for dark theme visibility)
        private static readonly Dictionary<string, Color> CategoryColors = new Dictionary<string, Color>(StringComparer.OrdinalIgnoreCase)
        {
            { "Core", Color.FromArgb(128, 128, 128) },
            { "Player", Color.FromArgb(76, 175, 80) },
            { "Queue", Color.FromArgb(33, 150, 243) },
            { "Library", Color.FromArgb(156, 39, 176) },
            { "Tags", Color.FromArgb(255, 152, 0) },
            { "Playlist", Color.FromArgb(0, 188, 212) },
            { "Download", Color.FromArgb(255, 235, 59) },
            { "Sync", Color.FromArgb(121, 85, 72) },
            { "UI", Color.FromArgb(233, 30, 99) },
            { "System", Color.FromArgb(244, 67, 54) }
        };

        // Level colors (adjusted for dark theme visibility)
        private static readonly Dictionary<string, Color> LevelColors = new Dictionary<string, Color>(StringComparer.OrdinalIgnoreCase)
        {
            { "Trace", Color.FromArgb(100, 100, 100) },
            { "Debug", Color.FromArgb(150, 150, 150) },
            { "Info", Color.FromArgb(220, 220, 220) },
            { "Warn", Color.FromArgb(255, 193, 7) },
            { "Error", Color.FromArgb(244, 67, 54) },
            { "Fatal", Color.FromArgb(183, 28, 28) }
        };

        /// <summary>
        /// Event fired when a new log entry is added.
        /// </summary>
        public event EventHandler<LogEntry> LogEntryAdded;

        /// <summary>
        /// Creates a new LogViewerPanel.
        /// </summary>
        /// <param name="maxEntries">Maximum number of entries to retain.</param>
        public LogViewerPanel(int maxEntries = 1000)
        {
            _maxEntries = maxEntries;
            _allEntries = new List<LogEntry>(maxEntries);
            _filteredEntries = new List<LogEntry>(maxEntries);
            _autoScroll = true;
            _isPaused = false;
            _sessionStartTime = DateTime.Now;

            // Initialize components
            InitializeComponent();
            SetupContextMenu();
            SetupEventHandlers();
            SetupRefreshTimer();
        }

        /// <summary>
        /// Initializes UI components with dark theme.
        /// </summary>
        private void InitializeComponent()
        {
            SuspendLayout();

            // Main layout with dark theme
            Dock = DockStyle.Fill;
            BackColor = DarkBackground;
            ForeColor = DarkForeground;

            // ============================================
            // Header Panel - Title and action buttons
            // ============================================
            _headerPanel = new Panel
            {
                Dock = DockStyle.Top,
                Height = 42,
                BackColor = DarkHeaderBackground
            };

            _titleLabel = new Label
            {
                Text = "Clouseau Event Log",
                Location = new Point(10, 12),
                AutoSize = true,
                ForeColor = Color.White,
                Font = new Font("Segoe UI", 9f, FontStyle.Bold)
            };
            _headerPanel.Controls.Add(_titleLabel);

            // Dashboard button (hidden when inside Dashboard)
            _dashboardButton = new Button
            {
                Text = "Dashboard",
                Location = new Point(200, 7),
                Size = new Size(100, 28),
                FlatStyle = FlatStyle.Flat,
                ForeColor = Color.White,
                BackColor = AccentColor
            };
            _dashboardButton.FlatAppearance.BorderSize = 0;
            _headerPanel.Controls.Add(_dashboardButton);

            Controls.Add(_headerPanel);

            // ============================================
            // Toolbar Panel - Filters and controls
            // ============================================
            _toolbarPanel = new Panel
            {
                Dock = DockStyle.Top,
                Height = 38,
                Padding = new Padding(4),
                BackColor = DarkControlBackground
            };

            int xPos = 5;

            // Category filter
            var categoryLabel = new Label
            {
                Text = "Category:",
                AutoSize = true,
                Location = new Point(xPos, 8),
                ForeColor = DarkForeground
            };
            _toolbarPanel.Controls.Add(categoryLabel);
            xPos += categoryLabel.Width + 45;

            _categoryFilter = new ComboBox
            {
                Location = new Point(xPos, 4),
                Width = 90,
                DropDownStyle = ComboBoxStyle.DropDownList,
                BackColor = DarkControlBackground,
                ForeColor = DarkForeground,
                FlatStyle = FlatStyle.Flat
            };
            _categoryFilter.Items.Add("All");
            _categoryFilter.Items.AddRange(CategoryColors.Keys.ToArray());
            _categoryFilter.SelectedIndex = 0;
            _toolbarPanel.Controls.Add(_categoryFilter);
            xPos += _categoryFilter.Width + 10;

            // Level filter
            var levelLabel = new Label
            {
                Text = "Level:",
                AutoSize = true,
                Location = new Point(xPos, 8),
                ForeColor = DarkForeground
            };
            _toolbarPanel.Controls.Add(levelLabel);
            xPos += levelLabel.Width + 30;

            _levelFilter = new ComboBox
            {
                Location = new Point(xPos, 4),
                Width = 70,
                DropDownStyle = ComboBoxStyle.DropDownList,
                BackColor = DarkControlBackground,
                ForeColor = DarkForeground,
                FlatStyle = FlatStyle.Flat
            };
            _levelFilter.Items.Add("All");
            _levelFilter.Items.AddRange(new[] { "Trace", "Debug", "Info", "Warn", "Error", "Fatal" });
            _levelFilter.SelectedIndex = 0;
            _toolbarPanel.Controls.Add(_levelFilter);
            xPos += _levelFilter.Width + 10;

            // Search box
            var searchLabel = new Label
            {
                Text = "Search:",
                AutoSize = true,
                Location = new Point(xPos, 8),
                ForeColor = DarkForeground
            };
            _toolbarPanel.Controls.Add(searchLabel);
            xPos += searchLabel.Width + 35;

            _searchBox = new TextBox
            {
                Location = new Point(xPos, 5),
                Width = 100,
                BackColor = DarkControlBackground,
                ForeColor = DarkForeground,
                BorderStyle = BorderStyle.FixedSingle
            };
            _toolbarPanel.Controls.Add(_searchBox);
            xPos += _searchBox.Width + 10;

            // Pause checkbox
            _pauseCheckbox = new CheckBox
            {
                Text = "Pause",
                AutoSize = true,
                Location = new Point(xPos, 7),
                Checked = false,
                ForeColor = DarkForeground
            };
            _toolbarPanel.Controls.Add(_pauseCheckbox);
            xPos += 60;

            // Auto-scroll checkbox
            _autoScrollCheckbox = new CheckBox
            {
                Text = "Auto-scroll",
                AutoSize = true,
                Location = new Point(xPos, 7),
                Checked = true,
                ForeColor = DarkForeground
            };
            _toolbarPanel.Controls.Add(_autoScrollCheckbox);
            xPos += 85;

            // Clear button with dark theme
            _clearButton = new Button
            {
                Text = "Clear",
                Location = new Point(xPos, 5),
                Width = 60,
                Height = 28,
                BackColor = DarkControlBackground,
                ForeColor = DarkForeground,
                FlatStyle = FlatStyle.Flat
            };
            _clearButton.FlatAppearance.BorderColor = DarkBorder;
            _toolbarPanel.Controls.Add(_clearButton);
            xPos += 65;

            // Export button with dark theme
            _exportButton = new Button
            {
                Text = "Export",
                Location = new Point(xPos, 5),
                Width = 65,
                Height = 28,
                BackColor = DarkControlBackground,
                ForeColor = DarkForeground,
                FlatStyle = FlatStyle.Flat
            };
            _exportButton.FlatAppearance.BorderColor = DarkBorder;
            _toolbarPanel.Controls.Add(_exportButton);

            Controls.Add(_toolbarPanel);

            // ============================================
            // Status Bar Panel - Entry counts and session info
            // ============================================
            _statusBarPanel = new Panel
            {
                Dock = DockStyle.Bottom,
                Height = 22,
                BackColor = DarkHeaderBackground
            };

            _statusLabel = new Label
            {
                Text = "Ready",
                Location = new Point(10, 4),
                AutoSize = true,
                ForeColor = Color.Gray,
                Font = new Font("Segoe UI", 8f)
            };
            _statusBarPanel.Controls.Add(_statusLabel);

            Controls.Add(_statusBarPanel);

            // ============================================
            // Log ListView (virtual mode for performance)
            // ============================================
            _logListView = new ListView
            {
                Dock = DockStyle.Fill,
                View = View.Details,
                FullRowSelect = true,
                VirtualMode = true,
                VirtualListSize = 0,
                GridLines = true,
                Font = new Font("Consolas", 9F),
                BackColor = DarkListBackground,
                ForeColor = DarkForeground,
                BorderStyle = BorderStyle.None
            };

            _logListView.Columns.Add("Time", -1);      // Auto-size to header
            _logListView.Columns.Add("Level", -1);     // Auto-size to header
            _logListView.Columns.Add("Category", -1);  // Auto-size to header
            _logListView.Columns.Add("Event", -1);     // Auto-size to header
            _logListView.Columns.Add("Details", -2);   // Auto-size to fill remaining space

            Controls.Add(_logListView);

            // Context menu with dark theme
            _contextMenu = new ContextMenuStrip
            {
                BackColor = DarkControlBackground,
                ForeColor = DarkForeground
            };
            _logListView.ContextMenuStrip = _contextMenu;

            // Adjust control z-order so docking works correctly
            _logListView.BringToFront();

            ResumeLayout(false);
        }

        /// <summary>
        /// Sets up the context menu.
        /// </summary>
        private void SetupContextMenu()
        {
            var copyItem = new ToolStripMenuItem("Copy Entry", null, OnCopyEntry);
            var copyAllItem = new ToolStripMenuItem("Copy All Visible", null, OnCopyAll);
            var exportSelectionItem = new ToolStripMenuItem("Export Selection", null, OnExportSelection);
            var separator = new ToolStripSeparator();
            var clearItem = new ToolStripMenuItem("Clear Log", null, OnClearLog);

            _contextMenu.Items.AddRange(new ToolStripItem[]
            {
                copyItem,
                copyAllItem,
                exportSelectionItem,
                separator,
                clearItem
            });
        }

        /// <summary>
        /// Sets up event handlers.
        /// </summary>
        private void SetupEventHandlers()
        {
            _categoryFilter.SelectedIndexChanged += (s, e) => ApplyFilters();
            _levelFilter.SelectedIndexChanged += (s, e) => ApplyFilters();
            _searchBox.TextChanged += (s, e) => ApplyFilters();
            _autoScrollCheckbox.CheckedChanged += (s, e) => _autoScroll = _autoScrollCheckbox.Checked;
            _pauseCheckbox.CheckedChanged += OnPauseChanged;
            _clearButton.Click += OnClearLog;
            _exportButton.Click += OnExportLog;
            _dashboardButton.Click += OnDashboardClick;
            _logListView.RetrieveVirtualItem += OnRetrieveVirtualItem;
            _logListView.ColumnWidthChanged += OnColumnWidthChanged;
        }

        /// <summary>
        /// Sets up the status refresh timer.
        /// </summary>
        private void SetupRefreshTimer()
        {
            _refreshTimer = new Timer { Interval = 500 };
            _refreshTimer.Tick += OnRefreshTimerTick;
            _refreshTimer.Start();
        }

        /// <summary>
        /// Handles pause checkbox changes.
        /// </summary>
        private void OnPauseChanged(object sender, EventArgs e)
        {
            _isPaused = _pauseCheckbox.Checked;
            UpdatePauseVisual();
            UpdateStatusBar();
        }

        /// <summary>
        /// Updates the visual state when paused.
        /// </summary>
        private void UpdatePauseVisual()
        {
            if (_isPaused)
            {
                _titleLabel.Text = "Clouseau Event Log [PAUSED]";
                _titleLabel.ForeColor = Color.FromArgb(255, 193, 7); // Warning yellow
            }
            else
            {
                _titleLabel.Text = "Clouseau Event Log";
                _titleLabel.ForeColor = Color.White;
            }
        }

        /// <summary>
        /// Handles dashboard button click.
        /// </summary>
        private void OnDashboardClick(object sender, EventArgs e)
        {
            DashboardRequested?.Invoke(this, EventArgs.Empty);
        }

        /// <summary>
        /// Handles column width changes for auto-sizing last column.
        /// </summary>
        private void OnColumnWidthChanged(object sender, ColumnWidthChangedEventArgs e)
        {
            // Auto-size the last column to fill remaining space
            if (e.ColumnIndex != _logListView.Columns.Count - 1)
            {
                AdjustLastColumnWidth();
            }
        }

        /// <summary>
        /// Adjusts the last column width to fill remaining space.
        /// </summary>
        private void AdjustLastColumnWidth()
        {
            if (_logListView.Columns.Count == 0) return;

            int totalWidth = 0;
            for (int i = 0; i < _logListView.Columns.Count - 1; i++)
            {
                totalWidth += _logListView.Columns[i].Width;
            }

            int remainingWidth = _logListView.ClientSize.Width - totalWidth - 20; // 20 for scrollbar
            if (remainingWidth > 100)
            {
                _logListView.Columns[_logListView.Columns.Count - 1].Width = remainingWidth;
            }
        }

        /// <summary>
        /// Timer tick handler for refreshing status bar.
        /// </summary>
        private void OnRefreshTimerTick(object sender, EventArgs e)
        {
            UpdateStatusBar();
        }

        /// <summary>
        /// Updates the status bar with current statistics.
        /// </summary>
        private void UpdateStatusBar()
        {
            if (_statusLabel == null) return;

            string sessionTime = "";
            if (_sessionStartTime.HasValue)
            {
                var elapsed = DateTime.Now - _sessionStartTime.Value;
                sessionTime = $"Session: {elapsed.Hours:D2}:{elapsed.Minutes:D2}:{elapsed.Seconds:D2}";
            }

            string pauseStatus = _isPaused ? " [PAUSED]" : "";
            string filterStatus = "";

            lock (_lockObject)
            {
                if (_filteredEntries.Count != _allEntries.Count)
                {
                    filterStatus = $" (filtered: {_filteredEntries.Count})";
                }

                _statusLabel.Text = $"{sessionTime} | Total: {_allEntries.Count}{filterStatus}{pauseStatus}";
            }
        }

        /// <summary>
        /// Adds a new log entry to the viewer.
        /// Thread-safe method that can be called from any thread.
        /// Respects pause state - entries are still stored but display not updated.
        /// </summary>
        public void AddEntry(LogEntry entry)
        {
            if (entry == null) return;

            lock (_lockObject)
            {
                // Remove oldest entries if at max
                while (_allEntries.Count >= _maxEntries)
                {
                    _allEntries.RemoveAt(0);
                }

                _allEntries.Add(entry);
            }

            // Only update display if not paused
            if (!_isPaused)
            {
                // Update UI on UI thread
                if (InvokeRequired)
                {
                    BeginInvoke(new Action(() => UpdateDisplay()));
                }
                else
                {
                    UpdateDisplay();
                }
            }

            LogEntryAdded?.Invoke(this, entry);
        }

        /// <summary>
        /// Adds a log entry with parameters.
        /// </summary>
        public void AddEntry(string category, string level, string eventType, string message, string sourceFile = null)
        {
            var entry = new LogEntry(category, eventType, 0, message, level);
            if (!string.IsNullOrEmpty(sourceFile))
            {
                entry.WithSourceFile(sourceFile);
            }
            AddEntry(entry);
        }

        /// <summary>
        /// Updates the display with filtered entries.
        /// </summary>
        private void UpdateDisplay()
        {
            ApplyFilters();

            if (_autoScroll && _filteredEntries.Count > 0)
            {
                _logListView.EnsureVisible(_filteredEntries.Count - 1);
            }
        }

        /// <summary>
        /// Applies current filters to the entry list.
        /// </summary>
        private void ApplyFilters()
        {
            lock (_lockObject)
            {
                _filteredEntries.Clear();

                var categoryFilter = _categoryFilter.SelectedItem?.ToString() ?? "All";
                var levelFilter = _levelFilter.SelectedItem?.ToString() ?? "All";
                var searchText = _searchBox.Text?.ToLowerInvariant() ?? "";

                foreach (var entry in _allEntries)
                {
                    // Category filter
                    if (categoryFilter != "All" && !string.Equals(entry.Category, categoryFilter, StringComparison.OrdinalIgnoreCase))
                        continue;

                    // Level filter
                    if (levelFilter != "All" && !string.Equals(entry.Level, levelFilter, StringComparison.OrdinalIgnoreCase))
                        continue;

                    // Search filter
                    if (!string.IsNullOrEmpty(searchText))
                    {
                        var matchesSearch =
                            (entry.EventType?.ToLowerInvariant().Contains(searchText) == true) ||
                            (entry.Message?.ToLowerInvariant().Contains(searchText) == true) ||
                            (entry.SourceFile?.ToLowerInvariant().Contains(searchText) == true);

                        if (!matchesSearch) continue;
                    }

                    _filteredEntries.Add(entry);
                }

                _logListView.VirtualListSize = _filteredEntries.Count;
                _logListView.Invalidate();
            }
        }

        /// <summary>
        /// Handles virtual list item retrieval with dark theme coloring.
        /// </summary>
        private void OnRetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
        {
            lock (_lockObject)
            {
                if (e.ItemIndex < 0 || e.ItemIndex >= _filteredEntries.Count)
                {
                    e.Item = new ListViewItem(new[] { "", "", "", "", "" })
                    {
                        BackColor = DarkListBackground,
                        ForeColor = DarkForeground
                    };
                    return;
                }

                var entry = _filteredEntries[e.ItemIndex];
                var item = new ListViewItem(new[]
                {
                    entry.Timestamp.ToString("HH:mm:ss.fff"),
                    entry.Level ?? "",
                    entry.Category ?? "",
                    entry.EventType ?? "",
                    entry.Message ?? ""
                });

                // Default dark theme colors
                item.BackColor = DarkListBackground;
                item.ForeColor = DarkForeground;

                // Apply category color as subtle background tint
                if (!string.IsNullOrEmpty(entry.Category) && CategoryColors.TryGetValue(entry.Category, out var catColor))
                {
                    // Create a subtle tint by blending with dark background
                    item.BackColor = Color.FromArgb(
                        35,
                        Math.Min(25 + (catColor.R / 10), 255),
                        Math.Min(25 + (catColor.G / 10), 255),
                        Math.Min(25 + (catColor.B / 10), 255)
                    );
                }

                // Apply level color to text - use brighter colors for visibility
                if (!string.IsNullOrEmpty(entry.Level) && LevelColors.TryGetValue(entry.Level, out var levelColor))
                {
                    item.ForeColor = levelColor;
                }

                e.Item = item;
            }
        }

        /// <summary>
        /// Clears all log entries.
        /// </summary>
        private void OnClearLog(object sender, EventArgs e)
        {
            lock (_lockObject)
            {
                _allEntries.Clear();
                _filteredEntries.Clear();
                _logListView.VirtualListSize = 0;
                _logListView.Invalidate();
            }
        }

        /// <summary>
        /// Exports the log to a file.
        /// </summary>
        private void OnExportLog(object sender, EventArgs e)
        {
            using (var dialog = new SaveFileDialog())
            {
                dialog.Filter = "Text Files (*.txt)|*.txt|CSV Files (*.csv)|*.csv|JSON Files (*.json)|*.json";
                dialog.DefaultExt = "txt";
                dialog.FileName = $"clouseau_log_{DateTime.Now:yyyyMMdd_HHmmss}";

                if (dialog.ShowDialog() == DialogResult.OK)
                {
                    try
                    {
                        ExportToFile(dialog.FileName, _filteredEntries);
                        MessageBox.Show($"Log exported to:\n{dialog.FileName}", "Export Complete",
                            MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                    catch (Exception ex)
                    {
                        Logger.Error(ex, "Error exporting log");
                        MessageBox.Show($"Error exporting log:\n{ex.Message}", "Export Error",
                            MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            }
        }

        /// <summary>
        /// Copies the selected entry to clipboard.
        /// </summary>
        private void OnCopyEntry(object sender, EventArgs e)
        {
            if (_logListView.SelectedIndices.Count == 0) return;

            lock (_lockObject)
            {
                var sb = new StringBuilder();
                foreach (int index in _logListView.SelectedIndices)
                {
                    if (index >= 0 && index < _filteredEntries.Count)
                    {
                        var entry = _filteredEntries[index];
                        sb.AppendLine(FormatEntry(entry));
                    }
                }
                Clipboard.SetText(sb.ToString());
            }
        }

        /// <summary>
        /// Copies all visible entries to clipboard.
        /// </summary>
        private void OnCopyAll(object sender, EventArgs e)
        {
            lock (_lockObject)
            {
                var sb = new StringBuilder();
                foreach (var entry in _filteredEntries)
                {
                    sb.AppendLine(FormatEntry(entry));
                }
                Clipboard.SetText(sb.ToString());
            }
        }

        /// <summary>
        /// Exports selected entries.
        /// </summary>
        private void OnExportSelection(object sender, EventArgs e)
        {
            if (_logListView.SelectedIndices.Count == 0) return;

            using (var dialog = new SaveFileDialog())
            {
                dialog.Filter = "Text Files (*.txt)|*.txt";
                dialog.DefaultExt = "txt";
                dialog.FileName = $"clouseau_selection_{DateTime.Now:yyyyMMdd_HHmmss}";

                if (dialog.ShowDialog() == DialogResult.OK)
                {
                    lock (_lockObject)
                    {
                        var selected = new List<LogEntry>();
                        foreach (int index in _logListView.SelectedIndices)
                        {
                            if (index >= 0 && index < _filteredEntries.Count)
                            {
                                selected.Add(_filteredEntries[index]);
                            }
                        }
                        ExportToFile(dialog.FileName, selected);
                    }
                }
            }
        }

        /// <summary>
        /// Formats a log entry as a string.
        /// </summary>
        private string FormatEntry(LogEntry entry)
        {
            return $"[{entry.Timestamp:yyyy-MM-dd HH:mm:ss.fff}] [{entry.Level}] [{entry.Category}] {entry.EventType}: {entry.Message}";
        }

        /// <summary>
        /// Exports entries to a file.
        /// </summary>
        private void ExportToFile(string filePath, List<LogEntry> entries)
        {
            var extension = System.IO.Path.GetExtension(filePath).ToLowerInvariant();

            switch (extension)
            {
                case ".csv":
                    ExportToCsv(filePath, entries);
                    break;
                case ".json":
                    ExportToJson(filePath, entries);
                    break;
                default:
                    ExportToText(filePath, entries);
                    break;
            }
        }

        private void ExportToText(string filePath, List<LogEntry> entries)
        {
            var sb = new StringBuilder();
            sb.AppendLine($"mb_clouseau Log Export - {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
            sb.AppendLine(new string('=', 80));
            sb.AppendLine();

            foreach (var entry in entries)
            {
                sb.AppendLine(FormatEntry(entry));
            }

            System.IO.File.WriteAllText(filePath, sb.ToString());
        }

        private void ExportToCsv(string filePath, List<LogEntry> entries)
        {
            var sb = new StringBuilder();
            sb.AppendLine("Timestamp,Level,Category,EventType,Message,SourceFile");

            foreach (var entry in entries)
            {
                sb.AppendLine($"\"{entry.Timestamp:yyyy-MM-dd HH:mm:ss.fff}\",\"{entry.Level}\",\"{entry.Category}\",\"{entry.EventType}\",\"{entry.Message?.Replace("\"", "\"\"")}\",\"{entry.SourceFile}\"");
            }

            System.IO.File.WriteAllText(filePath, sb.ToString());
        }

        private void ExportToJson(string filePath, List<LogEntry> entries)
        {
            var json = Newtonsoft.Json.JsonConvert.SerializeObject(entries, Newtonsoft.Json.Formatting.Indented);
            System.IO.File.WriteAllText(filePath, json);
        }

        /// <summary>
        /// Gets the current entry count.
        /// </summary>
        public int EntryCount
        {
            get
            {
                lock (_lockObject)
                {
                    return _allEntries.Count;
                }
            }
        }

        /// <summary>
        /// Gets the filtered entry count.
        /// </summary>
        public int FilteredCount
        {
            get
            {
                lock (_lockObject)
                {
                    return _filteredEntries.Count;
                }
            }
        }

        /// <summary>
        /// Binds this panel to an EventLogger for live updates.
        /// The panel will automatically receive new log entries as they are added.
        /// </summary>
        /// <param name="eventLogger">The EventLogger to bind to.</param>
        public void BindToEventLogger(EventLogger eventLogger)
        {
            if (eventLogger == null)
            {
                throw new ArgumentNullException(nameof(eventLogger));
            }

            // Unbind from previous event logger if any
            if (_boundEventLogger != null)
            {
                _boundEventLogger.LogEntryAdded -= OnBoundEntryAdded;
            }

            _boundEventLogger = eventLogger;
            _boundBuffer = eventLogger.Buffer;

            // Subscribe to new entries
            eventLogger.LogEntryAdded += OnBoundEntryAdded;

            // Load existing entries from buffer
            LoadFromBuffer(_boundBuffer);

            Logger.Debug("LogViewerPanel bound to EventLogger");
        }

        /// <summary>
        /// Binds this panel to a LogBuffer for live updates.
        /// The panel will display existing entries and can be refreshed manually.
        /// </summary>
        /// <param name="buffer">The LogBuffer to bind to.</param>
        public void BindToBuffer(LogBuffer buffer)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }

            _boundBuffer = buffer;
            LoadFromBuffer(buffer);

            Logger.Debug("LogViewerPanel bound to LogBuffer with {0} entries", buffer.Count);
        }

        /// <summary>
        /// Loads entries from a LogBuffer into the panel.
        /// </summary>
        /// <param name="buffer">The buffer to load from.</param>
        private void LoadFromBuffer(LogBuffer buffer)
        {
            lock (_lockObject)
            {
                _allEntries.Clear();
                _allEntries.AddRange(buffer.GetAll());
            }

            if (InvokeRequired)
            {
                BeginInvoke(new Action(() => UpdateDisplay()));
            }
            else
            {
                UpdateDisplay();
            }
        }

        /// <summary>
        /// Refreshes the display from the bound buffer.
        /// </summary>
        public void RefreshFromBuffer()
        {
            if (_boundBuffer != null)
            {
                LoadFromBuffer(_boundBuffer);
            }
        }

        /// <summary>
        /// Handles new entries from the bound EventLogger.
        /// </summary>
        private void OnBoundEntryAdded(object sender, LogEntry entry)
        {
            AddEntry(entry);
        }

        /// <summary>
        /// Unbinds from the current EventLogger/Buffer.
        /// </summary>
        public void Unbind()
        {
            if (_boundEventLogger != null)
            {
                _boundEventLogger.LogEntryAdded -= OnBoundEntryAdded;
                _boundEventLogger = null;
            }
            _boundBuffer = null;

            Logger.Debug("LogViewerPanel unbound");
        }

        /// <summary>
        /// Gets whether the panel is currently bound to an EventLogger or Buffer.
        /// </summary>
        public bool IsBound => _boundEventLogger != null || _boundBuffer != null;

        /// <summary>
        /// Gets or sets whether live updates are paused.
        /// </summary>
        public bool IsPaused
        {
            get => _isPaused;
            set
            {
                if (_isPaused != value)
                {
                    _isPaused = value;
                    if (_pauseCheckbox != null && _pauseCheckbox.Checked != value)
                    {
                        _pauseCheckbox.Checked = value;
                    }
                    UpdatePauseVisual();
                    UpdateStatusBar();

                    // Refresh display when unpausing
                    if (!_isPaused)
                    {
                        UpdateDisplay();
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets the session start time for status display.
        /// </summary>
        public DateTime? SessionStartTime
        {
            get => _sessionStartTime;
            set
            {
                _sessionStartTime = value;
                UpdateStatusBar();
            }
        }

        /// <summary>
        /// Gets or sets whether auto-scroll is enabled.
        /// </summary>
        public bool AutoScrollEnabled
        {
            get => _autoScroll;
            set
            {
                _autoScroll = value;
                if (_autoScrollCheckbox != null && _autoScrollCheckbox.Checked != value)
                {
                    _autoScrollCheckbox.Checked = value;
                }
            }
        }

        /// <summary>
        /// Gets the currently selected category filter.
        /// </summary>
        public string SelectedCategory => _categoryFilter?.SelectedItem?.ToString() ?? "All";

        /// <summary>
        /// Gets the currently selected level filter.
        /// </summary>
        public string SelectedLevel => _levelFilter?.SelectedItem?.ToString() ?? "All";

        /// <summary>
        /// Gets the current search text.
        /// </summary>
        public string SearchText => _searchBox?.Text ?? "";

        /// <summary>
        /// Programmatically sets the category filter.
        /// </summary>
        /// <param name="category">The category to filter by, or "All" for no filter.</param>
        public void SetCategoryFilter(string category)
        {
            if (_categoryFilter == null) return;

            var index = _categoryFilter.Items.IndexOf(category);
            if (index >= 0)
            {
                _categoryFilter.SelectedIndex = index;
            }
        }

        /// <summary>
        /// Programmatically sets the level filter.
        /// </summary>
        /// <param name="level">The level to filter by, or "All" for no filter.</param>
        public void SetLevelFilter(string level)
        {
            if (_levelFilter == null) return;

            var index = _levelFilter.Items.IndexOf(level);
            if (index >= 0)
            {
                _levelFilter.SelectedIndex = index;
            }
        }

        /// <summary>
        /// Programmatically sets the search text.
        /// </summary>
        /// <param name="text">The text to search for.</param>
        public void SetSearchText(string text)
        {
            if (_searchBox != null)
            {
                _searchBox.Text = text ?? "";
            }
        }

        /// <summary>
        /// Clears all filters.
        /// </summary>
        public void ClearFilters()
        {
            if (_categoryFilter != null)
            {
                _categoryFilter.SelectedIndex = 0;
            }
            if (_levelFilter != null)
            {
                _levelFilter.SelectedIndex = 0;
            }
            if (_searchBox != null)
            {
                _searchBox.Text = "";
            }
        }

        /// <summary>
        /// Scrolls to the most recent entry.
        /// </summary>
        public void ScrollToEnd()
        {
            if (_logListView != null && _filteredEntries.Count > 0)
            {
                _logListView.EnsureVisible(_filteredEntries.Count - 1);
            }
        }

        /// <summary>
        /// Scrolls to the first entry.
        /// </summary>
        public void ScrollToStart()
        {
            if (_logListView != null && _filteredEntries.Count > 0)
            {
                _logListView.EnsureVisible(0);
            }
        }

        /// <summary>
        /// Gets all entries that match the current filter.
        /// </summary>
        /// <returns>A copy of the filtered entries list.</returns>
        public List<LogEntry> GetFilteredEntries()
        {
            lock (_lockObject)
            {
                return new List<LogEntry>(_filteredEntries);
            }
        }

        /// <summary>
        /// Gets all entries regardless of filter.
        /// </summary>
        /// <returns>A copy of all entries.</returns>
        public List<LogEntry> GetAllEntries()
        {
            lock (_lockObject)
            {
                return new List<LogEntry>(_allEntries);
            }
        }

        /// <summary>
        /// Disposes of resources used by this panel.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _refreshTimer?.Stop();
                _refreshTimer?.Dispose();
                Unbind();
                _contextMenu?.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}
