"""
Dockable panels for StreamLens GUI
"""

import os
from typing import Optional, List, TYPE_CHECKING, Dict
from PySide6.QtWidgets import (
    QDockWidget, QWidget, QVBoxLayout, QHBoxLayout, QTableWidget, 
    QTableWidgetItem, QLabel, QHeaderView, QSplitter, QTextEdit
)
from PySide6.QtCore import Qt, Signal
from PySide6.QtGui import QFont, QColor

try:
    # Matplotlib integration - lazy loaded
    matplotlib = None
    FigureCanvas = None
    NavigationToolbar = None
    Figure = None
    plt = None
    
    def _ensure_matplotlib_gui_loaded():
        """Lazy load matplotlib for GUI mode"""
        global matplotlib, FigureCanvas, NavigationToolbar, Figure, plt
        
        if matplotlib is not None:
            return True
            
        try:
            import matplotlib as mpl
            matplotlib = mpl
            matplotlib.use('Qt5Agg')  # Use Qt backend for matplotlib
            
            from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FC
            from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NT
            from matplotlib.figure import Figure as Fig
            import matplotlib.pyplot as pyplot
            
            # Turn off interactive mode to prevent floating windows
            pyplot.ioff()
            
            # Ensure no figure windows are created
            mpl.rcParams['figure.max_open_warning'] = 0
            mpl.rcParams['backend'] = 'Qt5Agg'
            
            # Prevent any automatic figure display
            mpl.pyplot.show = lambda *args, **kwargs: None
            pyplot.show = lambda *args, **kwargs: None
            
            # Also prevent figure.show()
            original_figure_show = Fig.show
            Fig.show = lambda self, *args, **kwargs: None
            
            FigureCanvas = FC
            NavigationToolbar = NT
            Figure = Fig
            plt = pyplot
            
            return True
        except ImportError as e:
            print(f"Matplotlib GUI integration not available: {e}")
            return False
            
except ImportError as e:
    print(f"GUI dependencies not available: {e}")

if TYPE_CHECKING:
    from ..analysis.core import EthernetAnalyzer
    from ..models.flow_stats import FlowStats


class FlowListDockWidget(QWidget):
    """Widget containing the flow list and file information with integrated plots"""
    
    def __init__(self, parent=None):
        super().__init__(parent)
        self.analyzer: Optional['EthernetAnalyzer'] = None
        self.integrated_mode = True  # Always use integrated mode
        self._signal_cache = {}  # Cache for processed signal data
        
        # Set up compact main layout
        layout = QVBoxLayout()
        layout.setContentsMargins(4, 4, 4, 4)  # Tight margins
        layout.setSpacing(2)  # Minimal spacing between elements
        
        # Compact file info section
        self.file_info_label = QLabel("No file loaded")
        self.file_info_label.setWordWrap(True)
        self.file_info_label.setStyleSheet("""
            QLabel {
                padding: 6px 12px;
                background-color: #2d2d2d;
                border: 1px solid #404040;
                border-radius: 6px;
                font-size: 11px;
                color: #cccccc;
                font-weight: 500;
            }
        """)
        self.file_info_label.setMaximumHeight(35)  # Compact height
        layout.addWidget(self.file_info_label)
        
        # Compact flow table with comprehensive data
        self.flows_table = QTableWidget()
        self.flows_table.setColumnCount(10)  # More columns for dense data
        self.flows_table.setHorizontalHeaderLabels([
            "Source IP", "Dest IP", "Pkts", "Bytes", "Max σ", "Avg ΔT", "Std ΔT", "Outliers", "Protocols", "Signal Plot"
        ])
        
        # Configure table for compact, dense display with user-adjustable columns
        header = self.flows_table.horizontalHeader()
        # Make all columns user-resizable by dragging
        header.setSectionResizeMode(QHeaderView.Interactive)
        
        # Auto-resize headers to fit content first
        for i in range(self.flows_table.columnCount()):
            header.resizeSection(i, header.sectionSizeHint(i))
        
        # Then resize to content for data columns
        self.flows_table.resizeColumnsToContents()
        
        # Set minimum widths for important columns and ensure plot column gets priority
        header.setMinimumSectionSize(50)  # Minimum for any column
        self.flows_table.setColumnWidth(2, max(60, self.flows_table.columnWidth(2)))   # Pkts
        self.flows_table.setColumnWidth(3, max(80, self.flows_table.columnWidth(3)))   # Bytes  
        self.flows_table.setColumnWidth(4, max(60, self.flows_table.columnWidth(4)))   # Max σ
        self.flows_table.setColumnWidth(7, max(60, self.flows_table.columnWidth(7)))   # Outliers
        self.flows_table.setColumnWidth(9, max(600, self.flows_table.columnWidth(9)))  # Signal Plot gets 600px minimum
        
        # Ensure the table uses the full available width
        header.setStretchLastSection(True)  # Last column (plots) stretches to fill remaining space
        
        # Increased row height (25% taller: 24px -> 30px) and styling
        self.flows_table.setSelectionBehavior(QTableWidget.SelectRows)
        self.flows_table.setAlternatingRowColors(True)
        self.flows_table.verticalHeader().setDefaultSectionSize(30)  # 25% taller rows
        self.flows_table.setShowGrid(True)
        self.flows_table.setGridStyle(Qt.DotLine)  # Subtle grid lines
        self.flows_table.itemSelectionChanged.connect(self.on_flow_selected)
        
        # Enable sorting
        self.flows_table.setSortingEnabled(True)
        
        # Modern dark theme styling for table
        self.flows_table.setStyleSheet("""
            QTableWidget {
                background-color: #1e1e1e;
                color: #ffffff;
                font-size: 11px;
                gridline-color: #404040;
                border: 1px solid #404040;
                border-radius: 6px;
                selection-background-color: #0078d4;
                alternate-background-color: #252525;
            }
            
            QTableWidget::item {
                padding: 6px 8px;
                border: none;
            }
            
            QTableWidget::item:selected {
                background-color: #0078d4;
                color: #ffffff;
            }
            
            QTableWidget::item:hover {
                background-color: #2d2d2d;
            }
            
            QHeaderView::section {
                background-color: #2d2d2d;
                color: #ffffff;
                padding: 8px 12px;
                border: none;
                border-right: 1px solid #404040;
                border-bottom: 1px solid #404040;
                font-weight: bold;
                font-size: 10px;
                text-transform: uppercase;
                letter-spacing: 0.5px;
            }
            
            QHeaderView::section:hover {
                background-color: #404040;
            }
            
            QHeaderView::section:pressed {
                background-color: #505050;
            }
            
            /* Scrollbar styling */
            QScrollBar:vertical {
                background-color: #2d2d2d;
                width: 12px;
                border-radius: 6px;
            }
            
            QScrollBar::handle:vertical {
                background-color: #505050;
                border-radius: 6px;
                min-height: 20px;
            }
            
            QScrollBar::handle:vertical:hover {
                background-color: #606060;
            }
            
            QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
                border: none;
                background: none;
            }
            
            QScrollBar:horizontal {
                background-color: #2d2d2d;
                height: 12px;
                border-radius: 6px;
            }
            
            QScrollBar::handle:horizontal {
                background-color: #505050;
                border-radius: 6px;
                min-width: 20px;
            }
            
            QScrollBar::handle:horizontal:hover {
                background-color: #606060;
            }
            
            QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal {
                border: none;
                background: none;
            }
        """)
        
        layout.addWidget(self.flows_table)
        
        # Compact status section
        self.status_label = QLabel("Chapter 10 flows (highlighted) show integrated signal plots • All columns are resizable")
        self.status_label.setStyleSheet("""
            QLabel {
                color: #888888;
                font-style: italic;
                padding: 4px 8px;
                font-size: 10px;
                background-color: #252525;
                border-radius: 4px;
            }
        """)
        self.status_label.setMaximumHeight(25)
        layout.addWidget(self.status_label)
        
        self.setLayout(layout)
    
    def set_analyzer(self, analyzer: 'EthernetAnalyzer'):
        """Set the analyzer and populate flow data"""
        self.analyzer = analyzer
        # Clear cache when analyzer changes
        self._signal_cache.clear()
        self.populate_flows_table()
    
    def update_file_info(self, file_path: str):
        """Update file information display"""
        if not self.analyzer:
            return
            
        summary = self.analyzer.get_summary()
        file_info = f"<b>File:</b> {os.path.basename(file_path)}<br/>"
        file_info += f"<b>Packets:</b> {summary['total_packets']:,}<br/>"
        file_info += f"<b>Flows:</b> {summary['unique_flows']}<br/>"
        file_info += f"<b>IPs:</b> {summary['unique_ips']}"
        self.file_info_label.setText(file_info)
    
    def populate_flows_table(self):
        """Populate the flows table with data"""
        if not self.analyzer:
            return
        
        summary = self.analyzer.get_summary()
        flows_list = list(summary['flows'].values())
        
        # Sort by maximum sigma deviation
        flows_list.sort(key=lambda x: (
            self.analyzer.statistics_engine.get_max_sigma_deviation(x),
            x.frame_count
        ), reverse=True)
        
        self.flows_table.setRowCount(len(flows_list))
        
        for row, flow in enumerate(flows_list):
            # Source IP (column 0)
            src_item = QTableWidgetItem(flow.src_ip)
            has_ch10 = any('CH10' in ft or 'TMATS' in ft for ft in flow.frame_types.keys())
            if has_ch10:
                font = QFont()
                font.setBold(True)
                src_item.setFont(font)
                src_item.setBackground(QColor(0, 120, 212, 80))  # Modern blue highlight
            src_item.setData(Qt.UserRole, flow)  # Store flow object
            self.flows_table.setItem(row, 0, src_item)
            
            # Destination IP (column 1)
            dst_item = QTableWidgetItem(flow.dst_ip)
            if has_ch10:
                font = QFont()
                font.setBold(True)
                dst_item.setFont(font)
                dst_item.setBackground(QColor(0, 120, 212, 80))  # Modern blue highlight
            self.flows_table.setItem(row, 1, dst_item)
            
            # Packets (column 2)
            packets_item = QTableWidgetItem(f"{flow.frame_count:,}")
            packets_item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
            self.flows_table.setItem(row, 2, packets_item)
            
            # Total Bytes (column 3)
            bytes_item = QTableWidgetItem(f"{flow.total_bytes:,}")
            bytes_item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
            self.flows_table.setItem(row, 3, bytes_item)
            
            # Max sigma deviation (column 4)
            max_sigma = self.analyzer.statistics_engine.get_max_sigma_deviation(flow)
            sigma_item = QTableWidgetItem(f"{max_sigma:.2f}σ")
            sigma_item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
            # Color code sigma values with modern colors
            if max_sigma > 5.0:
                sigma_item.setBackground(QColor(220, 53, 69, 120))  # Modern red for high sigma
                sigma_item.setForeground(QColor(255, 255, 255))  # White text for contrast
            elif max_sigma > 3.0:
                sigma_item.setBackground(QColor(255, 193, 7, 120))  # Modern amber for medium sigma
                sigma_item.setForeground(QColor(0, 0, 0))  # Black text for contrast
            self.flows_table.setItem(row, 4, sigma_item)
            
            # Average inter-arrival time (column 5)
            avg_time = f"{flow.avg_inter_arrival:.6f}s" if flow.avg_inter_arrival > 0 else "N/A"
            avg_item = QTableWidgetItem(avg_time)
            avg_item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
            self.flows_table.setItem(row, 5, avg_item)
            
            # Standard deviation (column 6)
            std_time = f"{flow.std_inter_arrival:.6f}s" if flow.std_inter_arrival > 0 else "N/A"
            std_item = QTableWidgetItem(std_time)
            std_item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
            self.flows_table.setItem(row, 6, std_item)
            
            # Outlier count (column 7)
            outlier_count = len(flow.outlier_frames)
            outlier_item = QTableWidgetItem(str(outlier_count))
            outlier_item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
            if outlier_count > 0:
                outlier_item.setBackground(QColor(220, 53, 69, 100))  # Modern red for outliers
                outlier_item.setForeground(QColor(255, 255, 255))  # White text for contrast
            self.flows_table.setItem(row, 7, outlier_item)
            
            # Protocols (column 8) - compact format
            protocols = []
            if flow.detected_protocol_types:
                protocols.extend(flow.detected_protocol_types)
            protocols.extend([p for p in flow.protocols if p not in protocols])
            protocols_text = ", ".join(protocols[:3])  # Limit to first 3 protocols
            if len(protocols) > 3:
                protocols_text += f" (+{len(protocols)-3})"
            protocols_item = QTableWidgetItem(protocols_text)
            self.flows_table.setItem(row, 8, protocols_item)
            
            # Signal plot column (column 9)
            if has_ch10:
                plot_widget = self._create_integrated_plot_widget(flow, f"{flow.src_ip} → {flow.dst_ip}")
                self.flows_table.setCellWidget(row, 9, plot_widget)
            else:
                plot_item = QTableWidgetItem("N/A")
                plot_item.setTextAlignment(Qt.AlignCenter)
                plot_item.setFlags(plot_item.flags() & ~Qt.ItemIsEditable)
                self.flows_table.setItem(row, 9, plot_item)
        
        # Auto-resize numeric columns to fit content
        for col in [2, 3, 4, 7]:  # Packets, Bytes, Max σ, Outliers
            self.flows_table.resizeColumnToContents(col)
        
        # Update header with time range information if we have flows
        self._update_signal_plot_header(flows_list)
    
    def populate_flows_table_quick(self):
        """Populate the flows table quickly without plots for immediate display"""
        if not self.analyzer:
            return
        
        summary = self.analyzer.get_summary()
        flows_list = list(summary['flows'].values())
        
        # Sort by maximum sigma deviation
        flows_list.sort(key=lambda x: (
            self.analyzer.statistics_engine.get_max_sigma_deviation(x),
            x.frame_count
        ), reverse=True)
        
        self.flows_table.setRowCount(len(flows_list))
        
        for row, flow in enumerate(flows_list):
            # Use same logic as populate_flows_table but with placeholder for plots
            has_ch10 = any('CH10' in ft or 'TMATS' in ft for ft in flow.frame_types.keys())
            
            # Source IP (column 0)
            src_item = QTableWidgetItem(flow.src_ip)
            if has_ch10:
                font = QFont()
                font.setBold(True)
                src_item.setFont(font)
                src_item.setBackground(QColor(0, 120, 212, 80))
            src_item.setData(Qt.UserRole, flow)
            self.flows_table.setItem(row, 0, src_item)
            
            # Destination IP (column 1)
            dst_item = QTableWidgetItem(flow.dst_ip)
            if has_ch10:
                font = QFont()
                font.setBold(True)
                dst_item.setFont(font)
                dst_item.setBackground(QColor(0, 120, 212, 80))
            self.flows_table.setItem(row, 1, dst_item)
            
            # Fill all other columns as in full populate method
            for col, value in [
                (2, f"{flow.frame_count:,}"),
                (3, f"{flow.total_bytes:,}"),
                (4, f"{self.analyzer.statistics_engine.get_max_sigma_deviation(flow):.2f}σ"),
                (5, f"{flow.avg_inter_arrival:.6f}s" if flow.avg_inter_arrival > 0 else "N/A"),
                (6, f"{flow.std_inter_arrival:.6f}s" if flow.std_inter_arrival > 0 else "N/A"),
                (7, str(len(flow.outlier_frames))),
                (8, ", ".join(list(flow.detected_protocol_types)[:2] if flow.detected_protocol_types else list(flow.protocols)[:2]))
            ]:
                item = QTableWidgetItem(value)
                if col in [2, 3, 4, 5, 6, 7]:  # Right-align numeric columns
                    item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
                self.flows_table.setItem(row, col, item)
            
            # Plot column placeholder
            if has_ch10:
                plot_item = QTableWidgetItem("Loading plot...")
                plot_item.setTextAlignment(Qt.AlignCenter)
                plot_item.setForeground(QColor(128, 128, 128))
                plot_item.setFlags(plot_item.flags() & ~Qt.ItemIsEditable)
                self.flows_table.setItem(row, 9, plot_item)
            else:
                plot_item = QTableWidgetItem("N/A")
                plot_item.setTextAlignment(Qt.AlignCenter)
                plot_item.setFlags(plot_item.flags() & ~Qt.ItemIsEditable)
                self.flows_table.setItem(row, 9, plot_item)
        
        # Auto-resize numeric columns to fit content
        for col in [2, 3, 4, 7]:  # Packets, Bytes, Max σ, Outliers
            self.flows_table.resizeColumnToContents(col)
    
    def _update_signal_plot_header(self, flows_list):
        """Update the Signal Plot column header with time range information"""
        if not flows_list or not self.analyzer:
            return
            
        # Find earliest and latest timestamps across all flows
        earliest_time = float('inf')
        latest_time = float('-inf')
        
        for flow in flows_list:
            if flow.timestamps:
                flow_start = min(flow.timestamps)
                flow_end = max(flow.timestamps)
                earliest_time = min(earliest_time, flow_start)
                latest_time = max(latest_time, flow_end)
        
        if earliest_time != float('inf') and latest_time != float('-inf'):
            # Convert timestamps to time-of-day format (assuming they're epoch seconds)
            import datetime
            try:
                start_time = datetime.datetime.fromtimestamp(earliest_time).strftime('%H:%M:%S')
                end_time = datetime.datetime.fromtimestamp(latest_time).strftime('%H:%M:%S')
                header_text = f"Signal Plot\n{start_time} → {end_time}"
            except (ValueError, OSError):
                # If timestamp conversion fails, show duration instead
                duration = latest_time - earliest_time
                header_text = f"Signal Plot\n{duration:.1f}s span"
        else:
            header_text = "Signal Plot"
        
        # Update the header
        self.flows_table.setHorizontalHeaderLabels([
            "Source IP", "Dest IP", "Pkts", "Bytes", "Max σ", "Avg ΔT", "Std ΔT", "Outliers", "Protocols", header_text
        ])
    
    def on_flow_selected(self):
        """Handle flow selection"""
        selected_rows = self.flows_table.selectionModel().selectedRows()
        
        if not selected_rows:
            self.status_label.setText("Chapter 10 flows (highlighted) show integrated signal plots • All columns are resizable")
            return
        
        # Get selected flow
        row = selected_rows[0].row()
        flow_item = self.flows_table.item(row, 0)
        flow = flow_item.data(Qt.UserRole)
        
        if flow:
            # Check if flow has Chapter 10 data
            has_ch10 = any('CH10' in ft or 'TMATS' in ft for ft in flow.frame_types.keys())
            
            if has_ch10:
                self.status_label.setText("Chapter 10 flow selected - signal plot shown in table")
            else:
                self.status_label.setText("Selected flow does not contain Chapter 10 telemetry data")
    
    def _create_integrated_plot_widget(self, flow: 'FlowStats', flow_key: str) -> QWidget:
        """Create a small matplotlib widget for integrated plots"""
        if not _ensure_matplotlib_gui_loaded():
            placeholder = QLabel("Matplotlib not available")
            placeholder.setAlignment(Qt.AlignCenter)
            return placeholder
        
        # Create a compact matplotlib widget
        plot_widget = QWidget()
        layout = QVBoxLayout()
        layout.setContentsMargins(2, 2, 2, 2)
        
        # Create wider figure for integrated display with dark theme
        figure = Figure(figsize=(8, 2.5), facecolor='#1e1e1e')  # Wider and slightly taller
        canvas = FigureCanvas(figure)
        canvas.setMaximumHeight(150)  # Increased height to match taller rows
        
        # Apply dark theme to matplotlib
        canvas.setStyleSheet("background-color: #1e1e1e; border: 1px solid #404040; border-radius: 4px;")
        
        layout.addWidget(canvas)
        plot_widget.setLayout(layout)
        
        # Load and plot data immediately
        self._populate_integrated_plot(figure, canvas, flow, flow_key)
        
        return plot_widget
    
    def _populate_integrated_plot(self, figure, canvas, flow: 'FlowStats', flow_key: str):
        """Populate an integrated plot with actual signal data"""
        try:
            if not self.analyzer:
                self._create_error_plot(figure, canvas, "No analyzer available")
                return
            
            # Check cache first
            cache_key = f"{flow.src_ip}_{flow.dst_ip}"
            if cache_key in self._signal_cache:
                signal_data_list = self._signal_cache[cache_key]
            else:
                # Get flow packets
                flow_packets = self._get_flow_packets(flow)
                
                if not flow_packets:
                    self._create_error_plot(figure, canvas, "No packets found")
                    return
                
                # Extract signal data using the same method as floating plots
                from ..utils.signal_visualizer import signal_visualizer
                
                # Extract TMATS metadata and signals
                tmats_metadata = signal_visualizer._extract_tmats_from_flow(flow_packets)
                signal_data_list = signal_visualizer._extract_signals_from_flow(flow_packets, tmats_metadata)
                
                # Cache the result
                self._signal_cache[cache_key] = signal_data_list
            
            if not signal_data_list:
                self._create_error_plot(figure, canvas, "No decodable\nsignal data")
                return
            
            # Plot the first signal with dark theme styling
            ax = figure.add_subplot(111, facecolor='#1e1e1e')
            
            # Use the first signal for the integrated plot
            signal_data = signal_data_list[0]
            
            # Plot the first channel in the signal
            if signal_data.channels:
                channel_name, data = next(iter(signal_data.channels.items()))
                
                # Downsample if too many points for integrated view
                timestamps = signal_data.timestamps
                if len(timestamps) > 200:
                    # Simple downsampling by taking every nth point
                    step = len(timestamps) // 200
                    timestamps = timestamps[::step]
                    data = data[::step]
                
                # Modern color scheme - blue for primary data
                ax.plot(timestamps, data, color='#0078d4', linewidth=1.2, alpha=0.9)
                
                # Dark theme styling with larger, more legible text
                ax.set_xlabel('Time (s)', fontsize=9, color='#ffffff')
                # ax.set_ylabel('Amplitude', fontsize=9, color='#ffffff')  # Removed for cleaner embedded view
                ax.tick_params(labelsize=8, colors='#cccccc', left=False, labelleft=False, bottom=False, labelbottom=False)  # Hide all tick labels
                ax.grid(True, alpha=0.15, color='#404040')
                
                # No legend needed for embedded plots - cleaner appearance
                
                # Add Y-axis min/max indicators for better readability
                y_min, y_max = ax.get_ylim()
                ax.text(0.02, 0.95, f'Max: {y_max:.2f}', transform=ax.transAxes, 
                       fontsize=7, color='#00ff88', weight='bold', 
                       bbox=dict(boxstyle='round,pad=0.2', facecolor='#2d2d2d', alpha=0.8))
                ax.text(0.02, 0.02, f'Min: {y_min:.2f}', transform=ax.transAxes, 
                       fontsize=7, color='#ff6b6b', weight='bold',
                       bbox=dict(boxstyle='round,pad=0.2', facecolor='#2d2d2d', alpha=0.8))
                
                # Style the spines
                for spine in ax.spines.values():
                    spine.set_color('#404040')
                    spine.set_linewidth(0.5)
                
                # Add compact title with time range info
                time_start = timestamps[0] if len(timestamps) > 0 else 0
                time_end = timestamps[-1] if len(timestamps) > 0 else 0
                duration = time_end - time_start
                
                title_text = f'{channel_name}'
                if len(signal_data_list) > 1:
                    title_text += f' (+{len(signal_data_list)-1} more)'
                title_text += f' | {duration:.2f}s span'
                
                ax.set_title(title_text, fontsize=8, color='#ffffff', pad=8)
                
            else:
                self._create_error_plot(figure, canvas, "No channel data")
                return
            
            # Maximum plot area with ultra-minimal margins on all sides
            figure.subplots_adjust(left=0.01, right=0.99, top=0.92, bottom=0.15)
            canvas.draw_idle()  # Use draw_idle to avoid window creation
            
        except Exception as e:
            self._create_error_plot(figure, canvas, f"Error:\n{str(e)[:30]}...")
    
    def _get_flow_packets(self, flow: 'FlowStats'):
        """Get all packets for a specific flow"""
        if not self.analyzer or not hasattr(self.analyzer, 'all_packets') or not self.analyzer.all_packets:
            return []
        
        flow_packets = []
        
        for packet in self.analyzer.all_packets:
            try:
                if hasattr(packet, 'haslayer'):
                    from scapy.all import IP
                    if packet.haslayer(IP):
                        ip_layer = packet[IP]
                        if ip_layer.src == flow.src_ip and ip_layer.dst == flow.dst_ip:
                            flow_packets.append(packet)
            except:
                continue
        
        return flow_packets
    
    def _create_error_plot(self, figure, canvas, message: str):
        """Create an error message plot with dark theme"""
        ax = figure.add_subplot(111, facecolor='#1e1e1e')
        ax.text(0.5, 0.5, message, 
               ha='center', va='center', transform=ax.transAxes, 
               fontsize=8, color='#ff6b6b', style='italic')  # Modern red for errors
        ax.set_xlim(0, 1)
        ax.set_ylim(0, 1)
        ax.axis('off')
        figure.subplots_adjust(left=0, right=1, top=1, bottom=0)
        canvas.draw_idle()  # Use draw_idle to avoid window creation




class FlowDetailDockWidget(QDockWidget):
    """Dockable widget showing detailed information about selected flow"""
    
    def __init__(self, parent=None):
        super().__init__("Flow Details", parent)
        
        # Create main widget
        main_widget = QWidget()
        layout = QVBoxLayout()
        
        # Detail text area with dark theme
        self.detail_text = QTextEdit()
        self.detail_text.setReadOnly(True)
        self.detail_text.setMaximumHeight(150)
        self.detail_text.setStyleSheet("""
            QTextEdit {
                background-color: #1e1e1e;
                color: #ffffff;
                border: 1px solid #404040;
                border-radius: 6px;
                padding: 8px;
                font-family: 'Monaco', 'Menlo', 'DejaVu Sans Mono', monospace;
                font-size: 11px;
                selection-background-color: #0078d4;
            }
        """)
        layout.addWidget(self.detail_text)
        
        main_widget.setLayout(layout)
        self.setWidget(main_widget)
        
        # Set dock properties
        self.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable)
        self.setAllowedAreas(Qt.BottomDockWidgetArea | Qt.TopDockWidgetArea)
        
        # Initial content with dark theme colors
        self.detail_text.setHtml('<span style="color: #888888; font-style: italic;">Select a flow to view detailed information</span>')
    
    def update_flow_details(self, flow: 'FlowStats', analyzer: 'EthernetAnalyzer'):
        """Update the detail view with flow information"""
        if not flow or not analyzer:
            self.detail_text.setHtml('<span style="color: #888888; font-style: italic;">No flow selected</span>')
            return
        
        max_sigma = analyzer.statistics_engine.get_max_sigma_deviation(flow)
        
        html = f"""
        <div style="color: #ffffff; font-family: 'Monaco', 'Menlo', 'DejaVu Sans Mono', monospace;">
        <h3 style="color: #0078d4; margin-bottom: 12px;">{flow.src_ip} → {flow.dst_ip}</h3>
        <table border="0" cellpadding="8" cellspacing="0" style="width: 100%; border-collapse: collapse;">
        <tr style="background-color: #2d2d2d;"><td style="color: #cccccc; font-weight: bold; border: 1px solid #404040;">Packets:</td><td style="color: #ffffff; border: 1px solid #404040;">{flow.frame_count:,}</td></tr>
        <tr style="background-color: #252525;"><td style="color: #cccccc; font-weight: bold; border: 1px solid #404040;">Total Bytes:</td><td style="color: #ffffff; border: 1px solid #404040;">{flow.total_bytes:,}</td></tr>
        <tr style="background-color: #2d2d2d;"><td style="color: #cccccc; font-weight: bold; border: 1px solid #404040;">Max Sigma Deviation:</td><td style="color: #ff6b6b; font-weight: bold; border: 1px solid #404040;">{max_sigma:.2f}σ</td></tr>
        <tr style="background-color: #252525;"><td style="color: #cccccc; font-weight: bold; border: 1px solid #404040;">Protocols:</td><td style="color: #ffffff; border: 1px solid #404040;">{', '.join(flow.protocols)}</td></tr>
        """
        
        if flow.detected_protocol_types:
            html += f'<tr style="background-color: #2d2d2d;"><td style="color: #cccccc; font-weight: bold; border: 1px solid #404040;">Enhanced Protocols:</td><td style="color: #ffffff; border: 1px solid #404040;">{", ".join(flow.detected_protocol_types)}</td></tr>'
        
        if flow.avg_inter_arrival > 0:
            html += f"""
            <tr style="background-color: #252525;"><td style="color: #cccccc; font-weight: bold; border: 1px solid #404040;">Avg Inter-arrival:</td><td style="color: #ffffff; border: 1px solid #404040;">{flow.avg_inter_arrival:.6f}s</td></tr>
            <tr style="background-color: #2d2d2d;"><td style="color: #cccccc; font-weight: bold; border: 1px solid #404040;">Std Deviation:</td><td style="color: #ffffff; border: 1px solid #404040;">{flow.std_inter_arrival:.6f}s</td></tr>
            """
        
        if flow.outlier_frames:
            html += f'<tr style="background-color: #252525;"><td style="color: #cccccc; font-weight: bold; border: 1px solid #404040;">Outlier Frames:</td><td style="color: #ff6b6b; font-weight: bold; border: 1px solid #404040;">{len(flow.outlier_frames)}</td></tr>'
        
        html += "</table>"
        
        # Frame type breakdown
        if flow.frame_types:
            html += '<h4 style="color: #0078d4; margin-top: 16px; margin-bottom: 8px;">Frame Types:</h4>'
            html += '<ul style="list-style-type: none; padding-left: 0;">'
            for frame_type, ft_stats in flow.frame_types.items():
                avg_str = f"{ft_stats.avg_inter_arrival:.3f}s" if ft_stats.avg_inter_arrival > 0 else "N/A"
                html += f'<li style="margin-bottom: 4px; padding: 4px 8px; background-color: #252525; border-radius: 4px; border-left: 3px solid #0078d4;"><span style="color: #cccccc; font-weight: bold;">{frame_type}:</span> <span style="color: #ffffff;">{ft_stats.count} packets, avg {avg_str}</span></li>'
            html += "</ul>"
        
        html += "</div>"
        
        self.detail_text.setHtml(html)