from PySide6.QtWidgets import (
    QWidget, QVBoxLayout, QHBoxLayout, QLabel, 
    QGroupBox, QPushButton, QScrollArea, QSplitter
)
from PySide6.QtCore import Qt, Slot
from PySide6.QtCharts import QChart, QChartView, QLineSeries, QPieSeries, QBarSeries, QBarSet, QBarCategoryAxis, QScatterSeries, QValueAxis
from PySide6.QtGui import QPainter, QColor, QPen, QFont, QBrush, QLinearGradient, QGradient

class ChartWidget(QWidget):
    """Base widget for analytics charts"""
    def __init__(self, title):
        super().__init__()
        self.layout = QVBoxLayout(self)
        self.layout.setContentsMargins(0, 0, 0, 0)
        
        # Chart title
        self.title_label = QLabel(title)
        self.title_label.setAlignment(Qt.AlignCenter)
        self.title_label.setStyleSheet("font-weight: bold; font-size: 14px;")
        self.layout.addWidget(self.title_label)
        
        # Create chart
        self.chart = QChart()        
        self.chart.setAnimationOptions(QChart.SeriesAnimations)
        self.chart.setBackgroundBrush(QBrush(QColor(240, 240, 240)))
        self.chart.legend().setVisible(True)
        self.chart.legend().setAlignment(Qt.AlignBottom)
        
        # Chart view
        self.chartview = QChartView(self.chart)
        self.chartview.setRenderHint(QPainter.RenderHint.Antialiasing)
        self.layout.addWidget(self.chartview)
        
        self.setMinimumSize(400, 300)

class TimeSeriesChart(ChartWidget):
    """Time series chart for traffic data"""
    def __init__(self, title="Traffic Over Time"):
        super().__init__(title)
        
        # Create series
        self.vehicle_series = QLineSeries()
        self.vehicle_series.setName("Vehicles")
        self.vehicle_series.setPen(QPen(QColor(0, 162, 232), 2))
        
        self.pedestrian_series = QLineSeries()
        self.pedestrian_series.setName("Pedestrians")
        self.pedestrian_series.setPen(QPen(QColor(255, 140, 0), 2))
        
        self.violation_series = QLineSeries()
        self.violation_series.setName("Violations")
        self.violation_series.setPen(QPen(QColor(232, 0, 0), 2))
        
        self.traffic_light_color_series = QLineSeries()
        self.traffic_light_color_series.setName("Traffic Light Color")
        self.traffic_light_color_series.setPen(QPen(QColor(128, 0, 128), 2, Qt.DashLine))
        
        # Add series to chart
        self.chart.addSeries(self.vehicle_series)
        self.chart.addSeries(self.pedestrian_series)
        self.chart.addSeries(self.violation_series)
        self.chart.addSeries(self.traffic_light_color_series)
        
        # Create and configure axes
        self.chart.createDefaultAxes()
        x_axis = self.chart.axes(Qt.Horizontal)[0]
        x_axis.setTitleText("Time")
        x_axis.setGridLineVisible(True)
        x_axis.setLabelsAngle(45)
        
        y_axis = self.chart.axes(Qt.Vertical)[0]
        y_axis.setTitleText("Count")
        y_axis.setGridLineVisible(True)
        
    def update_data(self, time_series):
        """Update chart with new time series data"""
        try:
            if not time_series or 'timestamps' not in time_series:
                return
                
            # Check if chart and series are still valid
            if not hasattr(self, 'chart') or self.chart is None:
                return
            if not hasattr(self, 'vehicle_series') or self.vehicle_series is None:
                return
                
            timestamps = time_series.get('timestamps', [])
            vehicle_counts = time_series.get('vehicle_counts', [])
            pedestrian_counts = time_series.get('pedestrian_counts', [])
            violation_counts = time_series.get('violation_counts', [])
            traffic_light_colors = time_series.get('traffic_light_colors', [])
            
            # Clear existing series safely
            try:
                self.vehicle_series.clear()
                self.pedestrian_series.clear()
                self.violation_series.clear()
                self.traffic_light_color_series.clear()
            except RuntimeError:
                # C++ object was already deleted, skip update
                return
            
            # Add data points
            for i in range(len(timestamps)):
                try:
                    # Add x as index, y as count
                    self.vehicle_series.append(i, vehicle_counts[i] if i < len(vehicle_counts) else 0)
                    self.pedestrian_series.append(i, pedestrian_counts[i] if i < len(pedestrian_counts) else 0)
                    self.violation_series.append(i, violation_counts[i] if i < len(violation_counts) else 0)
                    
                    # Add traffic light color as mapped int for charting (0=unknown, 1=red, 2=yellow, 3=green)
                    if i < len(traffic_light_colors):
                        color_map = {'unknown': 0, 'red': 1, 'yellow': 2, 'green': 3}
                        color_val = color_map.get(traffic_light_colors[i], 0)
                        self.traffic_light_color_series.append(i, color_val)
                except RuntimeError:
                    # C++ object was deleted during update
                    return
            
            # Update axes safely
            try:
                axes = self.chart.axes(Qt.Horizontal)
                if axes:
                    axes[0].setRange(0, max(len(timestamps)-1, 10))
                
                max_count = max(
                    max(vehicle_counts) if vehicle_counts else 0,
                    max(pedestrian_counts) if pedestrian_counts else 0,
                    max(violation_counts) if violation_counts else 0
                )
                axes = self.chart.axes(Qt.Vertical)
                if axes:
                    axes[0].setRange(0, max(max_count+1, 5))
            except (RuntimeError, IndexError):
                # Chart axes were deleted or not available
                pass
            
            # Optionally, set y-axis label for traffic light color
            axes = self.chart.axes(Qt.Vertical)
            if axes:
                axes[0].setTitleText("Count / TL Color (0=U,1=R,2=Y,3=G)")
        except Exception as e:
            print(f"[WARNING] Chart update failed: {e}")

class DetectionPieChart(ChartWidget):
    """Pie chart for detected object classes"""
    def __init__(self, title="Detection Classes"):
        super().__init__(title)
        
        self.pie_series = QPieSeries()
        self.chart.addSeries(self.pie_series)
        
    def update_data(self, detection_counts):
        """Update chart with detection counts"""
        try:
            if not detection_counts:
                return
                
            # Check if chart and series are still valid
            if not hasattr(self, 'chart') or self.chart is None:
                return
            if not hasattr(self, 'pie_series') or self.pie_series is None:
                return
                
            # Clear existing slices safely
            try:
                self.pie_series.clear()
            except RuntimeError:
                # C++ object was already deleted, skip update
                return
            
            # Add new slices
            for class_name, count in detection_counts.items():
                # Only add if count > 0
                if count > 0:
                    try:
                        slice = self.pie_series.append(class_name, count)
                        
                        # Set colors based on class
                        if class_name.lower() == 'car':
                            slice.setBrush(QColor(0, 200, 0))
                        elif class_name.lower() == 'person':
                            slice.setBrush(QColor(255, 165, 0))
                        elif class_name.lower() == 'truck':
                            slice.setBrush(QColor(0, 100, 200))
                        elif class_name.lower() == 'bus':
                            slice.setBrush(QColor(200, 0, 100))
                        
                        # Highlight important slices
                        if count > 10:
                            slice.setExploded(True)
                            slice.setLabelVisible(True)
                    except RuntimeError:
                        # C++ object was deleted during update
                        return
        except Exception as e:
            print(f"[WARNING] Pie chart update failed: {e}")

class ViolationBarChart(ChartWidget):
    """Bar chart for violation types"""
    def __init__(self, title="Violations by Type"):
        super().__init__(title)
        
        # Create series
        self.bar_series = QBarSeries()
        self.chart.addSeries(self.bar_series)
        
        # Create axes
        self.axis_x = QBarCategoryAxis()
        self.chart.addAxis(self.axis_x, Qt.AlignBottom)
        self.bar_series.attachAxis(self.axis_x)
        
        self.chart.createDefaultAxes()
        self.chart.axes(Qt.Vertical)[0].setTitleText("Count")
        
    def update_data(self, violation_counts):
        """Update chart with violation counts"""
        try:
            if not violation_counts:
                return
                
            # Check if chart and series are still valid
            if not hasattr(self, 'chart') or self.chart is None:
                return
            if not hasattr(self, 'bar_series') or self.bar_series is None:
                return
            if not hasattr(self, 'axis_x') or self.axis_x is None:
                return
                
            # Clear existing data safely
            try:
                self.bar_series.clear()
            except RuntimeError:
                # C++ object was already deleted, skip update
                return
            
            # Create bar set
            bar_set = QBarSet("Violations")
            
            # Set colors
            try:
                bar_set.setColor(QColor(232, 0, 0))
            except RuntimeError:
                return
            
            # Add values
            values = []
            categories = []
            
            for violation_type, count in violation_counts.items():
                if count > 0:
                    values.append(count)
                    # Format violation type for display
                    display_name = violation_type.replace('_', ' ').title()
                    categories.append(display_name)
            
            if values:
                try:
                    bar_set.append(values)
                    self.bar_series.append(bar_set)
                    
                    # Update x-axis categories
                    self.axis_x.setCategories(categories)
                    
                    # Update y-axis range
                    y_axes = self.chart.axes(Qt.Vertical)
                    if y_axes:
                        y_axes[0].setRange(0, max(values) * 1.2)
                except RuntimeError:
                    # C++ object was deleted during update
                    return
        except Exception as e:
            print(f"[WARNING] Bar chart update failed: {e}")

class LatencyChartWidget(ChartWidget):
    """Custom latency chart with spikes, device/res changes, and live stats legend."""
    def __init__(self, title="Inference Latency Over Time"):
        super().__init__(title)
        self.chart.setBackgroundBrush(QBrush(QColor(24, 28, 32)))
        self.title_label.setStyleSheet("font-weight: bold; font-size: 16px; color: #fff;")
        self.chart.legend().setVisible(False)
        # Main latency line
        self.latency_series = QLineSeries()
        self.latency_series.setName("Latency (ms)")
        self.latency_series.setPen(QPen(QColor(0, 255, 255), 2))
        self.chart.addSeries(self.latency_series)
        # Spikes as red dots
        self.spike_series = QScatterSeries()
        self.spike_series.setName("Spikes")
        self.spike_series.setMarkerSize(8)
        self.spike_series.setColor(QColor(255, 64, 64))
        self.chart.addSeries(self.spike_series)
        # Device/resolution change lines (vertical)
        self.event_lines = []
        # Axes
        self.chart.createDefaultAxes()
        self.x_axis = self.chart.axes(Qt.Horizontal)[0]
        self.x_axis.setTitleText("")
        self.x_axis.setLabelsColor(QColor("#fff"))
        self.x_axis.setGridLineColor(QColor("#444"))
        self.y_axis = self.chart.axes(Qt.Vertical)[0]
        self.y_axis.setTitleText("ms")
        self.y_axis.setLabelsColor(QColor("#fff"))
        self.y_axis.setGridLineColor(QColor("#444"))
        # Stats label
        self.stats_label = QLabel()
        self.stats_label.setStyleSheet("color: #00e6ff; font-size: 13px; font-weight: bold; margin: 2px 0 0 8px;")
        self.layout.addWidget(self.stats_label)

    def update_data(self, latency_data):
        """
        latency_data: dict with keys:
            'latencies': list of float,
            'spike_indices': list of int,
            'device_switches': list of int,
            'resolution_changes': list of int
        """
        if not latency_data or 'latencies' not in latency_data:
            return
        latencies = latency_data.get('latencies', [])
        spikes = set(latency_data.get('spike_indices', []))
        device_switches = set(latency_data.get('device_switches', []))
        res_changes = set(latency_data.get('resolution_changes', []))
        # Clear series
        self.latency_series.clear()
        self.spike_series.clear()
        # Remove old event lines
        for line in self.event_lines:
            self.chart.removeAxis(line)
        self.event_lines = []
        # Plot latency and spikes
        for i, val in enumerate(latencies):
            self.latency_series.append(i, val)
            if i in spikes:
                self.spike_series.append(i, val)
        # Add device/resolution change lines
        for idx in device_switches:
            line = QLineSeries()
            line.setPen(QPen(QColor(33, 150, 243), 3))  # Blue
            line.append(idx, min(latencies) if latencies else 0)
            line.append(idx, max(latencies) if latencies else 1)
            self.chart.addSeries(line)
            line.attachAxis(self.x_axis)
            line.attachAxis(self.y_axis)
            self.event_lines.append(line)
        for idx in res_changes:
            line = QLineSeries()
            line.setPen(QPen(QColor(255, 167, 38), 3))  # Orange
            line.append(idx, min(latencies) if latencies else 0)
            line.append(idx, max(latencies) if latencies else 1)
            self.chart.addSeries(line)
            line.attachAxis(self.x_axis)
            line.attachAxis(self.y_axis)
            self.event_lines.append(line)
        # Update axes
        self.x_axis.setRange(0, max(len(latencies)-1, 10))
        self.y_axis.setRange(0, max(max(latencies) if latencies else 1, 10))
        # Stats
        if latencies:
            avg = sum(latencies)/len(latencies)
            mx = max(latencies)
            self.stats_label.setText(f"Avg: {avg:.1f}ms | Max: {mx:.1f}ms | Spikes: {len(spikes)}")
        else:
            self.stats_label.setText("")

class FPSChartWidget(ChartWidget):
    """FPS & Resolution Impact chart with device/resolution change lines and live stats."""
    def __init__(self, title="FPS & Resolution Impact"):
        super().__init__(title)
        self.chart.setBackgroundBrush(QBrush(QColor(24, 28, 32)))
        self.title_label.setStyleSheet("font-weight: bold; font-size: 16px; color: #fff;")
        self.chart.legend().setVisible(False)
        self.fps_series = QLineSeries()
        self.fps_series.setName("FPS")
        self.fps_series.setPen(QPen(QColor(0, 255, 255), 2))
        self.chart.addSeries(self.fps_series)
        self.event_lines = []
        self.chart.createDefaultAxes()
        self.x_axis = self.chart.axes(Qt.Horizontal)[0]
        self.x_axis.setLabelsColor(QColor("#fff"))
        self.x_axis.setGridLineColor(QColor("#444"))
        self.y_axis = self.chart.axes(Qt.Vertical)[0]
        self.y_axis.setTitleText("FPS")
        self.y_axis.setLabelsColor(QColor("#fff"))
        self.y_axis.setGridLineColor(QColor("#444"))
        self.stats_label = QLabel()
        self.stats_label.setStyleSheet("color: #00ff82; font-size: 13px; font-weight: bold; margin: 2px 0 0 8px;")
        self.layout.addWidget(self.stats_label)
    def update_data(self, fps_data):
        if not fps_data or 'fps' not in fps_data:
            return
        fps = fps_data.get('fps', [])
        device_switches = set(fps_data.get('device_switches', []))
        res_changes = set(fps_data.get('resolution_changes', []))
        device_labels = fps_data.get('device_labels', {})
        res_labels = fps_data.get('resolution_labels', {})
        self.fps_series.clear()
        for line in self.event_lines:
            self.chart.removeAxis(line)
        self.event_lines = []
        for i, val in enumerate(fps):
            self.fps_series.append(i, val)
        for idx in device_switches:
            line = QLineSeries()
            line.setPen(QPen(QColor(33, 150, 243), 3))
            line.append(idx, min(fps) if fps else 0)
            line.append(idx, max(fps) if fps else 1)
            self.chart.addSeries(line)
            line.attachAxis(self.x_axis)
            line.attachAxis(self.y_axis)
            self.event_lines.append(line)
        for idx in res_changes:
            line = QLineSeries()
            line.setPen(QPen(QColor(255, 167, 38), 3))
            line.append(idx, min(fps) if fps else 0)
            line.append(idx, max(fps) if fps else 1)
            self.chart.addSeries(line)
            line.attachAxis(self.x_axis)
            line.attachAxis(self.y_axis)
            self.event_lines.append(line)
        self.x_axis.setRange(0, max(len(fps)-1, 10))
        self.y_axis.setRange(0, max(max(fps) if fps else 1, 10))
        # Live stats (current FPS, resolution, device)
        cur_fps = fps[-1] if fps else 0
        cur_res = res_labels.get(len(fps)-1, "-")
        cur_dev = device_labels.get(len(fps)-1, "-")
        self.stats_label.setText(f"Current FPS: {cur_fps:.1f} | Resolution: {cur_res} | Device: {cur_dev}")

class DeviceSwitchChartWidget(ChartWidget):
    """Device Switching & Resolution Changes chart with colored vertical lines and legend."""
    def __init__(self, title="Device Switching & Resolution Changes"):
        super().__init__(title)
        self.chart.setBackgroundBrush(QBrush(QColor(24, 28, 32)))
        self.title_label.setStyleSheet("font-weight: bold; font-size: 16px; color: #fff;")
        self.chart.legend().setVisible(False)
        self.event_lines = []
        self.chart.createDefaultAxes()
        self.x_axis = self.chart.axes(Qt.Horizontal)[0]
        self.x_axis.setLabelsColor(QColor("#fff"))
        self.x_axis.setGridLineColor(QColor("#444"))
        self.y_axis = self.chart.axes(Qt.Vertical)[0]
        self.y_axis.setTitleText("-")
        self.y_axis.setLabelsColor(QColor("#fff"))
        self.y_axis.setGridLineColor(QColor("#444"))
        self.legend_label = QLabel()
        self.legend_label.setStyleSheet("color: #ffb300; font-size: 13px; font-weight: bold; margin: 2px 0 0 8px;")
        self.layout.addWidget(self.legend_label)
    def update_data(self, event_data):
        if not event_data:
            return
        cpu_spikes = set(event_data.get('cpu_spikes', []))
        gpu_spikes = set(event_data.get('gpu_spikes', []))
        switches = set(event_data.get('switches', []))
        res_changes = set(event_data.get('res_changes', []))
        n = event_data.get('n', 100)
        for line in self.event_lines:
            self.chart.removeAxis(line)
        self.event_lines = []
        for idx in cpu_spikes:
            line = QLineSeries()
            line.setPen(QPen(QColor(255, 64, 64), 2))
            line.append(idx, 0)
            line.append(idx, 1)
            self.chart.addSeries(line)
            line.attachAxis(self.x_axis)
            line.attachAxis(self.y_axis)
            self.event_lines.append(line)
        for idx in gpu_spikes:
            line = QLineSeries()
            line.setPen(QPen(QColor(255, 87, 34), 2))
            line.append(idx, 0)
            line.append(idx, 1)
            self.chart.addSeries(line)
            line.attachAxis(self.x_axis)
            line.attachAxis(self.y_axis)
            self.event_lines.append(line)
        for idx in switches:
            line = QLineSeries()
            line.setPen(QPen(QColor(33, 150, 243), 2))
            line.append(idx, 0)
            line.append(idx, 1)
            self.chart.addSeries(line)
            line.attachAxis(self.x_axis)
            line.attachAxis(self.y_axis)
            self.event_lines.append(line)
        for idx in res_changes:
            line = QLineSeries()
            line.setPen(QPen(QColor(255, 167, 38), 2))
            line.append(idx, 0)
            line.append(idx, 1)
            self.chart.addSeries(line)
            line.attachAxis(self.x_axis)
            line.attachAxis(self.y_axis)
            self.event_lines.append(line)
        self.x_axis.setRange(0, n)
        self.y_axis.setRange(0, 1)
        self.legend_label.setText("<span style='color:#ff4444;'>CPU Spikes</span>: {} | <span style='color:#ff5722;'>GPU Spikes</span>: {} | <span style='color:#2196f3;'>Switches</span>: {} | <span style='color:#ffa726;'>Res Changes</span>: {}".format(len(cpu_spikes), len(gpu_spikes), len(switches), len(res_changes)))

class AnalyticsTab(QWidget):
    """Analytics tab with charts and statistics"""
    
    def __init__(self):
        super().__init__()
        self.initUI()
        
    def initUI(self):
        """Initialize UI components"""
        main_layout = QVBoxLayout(self)
        
        # Add notice that violations are disabled
        notice_label = QLabel("⚠️ Violation detection is currently disabled. Only object detection statistics will be shown.")
        notice_label.setStyleSheet("font-size: 14px; color: #FFA500; font-weight: bold; padding: 10px;")
        notice_label.setAlignment(Qt.AlignCenter)
        main_layout.addWidget(notice_label)
        
        # Charts section
        charts_splitter = QSplitter(Qt.Horizontal)
        
        # Latency chart (top, full width)
        self.latency_chart = LatencyChartWidget("Inference Latency Over Time")
        main_layout.addWidget(self.latency_chart)
        
        # Left side - Time series chart
        self.time_series_chart = TimeSeriesChart("Traffic Over Time")
        charts_splitter.addWidget(self.time_series_chart)
        
        # Right side - Detection and violation charts
        right_charts = QWidget()
        right_layout = QVBoxLayout(right_charts)
        
        self.detection_chart = DetectionPieChart("Detection Classes")
        self.violation_chart = ViolationBarChart("Violations by Type")
        
        right_layout.addWidget(self.detection_chart)
        right_layout.addWidget(self.violation_chart)
        
        charts_splitter.addWidget(right_charts)
        charts_splitter.setSizes([500, 500])  # Equal initial sizes
        
        main_layout.addWidget(charts_splitter)
        
        # Key metrics section
        metrics_box = QGroupBox("Key Metrics")
        metrics_layout = QHBoxLayout(metrics_box)
        
        # Vehicle metrics
        vehicle_metrics = QGroupBox("Traffic")
        vehicle_layout = QVBoxLayout(vehicle_metrics)
        self.total_vehicles_label = QLabel("Total Vehicles: 0")
        self.total_pedestrians_label = QLabel("Total Pedestrians: 0")
        vehicle_layout.addWidget(self.total_vehicles_label)
        vehicle_layout.addWidget(self.total_pedestrians_label)
        metrics_layout.addWidget(vehicle_metrics)
        
        # Violation metrics
        violation_metrics = QGroupBox("Violations")
        violation_layout = QVBoxLayout(violation_metrics)
        self.total_violations_label = QLabel("Total Violations: 0")
        self.peak_violation_label = QLabel("Peak Violation Hour: --")
        violation_layout.addWidget(self.total_violations_label)
        violation_layout.addWidget(self.peak_violation_label)
        metrics_layout.addWidget(violation_metrics)
        
        # Performance metrics
        performance_metrics = QGroupBox("Performance")
        performance_layout = QVBoxLayout(performance_metrics)
        self.avg_fps_label = QLabel("Avg FPS: 0")
        self.avg_processing_label = QLabel("Avg Processing Time: 0 ms")
        performance_layout.addWidget(self.avg_fps_label)
        performance_layout.addWidget(self.avg_processing_label)
        metrics_layout.addWidget(performance_metrics)
        
        main_layout.addWidget(metrics_box)
        
        # Controls
        controls = QHBoxLayout()
        self.reset_btn = QPushButton("Reset Statistics")
        controls.addWidget(self.reset_btn)
        controls.addStretch(1)  # Push button to left
        
        main_layout.addLayout(controls)
    
    @Slot(dict)
    def update_analytics(self, analytics):
        """
        Update analytics display with new data.
        
        Args:
            analytics: Dictionary of analytics data
        """
        try:
            if not analytics:
                return
                
            # Update latency chart
            try:
                if hasattr(self, 'latency_chart') and self.latency_chart is not None:
                    self.latency_chart.update_data(analytics.get('latency', {}))
            except Exception as e:
                print(f"[WARNING] Latency chart update failed: {e}")
            
            # Update charts with error handling
            try:
                if hasattr(self, 'time_series_chart') and self.time_series_chart is not None:
                    self.time_series_chart.update_data(analytics.get('time_series', {}))
            except Exception as e:
                print(f"[WARNING] Time series chart update failed: {e}")
                
            try:
                if hasattr(self, 'detection_chart') and self.detection_chart is not None:
                    self.detection_chart.update_data(analytics.get('detection_counts', {}))
            except Exception as e:
                print(f"[WARNING] Detection chart update failed: {e}")
                
            try:
                if hasattr(self, 'violation_chart') and self.violation_chart is not None:
                    self.violation_chart.update_data(analytics.get('violation_counts', {}))
            except Exception as e:
                print(f"[WARNING] Violation chart update failed: {e}")
            
            # Update metrics
            try:
                metrics = analytics.get('metrics', {})
                
                if hasattr(self, 'total_vehicles_label'):
                    self.total_vehicles_label.setText(f"Total Vehicles: {metrics.get('total_vehicles', 0)}")
                if hasattr(self, 'total_pedestrians_label'):
                    self.total_pedestrians_label.setText(f"Total Pedestrians: {metrics.get('total_pedestrians', 0)}")
                
                if hasattr(self, 'total_violations_label'):
                    self.total_violations_label.setText(f"Total Violations: {metrics.get('total_violations', 0)}")
                
                peak_hour = metrics.get('peak_violation_hour')
                if peak_hour:
                    peak_text = f"Peak Violation Hour: {peak_hour.get('time', '--')} ({peak_hour.get('violations', 0)})"
                else:
                    peak_text = "Peak Violation Hour: --"
                if hasattr(self, 'peak_violation_label'):
                    self.peak_violation_label.setText(peak_text)
                
                if hasattr(self, 'avg_fps_label'):
                    self.avg_fps_label.setText(f"Avg FPS: {metrics.get('avg_fps', 0):.1f}")
                if hasattr(self, 'avg_processing_label'):
                    self.avg_processing_label.setText(
                        f"Avg Processing Time: {metrics.get('avg_processing_time', 0):.1f} ms"
                    )
            except Exception as e:
                print(f"[WARNING] Metrics update failed: {e}")
                
            # Update traffic light label with latest color
            try:
                tl_series = analytics.get('traffic_light_color_series', [])
                if tl_series:
                    latest = tl_series[-1][1]
                    self.traffic_light_label.setText(f"Traffic Light: {latest.title()}")
                else:
                    self.traffic_light_label.setText("Traffic Light: Unknown")
            except Exception as e:
                print(f"[WARNING] Traffic light label update failed: {e}")
                
        except Exception as e:
            print(f"[ERROR] Analytics update failed: {e}")
