import time
import tkinter as tk
from tkinter import ttk
import win32com.client as com
from UCwinRoadUtils import AsF8COMdVec3
from LoggerProxy import LoggerProxy
from UCwinRoadCOM import UCwinRoadComProxy

from .scenario import RushHourScenario
from . import handlers


class RibbonUI:
    def __init__(self, winRoadProxy: UCwinRoadComProxy, logProxy: LoggerProxy) -> None:
        self.winRoadProxy = winRoadProxy
        self.logProxy = logProxy
        self.EventList = []
        self.scenario = RushHourScenario(winRoadProxy, logProxy)
        # Warm caches for models and accident assets once at startup
        try:
            self.scenario.warm_cache_models()
            self.scenario.warm_accident_assets()
            self.scenario.warm_emergency_vehicle()
        except Exception:
            pass

        self.tk_root = tk.Tk()
        self.tk_root.withdraw()
        self.tk_root.after(33, self._tick_loop)
        self.env_window_manager = None

    # Camera helpers
    def _set_camera(self, eye, view_point):
        try:
            const = self.winRoadProxy.const
            camState = com.Dispatch('UCwinRoad.F8COMMainCameraStateType')
            camState.allowUnderTerrain = True
            camState.cameraMode = const._useTiltAng
            camState.eye = eye
            camState.ViewPoint = view_point
            camState.tiltAngle = 0
            mainCamera = self.winRoadProxy.MainForm.MainCamera
            mainCamera.MainCameraState = camState
        except Exception as e:
            self.logProxy.logger.error(f"_set_camera failed: {e}")

    def camera_go_to_accident(self):
        try:
            if not hasattr(self, 'accident_pos') or self.accident_pos is None:
                self.scenario_status_label.config(text="No accident position stored")
                # Show error popup
                self.scenario.show_operation_complete_popup(
                    "Camera Operation Failed",
                    "No accident position available.\n\nPlease create an accident first.",
                    success=False
                )
                return

            # Show progress popup for camera operation
            popup, progress_var = self.scenario.show_progress_popup(
                "📹 Moving Camera",
                "Positioning camera at accident location...",
                duration_ms=2000
            )

            pos = self.accident_pos
            cam = self.winRoadProxy.MainForm.MainCamera
            camState = cam.MainCameraState
            view = camState.ViewPoint
            eye = camState.eye
            dirx, dirz = (view.X - eye.X), (view.Z - eye.Z)
            norm = max((dirx*dirx + dirz*dirz) ** 0.5, 1e-6)
            dirx /= norm; dirz /= norm
            back = 25.0; up = 12.0
            new_eye = AsF8COMdVec3(pos.X - dirx * back, pos.Y + up, pos.Z - dirz * back)
            self._set_camera(new_eye, AsF8COMdVec3(pos.X, pos.Y, pos.Z))

            # Close progress popup and show completion
            if popup:
                popup.destroy()
            self.scenario.show_operation_complete_popup(
                "Camera Moved",
                "📹 Camera positioned at accident location!\n\nReady for emergency response.",
                success=True
            )

        except Exception as e:
            self.logProxy.logger.error(f"camera_go_to_accident failed: {e}")
            # Close progress popup on error
            if popup:
                popup.destroy()
            self.scenario.show_operation_complete_popup(
                "Camera Operation Failed",
                f"Failed to move camera: {str(e)}",
                success=False
            )

    # Analysis
    def update_analysis(self):
        """Update traffic analysis using advanced academic metrics"""
        try:
            # Show progress popup for traffic analysis
            popup, progress_var = self.scenario.show_progress_popup(
                "📊 Analyzing Traffic",
                "Collecting traffic data and performing analysis...",
                duration_ms=5000
            )

            # Import the advanced traffic analysis module
            from .traffic_analysis import AdvancedTrafficAnalyzer, TrafficReportGenerator

            # Initialize analyzer if not exists
            if not hasattr(self, 'traffic_analyzer'):
                self.traffic_analyzer = AdvancedTrafficAnalyzer(self.winRoadProxy, self.logProxy)

            self.scenario.update_progress_popup(progress_var, "Checking simulation state...")
            # Check for basic requirements
            prj = self.winRoadProxy.Project
            traffic = self.winRoadProxy.ApplicationServices.SimulationCore.TrafficSimulation

            # Check total vehicles in the simulation
            vehs = traffic.GetTransientVehiclesArround(1000, self.winRoadProxy.MainForm.MainCamera.MainCameraState.eye)
            total_vehicles = getattr(vehs, 'Count', 0)
            self.logProxy.logger.info(f"Total vehicles in simulation area: {total_vehicles}")

            # Check roads count
            roads_count = getattr(prj, 'RoadsCount', 0)
            self.logProxy.logger.info(f"Total roads in project: {roads_count}")

            if total_vehicles == 0:
                self.logProxy.logger.warning("No vehicles found in simulation area")
                # Create empty network metrics for display
                from .traffic_analysis import NetworkMetrics
                empty_metrics = NetworkMetrics(0, 0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0.0, 0.0)
                self._update_analysis_display_advanced({}, empty_metrics)
                return
            if roads_count == 0:
                self.logProxy.logger.warning("No roads found in project")
                # Create empty network metrics for display
                from .traffic_analysis import NetworkMetrics
                empty_metrics = NetworkMetrics(0, 0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0.0, 0.0)
                self._update_analysis_display_advanced({}, empty_metrics)
                return

            self.scenario.update_progress_popup(progress_var, "Performing comprehensive analysis...")
            # Perform comprehensive analysis
            self.logProxy.logger.info("Starting comprehensive traffic analysis...")
            road_metrics, network_metrics = self.traffic_analyzer.analyze_road_network()

            self.scenario.update_progress_popup(progress_var, "Processing analysis results...")
            self.logProxy.logger.info(f"Analysis complete. Roads analyzed: {len(road_metrics) if road_metrics else 0}")

            if not road_metrics:
                self.logProxy.logger.warning("No road metrics generated")
                # Ensure we have valid network metrics
                if network_metrics is None:
                    from .traffic_analysis import NetworkMetrics
                    network_metrics = NetworkMetrics(0, 0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0.0, 0.0)
                self._update_analysis_display_advanced({}, network_metrics)

                # Close progress popup and show completion
                if popup:
                    popup.destroy()
                self.scenario.show_operation_complete_popup(
                    "Traffic Analysis Complete",
                    "No vehicles found in simulation area.\n\nPlease ensure traffic is running and vehicles are present.",
                    success=True
                )
                return

            # Store metrics for report generation
            self.road_metrics = road_metrics
            self.network_metrics = network_metrics

            self.scenario.update_progress_popup(progress_var, "Updating display...")
            # Update the display with comprehensive metrics
            self._update_analysis_display_advanced(road_metrics, network_metrics)
            self.logProxy.logger.info("Traffic analysis display updated successfully")

            # Close progress popup and show completion
            if popup:
                popup.destroy()

            analysis_type = "FAST" if (hasattr(self, 'traffic_analyzer') and getattr(self.traffic_analyzer, 'fast_mode', False)) else "DETAILED"
            self.scenario.show_operation_complete_popup(
                "Traffic Analysis Complete",
                f"{analysis_type} analysis completed successfully!\n\n"
                f"📊 Roads analyzed: {len(road_metrics)}\n"
                f"🚗 Total vehicles: {sum(m.vehicle_count for m in road_metrics.values())}\n\n"
                f"📈 Check the detailed tabs for comprehensive metrics.",
                success=True
            )

        except Exception as e:
            self.logProxy.logger.error(f"update_analysis failed: {e}")
            # Close progress popup on error
            if popup:
                popup.destroy()
            self.scenario.show_operation_complete_popup(
                "Traffic Analysis Failed",
                f"Failed to perform traffic analysis: {str(e)}\n\nAttempting basic analysis...",
                success=False
            )
            # Fallback to basic analysis
            try:
                self._update_analysis_basic()
            except Exception as fallback_e:
                self.logProxy.logger.error(f"Fallback analysis also failed: {fallback_e}")

    def _update_analysis_fast(self):
        """Fast traffic analysis with reduced sampling for quick results"""
        try:
            # Import the advanced traffic analysis module
            from .traffic_analysis import AdvancedTrafficAnalyzer, TrafficReportGenerator

            # Initialize analyzer if not exists
            if not hasattr(self, 'traffic_analyzer'):
                self.traffic_analyzer = AdvancedTrafficAnalyzer(self.winRoadProxy, self.logProxy)

            # Enable fast mode
            if hasattr(self.traffic_analyzer, 'fast_mode'):
                self.traffic_analyzer.fast_mode = True

            # Debug: Check if we have roads and vehicles
            try:
                prj = self.winRoadProxy.Project
                traffic = self.winRoadProxy.ApplicationServices.SimulationCore.TrafficSimulation

                vehs = traffic.GetTransientVehiclesArround(1000, self.winRoadProxy.MainForm.MainCamera.MainCameraState.eye)
                total_vehicles = getattr(vehs, 'Count', 0)
                roads_count = getattr(prj, 'RoadsCount', 0)

                if total_vehicles == 0:
                    self.logProxy.logger.warning("No vehicles found in simulation area")
                    from .traffic_analysis import NetworkMetrics
                    empty_metrics = NetworkMetrics(0, 0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0.0, 0.0)
                    self._update_analysis_display_advanced({}, empty_metrics)
                    return
                if roads_count == 0:
                    self.logProxy.logger.warning("No roads found in project")
                    from .traffic_analysis import NetworkMetrics
                    empty_metrics = NetworkMetrics(0, 0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0.0, 0.0)
                    self._update_analysis_display_advanced({}, empty_metrics)
                    return

            except Exception as debug_e:
                self.logProxy.logger.error(f"Debug check failed: {debug_e}")

            # Perform fast comprehensive analysis
            self.logProxy.logger.info("Starting FAST traffic analysis...")
            road_metrics, network_metrics = self.traffic_analyzer.analyze_road_network()

            self.logProxy.logger.info(f"Fast analysis complete. Roads analyzed: {len(road_metrics) if road_metrics else 0}")

            if not road_metrics:
                self.logProxy.logger.warning("No road metrics generated")
                if network_metrics is None:
                    from .traffic_analysis import NetworkMetrics
                    network_metrics = NetworkMetrics(0, 0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0.0, 0.0)
                self._update_analysis_display_advanced({}, network_metrics)
                return

            # Store metrics for report generation
            self.road_metrics = road_metrics
            self.network_metrics = network_metrics

            # Update the display with comprehensive metrics
            self._update_analysis_display_advanced(road_metrics, network_metrics)
            self.logProxy.logger.info("Fast traffic analysis display updated successfully")

            # Show success feedback
            try:
                from tkinter import messagebox
                if hasattr(self, 'analysis_window') and self.analysis_window.winfo_exists():
                    messagebox.showinfo("Fast Analysis Complete",
                                      f"⚡ Fast analysis completed!\n\n"
                                      f"• Roads analyzed: {len(road_metrics)}\n"
                                      f"• Total vehicles: {sum(m.vehicle_count for m in road_metrics.values())}\n\n"
                                      f"Use 'Refresh Analysis' for detailed results.",
                                      parent=self.analysis_window)
            except Exception as msg_e:
                self.logProxy.logger.warning(f"Could not show success message: {msg_e}")

            # Reset fast mode
            if hasattr(self.traffic_analyzer, 'fast_mode'):
                self.traffic_analyzer.fast_mode = False

        except Exception as e:
            self.logProxy.logger.error(f"_update_analysis_fast failed: {e}")
            # Reset fast mode on error
            if hasattr(self, 'traffic_analyzer') and hasattr(self.traffic_analyzer, 'fast_mode'):
                self.traffic_analyzer.fast_mode = False
    
    def _update_analysis_basic(self):
        """Fallback basic traffic analysis"""
        try:
            traffic = self.winRoadProxy.ApplicationServices.SimulationCore.TrafficSimulation
            const = self.winRoadProxy.const
            cam = self.winRoadProxy.MainForm.MainCamera
            center = cam.MainCameraState.eye
            
            # Get vehicles in a larger radius for better analysis
            vehs = traffic.GetTransientVehiclesArround(800, center)
            total = getattr(vehs, 'Count', 0)
            
            if total <= 0:
                self._update_analysis_display(0, 0.0, 0.0, 0.0, 0.0, 0.0)
                return
            
            # Sample vehicles for analysis (max 300 for performance)
            step = max(1, total // 300)
            speeds = []
            count = 0

            for i in range(0, total, step):
                v = vehs.Items(i)
                if not v:
                    continue
                try:
                    speed = v.Speed(const._KiloMeterPerHour)
                    speeds.append(speed)
                    count += 1
                except Exception:
                    pass
            
            if count == 0:
                self._update_analysis_display(total, 0.0, 0.0, 0.0, 0.0, 0.0)
                return
            
            # Calculate basic metrics
            avg_speed = sum(speeds) / len(speeds)
            max_speed = max(speeds)
            min_speed = min(speeds)
            
            # Basic congestion calculation
            speed_factor = max(0, (60 - avg_speed) / 60.0)
            congestion = min(1.0, max(0.0, speed_factor))
            flow_efficiency = count * avg_speed
            
            self._update_analysis_display(total, avg_speed, max_speed, min_speed, congestion, flow_efficiency)
            
        except Exception as e:
            self.logProxy.logger.error(f"_update_analysis_basic failed: {e}")
    
    def _update_analysis_display_advanced(self, road_metrics, network_metrics):
        """Update analysis display with advanced academic metrics"""
        try:
            # Handle case where network_metrics is None
            if network_metrics is None:
                from .traffic_analysis import NetworkMetrics
                network_metrics = NetworkMetrics(0, 0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0.0, 0.0)

            if not road_metrics:
                # No data available
                if hasattr(self, 'vehicle_count_label'):
                    self.vehicle_count_label.config(text="Active Vehicles: 0")
                if hasattr(self, 'avg_speed_label'):
                    self.avg_speed_label.config(text="Average Speed: -- km/h")
                if hasattr(self, 'speed_range_label'):
                    self.speed_range_label.config(text="Speed Range: -- km/h")
                if hasattr(self, 'congestion_label'):
                    self.congestion_label.config(text="Congestion Level: --")
                if hasattr(self, 'flow_efficiency_label'):
                    self.flow_efficiency_label.config(text="Flow Efficiency: --")
                return

            # Calculate network totals
            total_vehicles = sum(m.vehicle_count for m in road_metrics.values())
            avg_speed = network_metrics.network_avg_speed
            max_speed = max(m.avg_speed for m in road_metrics.values())
            min_speed = min(m.avg_speed for m in road_metrics.values())

            # Calculate congestion level
            congested_roads = sum(1 for m in road_metrics.values()
                                if m.level_of_service.value in ['E', 'F'])
            congestion_rate = (congested_roads / len(road_metrics)) * 100

            # Calculate flow efficiency
            total_flow = sum(m.flow_rate for m in road_metrics.values())
            flow_efficiency = sum(m.flow_rate * m.avg_speed for m in road_metrics.values())

            # Update basic display
            if hasattr(self, 'vehicle_count_label'):
                self.vehicle_count_label.config(text=f"Active Vehicles: {total_vehicles}")
            if hasattr(self, 'avg_speed_label'):
                self.avg_speed_label.config(text=f"Average Speed: {avg_speed:.1f} km/h")
            if hasattr(self, 'speed_range_label'):
                self.speed_range_label.config(text=f"Speed Range: {min_speed:.1f}-{max_speed:.1f} km/h")
            if hasattr(self, 'congestion_label'):
                self.congestion_label.config(text=f"Congestion Level: {congestion_rate:.1f}% ({congested_roads}/{len(road_metrics)} roads)")
            if hasattr(self, 'flow_efficiency_label'):
                self.flow_efficiency_label.config(text=f"Flow Efficiency: {flow_efficiency:.0f}")

            # Update detailed per-road display if available
            self._update_detailed_road_analysis(road_metrics, network_metrics)

        except Exception as e:
            self.logProxy.logger.error(f"_update_analysis_display_advanced failed: {e}")
    
    def _update_detailed_road_analysis(self, road_metrics, network_metrics):
        """Update detailed per-road analysis display"""
        try:
            # This will be called by the enhanced traffic analysis window
            if hasattr(self, 'detailed_road_analysis_callback'):
                self.detailed_road_analysis_callback(road_metrics, network_metrics)
        except Exception as e:
            self.logProxy.logger.error(f"_update_detailed_road_analysis failed: {e}")
    
    def _update_detailed_analysis_display(self, road_metrics, network_metrics):
        """Update the detailed analysis display with comprehensive metrics"""
        try:
            if not hasattr(self, 'analysis_window') or not road_metrics:
                return
            
            # Update network overview
            if hasattr(self, 'network_roads_label'):
                self.network_roads_label.config(text=f"Total Roads: {network_metrics.total_roads}")
            if hasattr(self, 'network_vehicles_label'):
                self.network_vehicles_label.config(text=f"Total Vehicles: {network_metrics.total_vehicles}")
            if hasattr(self, 'network_avg_speed_label'):
                self.network_avg_speed_label.config(text=f"Network Avg Speed: {network_metrics.network_avg_speed:.1f} km/h")
            if hasattr(self, 'network_delay_label'):
                self.network_delay_label.config(text=f"Total Delay: {network_metrics.network_delay:.2f} veh-h")
            if hasattr(self, 'congestion_rate_label'):
                congestion_rate = (network_metrics.congested_roads / network_metrics.total_roads * 100) if network_metrics.total_roads > 0 else 0
                self.congestion_rate_label.config(text=f"Congestion Rate: {congestion_rate:.1f}%")
            if hasattr(self, 'safety_rate_label'):
                self.safety_rate_label.config(text=f"Safety Violations: {network_metrics.speed_violation_rate*100:.1f}%")
            
            # Update per-road treeview
            if hasattr(self, 'roads_tree'):
                # Clear existing items
                for item in self.roads_tree.get_children():
                    self.roads_tree.delete(item)
                
                # Add road data
                for road_name, metrics in road_metrics.items():
                    self.roads_tree.insert('', 'end', values=(
                        road_name[:20] + '...' if len(road_name) > 20 else road_name,
                        metrics.vehicle_count,
                        f"{metrics.avg_speed:.1f}",
                        metrics.level_of_service.value,
                        f"{metrics.flow_rate:.0f}",
                        f"{metrics.density:.1f}",
                        f"{metrics.delay_per_vehicle:.1f}s",
                        f"{metrics.flow_rate * metrics.avg_speed:.0f}"
                    ))
            
            # Update detailed analysis tabs
            self._update_analysis_tabs(road_metrics, network_metrics)
            
        except Exception as e:
            self.logProxy.logger.error(f"_update_detailed_analysis_display failed: {e}")
    
    def _update_analysis_tabs(self, road_metrics, network_metrics):
        """Update the detailed analysis tabs with comprehensive metrics"""
        try:
            # Speed Analysis Tab
            if hasattr(self, 'speed_metrics_text'):
                speed_text = "=== SPEED ANALYSIS ===\n\n"
                speed_text += f"Network Average Speed: {network_metrics.network_avg_speed:.1f} km/h\n"
                speed_text += f"Speed Range: {min(m.avg_speed for m in road_metrics.values()):.1f} - {max(m.avg_speed for m in road_metrics.values()):.1f} km/h\n\n"
                
                speed_text += "Per-Road Speed Analysis:\n"
                speed_text += "-" * 50 + "\n"
                for road_name, metrics in sorted(road_metrics.items(), key=lambda x: x[1].avg_speed, reverse=True):
                    speed_text += f"{road_name}:\n"
                    speed_text += f"  • Average: {metrics.avg_speed:.1f} km/h\n"
                    speed_text += f"  • 85th Percentile: {metrics.speed_85th_percentile:.1f} km/h\n"
                    speed_text += f"  • 15th Percentile: {metrics.speed_15th_percentile:.1f} km/h\n"
                    speed_text += f"  • Std Deviation: {metrics.speed_std:.1f} km/h\n"
                    speed_text += f"  • Coefficient of Variation: {metrics.coefficient_of_variation:.3f}\n\n"
                
                self.speed_metrics_text.delete(1.0, tk.END)
                self.speed_metrics_text.insert(1.0, speed_text)
            
            # Flow Analysis Tab
            if hasattr(self, 'flow_metrics_text'):
                flow_text = "=== FLOW ANALYSIS ===\n\n"
                total_flow = sum(m.flow_rate for m in road_metrics.values())
                flow_text += f"Total Network Flow: {total_flow:.0f} veh/h\n"
                flow_text += f"Network Efficiency: {network_metrics.network_efficiency:.0f}\n\n"
                
                flow_text += "Per-Road Flow Analysis:\n"
                flow_text += "-" * 50 + "\n"
                for road_name, metrics in sorted(road_metrics.items(), key=lambda x: x[1].flow_rate, reverse=True):
                    flow_text += f"{road_name}:\n"
                    flow_text += f"  • Flow Rate: {metrics.flow_rate:.0f} veh/h\n"
                    flow_text += f"  • Density: {metrics.density:.1f} veh/km\n"
                    flow_text += f"  • Occupancy: {metrics.occupancy:.1f}%\n"
                    flow_text += f"  • Capacity: {metrics.capacity:.0f} veh/h\n"
                    flow_text += f"  • V/C Ratio: {metrics.vc_ratio:.3f}\n"
                    flow_text += f"  • Level of Service: {metrics.level_of_service.value}\n\n"
                
                self.flow_metrics_text.delete(1.0, tk.END)
                self.flow_metrics_text.insert(1.0, flow_text)
            
            # Safety Analysis Tab
            if hasattr(self, 'safety_metrics_text'):
                safety_text = "=== SAFETY ANALYSIS ===\n\n"
                safety_text += f"Speed Violation Rate: {network_metrics.speed_violation_rate*100:.1f}%\n"
                safety_text += f"Aggressive Driving Rate: {network_metrics.aggressive_driving_rate*100:.1f}%\n\n"
                
                safety_text += "Per-Road Safety Analysis:\n"
                safety_text += "-" * 50 + "\n"
                for road_name, metrics in sorted(road_metrics.items(), key=lambda x: x[1].coefficient_of_variation, reverse=True):
                    safety_text += f"{road_name}:\n"
                    safety_text += f"  • Speed Variance: {metrics.speed_variance:.1f}\n"
                    safety_text += f"  • Speed Differential: {metrics.speed_differential:.1f} km/h\n"
                    safety_text += f"  • Coefficient of Variation: {metrics.coefficient_of_variation:.3f}\n"
                    safety_text += f"  • Safety Rating: {'High Risk' if metrics.coefficient_of_variation > 0.3 else 'Moderate Risk' if metrics.coefficient_of_variation > 0.2 else 'Low Risk'}\n\n"
                
                self.safety_metrics_text.delete(1.0, tk.END)
                self.safety_metrics_text.insert(1.0, safety_text)
            
            # Environmental Analysis Tab
            if hasattr(self, 'env_metrics_text'):
                env_text = "=== ENVIRONMENTAL ANALYSIS ===\n\n"
                total_fuel = sum(m.fuel_consumption_rate * m.vehicle_count for m in road_metrics.values())
                total_emissions = sum(m.emissions_factor * m.vehicle_count for m in road_metrics.values())
                env_text += f"Total Fuel Consumption: {total_fuel:.1f} L/h\n"
                env_text += f"Total Emissions: {total_emissions:.0f} g CO2/h\n\n"
                
                env_text += "Per-Road Environmental Analysis:\n"
                env_text += "-" * 50 + "\n"
                for road_name, metrics in sorted(road_metrics.items(), key=lambda x: x[1].fuel_consumption_rate, reverse=True):
                    env_text += f"{road_name}:\n"
                    env_text += f"  • Fuel Consumption: {metrics.fuel_consumption_rate:.1f} L/100km\n"
                    env_text += f"  • Emissions Factor: {metrics.emissions_factor:.0f} g CO2/km\n"
                    env_text += f"  • Environmental Impact: {'High' if metrics.fuel_consumption_rate > 10 else 'Moderate' if metrics.fuel_consumption_rate > 8 else 'Low'}\n\n"
                
                self.env_metrics_text.delete(1.0, tk.END)
                self.env_metrics_text.insert(1.0, env_text)
                
        except Exception as e:
            self.logProxy.logger.error(f"_update_analysis_tabs failed: {e}")
    
    def _run_traffic_diagnostics(self):
        """Run diagnostics to check traffic analysis functionality"""
        try:
            from tkinter import messagebox

            diagnostics = []
            diagnostics.append("=== TRAFFIC ANALYSIS DIAGNOSTICS ===\n")

            # Check UC-win/Road connection
            try:
                prj = self.winRoadProxy.Project
                diagnostics.append("✓ UC-win/Road project connection: OK")
                roads_count = getattr(prj, 'RoadsCount', 0)
                diagnostics.append(f"✓ Roads in project: {roads_count}")
            except Exception as e:
                diagnostics.append(f"✗ UC-win/Road connection failed: {e}")
                messagebox.showerror("Diagnostics", "\n".join(diagnostics))
                return

            # Check traffic simulation
            try:
                traffic = self.winRoadProxy.ApplicationServices.SimulationCore.TrafficSimulation
                diagnostics.append("✓ Traffic simulation access: OK")
            except Exception as e:
                diagnostics.append(f"✗ Traffic simulation access failed: {e}")
                messagebox.showerror("Diagnostics", "\n".join(diagnostics))
                return

            # Check camera position
            try:
                cam = self.winRoadProxy.MainForm.MainCamera
                center = cam.MainCameraState.eye
                diagnostics.append(f"✓ Camera position: ({center.X:.1f}, {center.Y:.1f}, {center.Z:.1f})")
            except Exception as e:
                diagnostics.append(f"✗ Camera access failed: {e}")

            # Check for vehicles in area
            try:
                vehs = traffic.GetTransientVehiclesArround(1000, center)
                total_vehicles = getattr(vehs, 'Count', 0)
                diagnostics.append(f"✓ Vehicles in 1km radius: {total_vehicles}")

                if total_vehicles == 0:
                    diagnostics.append("\n⚠️ WARNING: No vehicles found in simulation area!")
                    diagnostics.append("   This could be because:")
                    diagnostics.append("   • No vehicles are spawned in the simulation")
                    diagnostics.append("   • Vehicles are outside the camera view area")
                    diagnostics.append("   • The simulation is not running")
                    diagnostics.append("   • Camera is positioned too far from roads")
                else:
                    diagnostics.append("   ✓ Vehicles detected - analysis should work!")
            except Exception as e:
                diagnostics.append(f"✗ Vehicle count check failed: {e}")

            # Check available traffic methods
            try:
                # Check if GetTransientVehiclesOnRoad method exists
                has_road_method = hasattr(traffic, 'GetTransientVehiclesOnRoad')
                diagnostics.append(f"{'✓' if has_road_method else '⚠️'} Road-specific vehicle method available: {has_road_method}")

                if not has_road_method:
                    diagnostics.append("   → Will use road-segment sampling with GetPositionAt")
                    diagnostics.append("   → This provides accurate road-specific traffic analysis")
                    diagnostics.append("   → Samples vehicles at multiple points along each road")
                    diagnostics.append("   → Use 'Fast Analysis' for quick results, 'Refresh Analysis' for detailed")

                # Try to get road attributes for debugging
                if roads_count > 0:
                    try:
                        first_road = prj.Road(0)
                        road_attrs = [attr for attr in dir(first_road) if not attr.startswith('_') and not callable(getattr(first_road, attr))]
                        position_attrs = [attr for attr in ['Position', 'Center', 'StartPoint', 'EndPoint', 'Length', 'GetPositionAt'] if hasattr(first_road, attr)]
                        diagnostics.append(f"✓ Road object has position attributes: {position_attrs}")
                        if 'GetPositionAt' in position_attrs:
                            diagnostics.append("   → GetPositionAt available - road-specific analysis will work!")
                        elif not position_attrs:
                            diagnostics.append("   → Road position detection may be limited")
                    except Exception as road_e:
                        diagnostics.append(f"⚠️ Could not inspect road attributes: {road_e}")

            except Exception as e:
                diagnostics.append(f"✗ Method check failed: {e}")

            # Check traffic analysis module
            try:
                from .traffic_analysis import AdvancedTrafficAnalyzer
                diagnostics.append("✓ Traffic analysis module import: OK")
            except Exception as e:
                diagnostics.append(f"✗ Traffic analysis module import failed: {e}")

            # Show diagnostics
            diagnostics.append("\n=== RECOMMENDATIONS ===")
            if total_vehicles == 0:
                diagnostics.append("• Make sure vehicles are spawned in the simulation")
                diagnostics.append("• Position camera closer to active roads")
                diagnostics.append("• Ensure simulation is running and vehicles are moving")
            else:
                diagnostics.append("• Traffic analysis should work with current setup")
                diagnostics.append("• Try clicking 'Refresh Analysis' to see results")
                diagnostics.append("• If analysis fails, area-based fallback will be used")

            messagebox.showinfo("Traffic Diagnostics", "\n".join(diagnostics),
                              parent=self.analysis_window if hasattr(self, 'analysis_window') else None)

        except Exception as e:
            self.logProxy.logger.error(f"_run_traffic_diagnostics failed: {e}")
            try:
                from tkinter import messagebox
                messagebox.showerror("Diagnostics Error", f"Diagnostics failed: {e}")
            except:
                pass

    def _generate_traffic_report(self):
        """Generate comprehensive traffic analysis report"""
        try:
            from .traffic_analysis import TrafficReportGenerator

            if not hasattr(self, 'traffic_analyzer') or not hasattr(self, 'road_metrics'):
                self.logProxy.logger.warning("No traffic data available for report generation")
                return

            # Get current metrics
            road_metrics = getattr(self, 'road_metrics', {})
            network_metrics = getattr(self, 'network_metrics', None)

            if not road_metrics:
                self.logProxy.logger.warning("No road metrics available for report generation")
                return

            # Generate reports
            report_text = "=== COMPREHENSIVE TRAFFIC ANALYSIS REPORT ===\n\n"
            report_text += f"Generated: {time.strftime('%Y-%m-%d %H:%M:%S')}\n\n"

            # Network summary
            if network_metrics:
                report_text += TrafficReportGenerator.generate_network_summary(road_metrics, network_metrics)
                report_text += "\n\n"

            # Individual road reports
            report_text += "=== INDIVIDUAL ROAD REPORTS ===\n\n"
            for road_name, metrics in road_metrics.items():
                report_text += TrafficReportGenerator.generate_road_report(metrics)
                report_text += "\n" + "="*60 + "\n\n"

            # Save report to file
            report_filename = f"traffic_analysis_report_{time.strftime('%Y%m%d_%H%M%S')}.txt"
            try:
                with open(report_filename, 'w', encoding='utf-8') as f:
                    f.write(report_text)
                self.logProxy.logger.info(f"Traffic analysis report saved to: {report_filename}")

                # Show success message
                from tkinter import messagebox
                messagebox.showinfo("Report Generated", f"Traffic analysis report saved to:\n{report_filename}")
            except Exception as e:
                self.logProxy.logger.error(f"Failed to save report: {e}")
                messagebox.showerror("Error", f"Failed to save report: {e}")

        except Exception as e:
            self.logProxy.logger.error(f"_generate_traffic_report failed: {e}")
    
    def _update_analysis_display(self, total, avg_speed, max_speed, min_speed, congestion, flow_efficiency):
        """Update the analysis display with calculated metrics."""
        try:
            if hasattr(self, 'vehicle_count_label'):
                self.vehicle_count_label.config(text=f"Active Vehicles: {total}")
            
            if hasattr(self, 'avg_speed_label'):
                self.avg_speed_label.config(text=f"Avg Speed: {avg_speed:.1f} km/h")
            
            if hasattr(self, 'congestion_label'):
                # Color-code congestion level
                if congestion < 0.3:
                    color = "green"
                    level = "Low"
                elif congestion < 0.6:
                    color = "orange"
                    level = "Medium"
                else:
                    color = "red"
                    level = "High"
                
                self.congestion_label.config(
                    text=f"Congestion: {level} ({congestion:.2f})",
                    foreground=color
                )
            
            # Add new metrics if labels exist
            if hasattr(self, 'speed_range_label'):
                self.speed_range_label.config(text=f"Speed Range: {min_speed:.1f} - {max_speed:.1f} km/h")
            
            if hasattr(self, 'flow_efficiency_label'):
                self.flow_efficiency_label.config(text=f"Flow Efficiency: {flow_efficiency:.0f}")
                
        except Exception as e:
            self.logProxy.logger.error(f"_update_analysis_display failed: {e}")

    def tick(self):
        try:
            now = time.perf_counter()
            # Emergency follow camera if requested (further reduced rate to limit COM load)
            if (
                hasattr(self, 'follow_emergency_var') and self.follow_emergency_var.get() and
                getattr(self, 'scenario', None) is not None and
                getattr(self.scenario, 'emg_car', None) is not None and
                self.scenario.emg_active and
                now - getattr(self, '_last_follow_update', 0.0) > 1.0/8.0
            ):
                try:
                    car = self.scenario.emg_car
                    pos = car.Position
                    dirv = getattr(car, 'BodyDirection', None) or getattr(car, 'Direction', None)
                    back = 18.0; up = 9.0
                    if dirv is not None:
                        eye = AsF8COMdVec3(pos.X - dirv.X * back, pos.Y + up, pos.Z - dirv.Z * back)
                        tgt = AsF8COMdVec3(pos.X + dirv.X * 8.0, pos.Y + 2.0, pos.Z + dirv.Z * 8.0)
                    else:
                        eye = AsF8COMdVec3(pos.X - 15.0, pos.Y + up, pos.Z - 15.0)
                        tgt = AsF8COMdVec3(pos.X, pos.Y + 2.0, pos.Z)
                    self._set_camera(eye, tgt)
                except Exception:
                    pass
                self._last_follow_update = now

            # Emergency game status polling and display
            try:
                if getattr(self, 'scenarios_window', None) is not None and getattr(self.scenario, 'emg_active', False):
                    # Poll every 3 seconds while emergency game is active
                    last_status_time = getattr(self, '_last_emg_status', 0.0)
                    time_since_last_poll = now - last_status_time

                    if time_since_last_poll > 3.0:  # Poll every 3 seconds
                        st = self.scenario.poll_emergency_game()
                        self._last_emg_status = now
                        if st and st.get('arrived', False):
                            # User has arrived - automatically reset the emergency game
                            self.logProxy.logger.info("Emergency game completed - user reached destination, resetting game")
                            self.scenario.reset_emergency_game()
                            st = None  # Don't display status after reset
                    else:
                        st = None
                    if st:
                        driving = '✅ Yes' if st['driving'] else '❌ No'
                        elapsed = st['elapsed']
                        mm = int(elapsed // 60); ss = int(elapsed % 60)
                        player_name = st.get('player_name', 'Player')
                        
                        # Better status display
                        if st['arrived']:
                            reached_accident = getattr(self.scenario, 'emg_reached_accident', 'Unknown')
                            txt = f"🎯 {player_name}: ARRIVED at {reached_accident}! Final Time: {mm:02d}:{ss:02d}"
                        else:
                            txt = f"🚑 {player_name}: Driving={driving}  Time={mm:02d}:{ss:02d}"
                            
                        if hasattr(self, 'emg_status'):
                            self.emg_status.config(text=txt)
            except Exception:
                pass

            # Check for completed simulation and update progress popup
            try:
                if (hasattr(self.scenario, '_simulation_completed') and
                    self.scenario._simulation_completed and
                    hasattr(self.scenario, '_current_progress_popup') and
                    self.scenario._current_progress_popup is not None):

                    # Update progress popup with completion message
                    if hasattr(self.scenario, '_current_progress_var') and self.scenario._current_progress_var:
                        try:
                            self.scenario.update_progress_popup(
                                self.scenario._current_progress_var,
                                "Traffic generation completed successfully!"
                            )
                        except Exception as e:
                            self.logProxy.logger.warning(f"Could not update progress: {e}")

                    # Close popup after a brief delay
                    def close_popup():
                        try:
                            if (hasattr(self.scenario, '_current_progress_popup') and
                                self.scenario._current_progress_popup):
                                self.scenario._current_progress_popup.destroy()
                                self.scenario._current_progress_popup = None
                                self.scenario._current_progress_var = None
                        except Exception as e:
                            self.logProxy.logger.warning(f"Could not close progress popup: {e}")

                    # Schedule popup closure
                    try:
                        if self.scenario._current_progress_popup:
                            self.scenario._current_progress_popup.after(2000, close_popup)
                    except Exception as e:
                        self.logProxy.logger.warning(f"Could not schedule popup closure: {e}")

                    # Show completion message
                    try:
                        if self.scenario._simulation_success:
                            self.scenario.show_operation_complete_popup(
                                "Traffic Generation Complete",
                                "✅ Successfully generated traffic simulation!\n\nTraffic is now running.",
                                success=True
                            )
                        else:
                            self.scenario.show_operation_complete_popup(
                                "Traffic Generation Failed",
                                "❌ Traffic generation encountered errors.\n\nCheck logs for details.",
                                success=False
                            )
                    except Exception as e:
                        self.logProxy.logger.warning(f"Could not show completion popup: {e}")

                    # Reset completion flags
                    self.scenario._simulation_completed = False
                    self.scenario._simulation_success = False

            except Exception as e:
                self.logProxy.logger.warning(f"Error checking simulation completion: {e}")

            # Analysis: only update on user request (no background polling)
            # if a Refresh button is present, it calls update_analysis() directly

        except Exception:
            pass

    def _tick_loop(self):
        try:
            self.tick()
        except Exception:
            pass
        finally:
            try:
                self.tk_root.after(33, self._tick_loop)
            except Exception:
                pass

    # Utility: go to a road by name (used by scenarios window)
    def _go_to_road_by_name(self, target_name: str):
        try:
            prj = self.winRoadProxy.Project
            road = None
            for i in range(prj.RoadsCount):
                r = prj.Road(i)
                if r.Name == target_name:
                    road = r; break
            if not road:
                return
            dist = float(getattr(road, 'Length', 100.0) * 0.5)
            pos = road.GetPositionAt(dist)
            dirv = road.GetDirectionAt(dist)
            back = 20.0; up = 10.0
            eye = AsF8COMdVec3(pos.X - dirv.X * back, pos.Y + up, pos.Z - dirv.Z * back)
            self._set_camera(eye, AsF8COMdVec3(pos.X, pos.Y, pos.Z))
        except Exception as e:
            self.logProxy.logger.error(f"_go_to_road_by_name failed: {e}")

    # Ribbon UI creation helpers
    def MakeRibbonTab(self, Parent, partsName, caption):
        if Parent is not None:
            tab = Parent.GetTabByName(partsName)
            if tab is None:
                tab = Parent.CreateTab(partsName, 10000)
                tab.Caption = caption
            return tab
        return None

    def MakeRibbonGroup(self, Parent, partsName, caption):
        if Parent is not None:
            group = Parent.GetGroupByName(partsName)
            if group is None:
                group = Parent.CreateGroup(partsName, 100)
                group.Caption = caption
            return group
        return None

    def DeleteControlFromParent(self, child, Parent):
        if child is not None:
            try:
                child.UnRegisterEventHandlers()
            except Exception:
                pass
            if Parent is not None:
                try:
                    Parent.DeleteControl(child)
                except Exception:
                    pass

    def CloseCallbackEvent(self):
        if self.EventList is not None:
            for Event in self.EventList:
                try:
                    Event.close()
                except Exception:
                    pass
            self.EventList.clear()

    def SetCallbackEvent(self, button, handler):
        if button is not None:
            isValue = button.IsSetCallbackOnClick()
            if isValue == False:
                Event = com.WithEvents(button, handler)
                Event.SetCOMEventClass(Event)
                button.RegisterEventHandlers()
                if not hasattr(self, 'EventList'):
                    self.EventList = []
                self.EventList.append(Event)
                return Event
        return None

    def MakeRibbonButton(self, Parent, partsName, caption, handler):
        if Parent is not None:
            button = Parent.GetControlByName(partsName)
            if button is None:
                button = Parent.CreateButton(partsName)
                button.Caption = caption
            self.SetCallbackEvent(button, handler)
            return button
        return None

    def MakeRibbonUI(self):
        mainForm = self.winRoadProxy.MainForm
        self.ribbonMenu = mainForm.MainRibbonMenu
        self.ribbonTab = self.MakeRibbonTab(self.ribbonMenu, 'TrafficScenarios', 'Traffic Scenarios')

        self.viewGroup = self.MakeRibbonGroup(self.ribbonTab, 'GroupView', 'View')
        self.camButton = self.MakeRibbonButton(self.viewGroup, 'ButtonCamWindow', '📷 Camera Modes', handlers.CameraButtonHandler)

        self.controlGroup = self.MakeRibbonGroup(self.ribbonTab, 'GroupControl', 'Control')
        self.startButton = self.MakeRibbonButton(self.controlGroup, 'ButtonStart', '▶ Start', handlers.StartButtonHandler)
        self.stopButton = self.MakeRibbonButton(self.controlGroup, 'ButtonStop', '⏹ Stop', handlers.StopButtonHandler)

        self.featuresGroup = self.MakeRibbonGroup(self.ribbonTab, 'GroupFeatures', 'Features 🚀')
        self.envWindowButton = self.MakeRibbonButton(self.featuresGroup, 'ButtonEnvWindow', '🌦️ Environment', handlers.OpenEnvironmentWindowHandler)
        self.analysisWindowButton = self.MakeRibbonButton(self.featuresGroup, 'ButtonAnalysisWindow', '📊 Traffic Analysis', handlers.OpenTrafficAnalysisWindowHandler)
        self.scenariosWindowButton = self.MakeRibbonButton(self.featuresGroup, 'ButtonScenariosWindow', '🎭 Scenarios', handlers.OpenScenariosWindowHandler)

    def create_environment_window(self):
        """Create a simple environment control window with weather buttons and context selector."""
        try:
            if not hasattr(self, 'env_window') or self.env_window is None or not self.env_window.winfo_exists():
                # Use scenario's topmost popup system for consistency
                root = self.scenario._create_topmost_popup()
                self.env_window = tk.Toplevel(root)
                self.env_window.title("Environment Control 🌦️")
                self.env_window.geometry("420x320")
                self.env_window.resizable(True, True)
                self.env_window.attributes('-topmost', True)
                self.env_window.lift()
                self.env_window.focus_force()
                self.env_window.protocol("WM_DELETE_WINDOW", self.env_window.withdraw)

                frame = ttk.Frame(self.env_window, padding="10")
                frame.grid(row=0, column=0, sticky=(tk.N, tk.S, tk.W, tk.E))
                self.env_window.columnconfigure(0, weight=1)
                self.env_window.rowconfigure(0, weight=1)

                ttk.Label(frame, text="Weather Settings", font=("Arial", 12, "bold")).grid(row=0, column=0, columnspan=3, pady=(0, 12), sticky=tk.W)

                ttk.Button(frame, text="☀️ Sunny", command=lambda: self.apply_weather_context("sunny")).grid(row=1, column=0, sticky=(tk.W, tk.E), padx=(0,8), pady=4)
                ttk.Button(frame, text="🌧️ Rainy", command=lambda: self.apply_weather_context("rainy")).grid(row=1, column=1, sticky=(tk.W, tk.E), padx=(8,8), pady=4)
                ttk.Button(frame, text="🌫️ Foggy", command=lambda: self.apply_weather_context("foggy")).grid(row=1, column=2, sticky=(tk.W, tk.E), padx=(8,0), pady=4)
                ttk.Button(frame, text="🧊 Icy", command=lambda: self.apply_weather_context("icy")).grid(row=2, column=0, sticky=(tk.W, tk.E), padx=(0,8), pady=4)
                ttk.Button(frame, text="⛈️ Stormy", command=lambda: self.apply_weather_context("stormy")).grid(row=2, column=1, columnspan=2, sticky=(tk.W, tk.E), padx=(8,0), pady=4)

                ttk.Separator(frame).grid(row=3, column=0, columnspan=3, sticky=(tk.W, tk.E), pady=(8,8))

                # Removed context dropdown (buttons already exist and auto-apply)

                self.env_status_label = ttk.Label(frame, text="Ready")
                self.env_status_label.grid(row=5, column=0, columnspan=3, pady=(10,0), sticky=tk.W)

                ttk.Button(frame, text="Close", command=self.env_window.withdraw).grid(row=6, column=0, columnspan=3, pady=(12,0))

                for c in range(3):
                    frame.columnconfigure(c, weight=1)

            self.env_window.deiconify()
            self.env_window.lift()
        except Exception as e:
            self.logProxy.logger.error(f"Failed to create environment window: {e}")

    def apply_weather_context(self, weather_type: str):
        """Apply a context if found; otherwise apply scenario weather effects."""
        try:
            if hasattr(self, 'env_status_label'):
                self.env_status_label.config(text=f"Applying {weather_type}...")
            prj = self.winRoadProxy.Project
            found = None
            names = {
                'sunny': ["sunny", "day", "clear"],
                'rainy': ["rainy", "rain", "wet"],
                'foggy': ["foggy", "fog", "mist"],
                'icy': ["icy", "ice", "slippery"],
                'stormy': ["stormy", "storm", "thunder"],
            }.get(weather_type, [])
            for i in range(prj.ContextsCount):
                ctx = prj.Context(i)
                if ctx.Name.lower() in names:
                    found = ctx; break
            if found:
                self.winRoadProxy.SimulationCore.ApplyContext(found)
                self.logProxy.logger.info(f"Applied context: {found.Name}")
                if hasattr(self, 'env_status_label'):
                    self.env_status_label.config(text=f"Applied {weather_type} weather")
            else:
                self.logProxy.logger.info(f"No '{weather_type}' context found; applying effects")
                if hasattr(self, 'env_status_label'):
                    self.env_status_label.config(text=f"No {weather_type} context found")
            if hasattr(self.scenario, 'apply_weather_effects'):
                self.scenario.apply_weather_effects(weather_type)
        except Exception as e:
            self.logProxy.logger.error(f"apply_weather_context failed: {e}")

    def create_traffic_analysis_window(self):
        """Create a comprehensive traffic analysis dashboard with per-road metrics."""
        try:
            if not hasattr(self, 'analysis_window') or self.analysis_window is None or not self.analysis_window.winfo_exists():
                # Use scenario's topmost popup system for consistency
                root = self.scenario._create_topmost_popup()
                self.analysis_window = tk.Toplevel(root)
                self.analysis_window.title("Advanced Traffic Analysis 📊")
                self.analysis_window.geometry("1000x700")
                self.analysis_window.resizable(True, True)
                self.analysis_window.attributes('-topmost', True)
                self.analysis_window.lift()
                self.analysis_window.focus_force()
                self.analysis_window.protocol("WM_DELETE_WINDOW", self.analysis_window.withdraw)

                # Create main container with scrollbar
                main_canvas = tk.Canvas(self.analysis_window)
                scrollbar = ttk.Scrollbar(self.analysis_window, orient="vertical", command=main_canvas.yview)
                scrollable_frame = ttk.Frame(main_canvas)

                scrollable_frame.bind(
                    "<Configure>",
                    lambda e: main_canvas.configure(scrollregion=main_canvas.bbox("all"))
                )

                main_canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
                main_canvas.configure(yscrollcommand=scrollbar.set)

                # Network Overview Section
                network_frame = ttk.LabelFrame(scrollable_frame, text="🌐 Network Overview", padding="10")
                network_frame.grid(row=0, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(0, 10), padx=10)
                
                # Network metrics
                self.network_roads_label = ttk.Label(network_frame, text="Total Roads: --", font=("Arial", 11))
                self.network_roads_label.grid(row=0, column=0, sticky=tk.W, padx=(0, 20))
                
                self.network_vehicles_label = ttk.Label(network_frame, text="Total Vehicles: --", font=("Arial", 11))
                self.network_vehicles_label.grid(row=0, column=1, sticky=tk.W, padx=(0, 20))
                
                self.network_avg_speed_label = ttk.Label(network_frame, text="Network Avg Speed: -- km/h", font=("Arial", 11))
                self.network_avg_speed_label.grid(row=0, column=2, sticky=tk.W, padx=(0, 20))
                
                self.network_delay_label = ttk.Label(network_frame, text="Total Delay: -- veh-h", font=("Arial", 11))
                self.network_delay_label.grid(row=1, column=0, sticky=tk.W, padx=(0, 20))
                
                self.congestion_rate_label = ttk.Label(network_frame, text="Congestion Rate: --%", font=("Arial", 11))
                self.congestion_rate_label.grid(row=1, column=1, sticky=tk.W, padx=(0, 20))
                
                self.safety_rate_label = ttk.Label(network_frame, text="Safety Violations: --%", font=("Arial", 11))
                self.safety_rate_label.grid(row=1, column=2, sticky=tk.W, padx=(0, 20))

                # Per-Road Analysis Section
                roads_frame = ttk.LabelFrame(scrollable_frame, text="🛣️ Per-Road Analysis", padding="10")
                roads_frame.grid(row=1, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(0, 10), padx=10)
                
                # Create treeview for road data
                columns = ('Road', 'Vehicles', 'Avg Speed', 'LOS', 'Flow Rate', 'Density', 'Delay', 'Efficiency')
                self.roads_tree = ttk.Treeview(roads_frame, columns=columns, show='headings', height=12)
                
                # Configure columns
                for col in columns:
                    self.roads_tree.heading(col, text=col)
                    self.roads_tree.column(col, width=100, anchor=tk.CENTER)
                
                # Add scrollbars for treeview
                roads_scrollbar_y = ttk.Scrollbar(roads_frame, orient="vertical", command=self.roads_tree.yview)
                roads_scrollbar_x = ttk.Scrollbar(roads_frame, orient="horizontal", command=self.roads_tree.xview)
                self.roads_tree.configure(yscrollcommand=roads_scrollbar_y.set, xscrollcommand=roads_scrollbar_x.set)
                
                # Grid treeview and scrollbars
                self.roads_tree.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
                roads_scrollbar_y.grid(row=0, column=1, sticky=(tk.N, tk.S))
                roads_scrollbar_x.grid(row=1, column=0, sticky=(tk.W, tk.E))
                
                # Configure grid weights
                roads_frame.columnconfigure(0, weight=1)
                roads_frame.rowconfigure(0, weight=1)

                # Detailed Analysis Section
                detail_frame = ttk.LabelFrame(scrollable_frame, text="📈 Detailed Metrics", padding="10")
                detail_frame.grid(row=2, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(0, 10), padx=10)
                
                # Create notebook for different analysis views
                self.analysis_notebook = ttk.Notebook(detail_frame)
                self.analysis_notebook.grid(row=0, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(0, 10))
                
                # Speed Analysis Tab
                speed_frame = ttk.Frame(self.analysis_notebook)
                self.analysis_notebook.add(speed_frame, text="Speed Analysis")
                
                self.speed_metrics_text = tk.Text(speed_frame, height=8, width=80, wrap=tk.WORD)
                speed_scrollbar = ttk.Scrollbar(speed_frame, orient="vertical", command=self.speed_metrics_text.yview)
                self.speed_metrics_text.configure(yscrollcommand=speed_scrollbar.set)
                self.speed_metrics_text.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
                speed_scrollbar.grid(row=0, column=1, sticky=(tk.N, tk.S))
                
                # Flow Analysis Tab
                flow_frame = ttk.Frame(self.analysis_notebook)
                self.analysis_notebook.add(flow_frame, text="Flow Analysis")
                
                self.flow_metrics_text = tk.Text(flow_frame, height=8, width=80, wrap=tk.WORD)
                flow_scrollbar = ttk.Scrollbar(flow_frame, orient="vertical", command=self.flow_metrics_text.yview)
                self.flow_metrics_text.configure(yscrollcommand=flow_scrollbar.set)
                self.flow_metrics_text.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
                flow_scrollbar.grid(row=0, column=1, sticky=(tk.N, tk.S))
                
                # Safety Analysis Tab
                safety_frame = ttk.Frame(self.analysis_notebook)
                self.analysis_notebook.add(safety_frame, text="Safety Analysis")
                
                self.safety_metrics_text = tk.Text(safety_frame, height=8, width=80, wrap=tk.WORD)
                safety_scrollbar = ttk.Scrollbar(safety_frame, orient="vertical", command=self.safety_metrics_text.yview)
                self.safety_metrics_text.configure(yscrollcommand=safety_scrollbar.set)
                self.safety_metrics_text.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
                safety_scrollbar.grid(row=0, column=1, sticky=(tk.N, tk.S))
                
                # Environmental Analysis Tab
                env_frame = ttk.Frame(self.analysis_notebook)
                self.analysis_notebook.add(env_frame, text="Environmental")
                
                self.env_metrics_text = tk.Text(env_frame, height=8, width=80, wrap=tk.WORD)
                env_scrollbar = ttk.Scrollbar(env_frame, orient="vertical", command=self.env_metrics_text.yview)
                self.env_metrics_text.configure(yscrollcommand=env_scrollbar.set)
                self.env_metrics_text.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
                env_scrollbar.grid(row=0, column=1, sticky=(tk.N, tk.S))

                # Control buttons
                button_frame = ttk.Frame(scrollable_frame)
                button_frame.grid(row=3, column=0, columnspan=2, pady=(0, 10), padx=10)
                
                ttk.Button(button_frame, text="🔄 Refresh Analysis", command=self.update_analysis).pack(side=tk.LEFT, padx=(0, 10))
                ttk.Button(button_frame, text="⚡ Fast Analysis", command=self._update_analysis_fast).pack(side=tk.LEFT, padx=(0, 10))
                ttk.Button(button_frame, text="📊 Auto Refresh", command=self._toggle_auto_refresh).pack(side=tk.LEFT, padx=(0, 10))
                ttk.Button(button_frame, text="🔧 Diagnostics", command=self._run_traffic_diagnostics).pack(side=tk.LEFT, padx=(0, 10))
                ttk.Button(button_frame, text="📄 Generate Report", command=self._generate_traffic_report).pack(side=tk.LEFT, padx=(0, 10))
                ttk.Button(button_frame, text="❌ Close", command=self.analysis_window.withdraw).pack(side=tk.RIGHT)

                # Configure main canvas grid
                main_canvas.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
                scrollbar.grid(row=0, column=1, sticky=(tk.N, tk.S))
                
                self.analysis_window.columnconfigure(0, weight=1)
                self.analysis_window.rowconfigure(0, weight=1)

                # Initialize auto-refresh state
                self.auto_refresh_enabled = False
                self.auto_refresh_job = None
                
                # Set callback for detailed analysis updates
                self.detailed_road_analysis_callback = self._update_detailed_analysis_display

            self.analysis_window.deiconify()
            self.analysis_window.lift()
            self.analysis_window.attributes('-topmost', True)
            self.analysis_window.after(100, lambda: self.analysis_window.attributes('-topmost', False))
            self.analysis_window.focus_force()
            self.logProxy.logger.info("Traffic analysis window created successfully")
        except Exception as e:
            self.logProxy.logger.error(f"Failed to create traffic analysis window: {e}")
            # Try to show an error message
            try:
                from tkinter import messagebox
                messagebox.showerror("Error", f"Failed to create traffic analysis window:\n{str(e)}")
            except:
                pass

    def _toggle_auto_refresh(self):
        """Toggle automatic refresh of traffic analysis."""
        try:
            if not hasattr(self, 'auto_refresh_enabled'):
                self.auto_refresh_enabled = False
            
            self.auto_refresh_enabled = not self.auto_refresh_enabled
            
            if self.auto_refresh_enabled:
                self._start_auto_refresh()
                self.logProxy.logger.info("Auto-refresh enabled for traffic analysis")
            else:
                self._stop_auto_refresh()
                self.logProxy.logger.info("Auto-refresh disabled for traffic analysis")
        except Exception as e:
            self.logProxy.logger.error(f"Failed to toggle auto-refresh: {e}")

    def _start_auto_refresh(self):
        """Start automatic refresh every 2 seconds."""
        try:
            if hasattr(self, 'auto_refresh_job') and self.auto_refresh_job:
                self.tk_root.after_cancel(self.auto_refresh_job)
            
            self.update_analysis()
            self.auto_refresh_job = self.tk_root.after(2000, self._auto_refresh_callback)
        except Exception as e:
            self.logProxy.logger.error(f"Failed to start auto-refresh: {e}")

    def _stop_auto_refresh(self):
        """Stop automatic refresh."""
        try:
            if hasattr(self, 'auto_refresh_job') and self.auto_refresh_job:
                self.tk_root.after_cancel(self.auto_refresh_job)
                self.auto_refresh_job = None
        except Exception as e:
            self.logProxy.logger.error(f"Failed to stop auto-refresh: {e}")

    def _auto_refresh_callback(self):
        """Callback for auto-refresh."""
        try:
            if hasattr(self, 'auto_refresh_enabled') and self.auto_refresh_enabled:
                self.update_analysis()
                self.auto_refresh_job = self.tk_root.after(2000, self._auto_refresh_callback)
        except Exception as e:
            self.logProxy.logger.error(f"Auto-refresh callback failed: {e}")

    def _create_accident(self, road_name: str, percent: float | None = None):
        """Create an accident on the specified road at the given percentage."""
        try:
            from .loading_popup import LoadingPopup
            lp = LoadingPopup(self.tk_root, title="Creating accident...")
            self.tk_root.update_idletasks()
            try:
                self.scenario.create_accident_at_percent(road_name, percent)
            finally:
                lp.close()
            if hasattr(self, 'scenario_status_label'):
                self.scenario_status_label.config(text=f"Accident created on {road_name}{f' at {percent:.0f}%' if percent is not None else ''}")
        except Exception as e:
            self.logProxy.logger.error(f"_create_accident failed: {e}")

    def _go_to_accident(self, road_name: str):
        """Go to accident location on the specified road."""
        try:
            pos = self.scenario.get_accident_pos(road_name)
            if not pos:
                if hasattr(self, 'scenario_status_label'):
                    self.scenario_status_label.config(text=f"No accident on {road_name}")
                return
            back = 25.0; up = 12.0
            # Use current camera forward to offset
            cam = self.winRoadProxy.MainForm.MainCamera
            state = cam.MainCameraState
            eye = state.eye; view = state.ViewPoint
            dirx, dirz = (view.X - eye.X), (view.Z - eye.Z)
            norm = max((dirx*dirx + dirz*dirz) ** 0.5, 1e-6)
            dirx /= norm; dirz /= norm
            new_eye = AsF8COMdVec3(pos.X - dirx * back, pos.Y + up, pos.Z - dirz * back)
            self._set_camera(new_eye, AsF8COMdVec3(pos.X, pos.Y, pos.Z))
            self.accident_pos = pos
        except Exception as e:
            self.logProxy.logger.error(f"_go_to_accident failed: {e}")

    def create_scenarios_window(self):
        """Create the scenarios control popup window (trimmed)."""
        try:
            if not hasattr(self, 'scenarios_window') or self.scenarios_window is None or not self.scenarios_window.winfo_exists():
                # Create normal window for scenarios (not topmost initially to avoid checkbox rendering issues)
                self.scenarios_window = tk.Toplevel()
                self.scenarios_window.title("Scenario Control")
                self.scenarios_window.geometry("800x600")
                self.scenarios_window.resizable(True, True)
                self.scenarios_window.protocol("WM_DELETE_WINDOW", self.scenarios_window.withdraw)

                # Delay topmost attributes to avoid interfering with widget rendering
                def make_topmost():
                    try:
                        self.scenarios_window.attributes('-topmost', True)
                        self.scenarios_window.lift()
                        self.scenarios_window.focus_force()
                    except:
                        pass  # Ignore if window is already closed

                self.scenarios_window.after(500, make_topmost)

                # Resizable content area (RoadConfigPanel has its own scrolling)
                self.scenarios_window.columnconfigure(0, weight=1)
                self.scenarios_window.rowconfigure(0, weight=1)

                main_frame = ttk.Frame(self.scenarios_window, padding="10")
                main_frame.grid(row=0, column=0, sticky=(tk.N, tk.S, tk.W, tk.E))
                main_frame.columnconfigure(0, weight=1)
                main_frame.columnconfigure(1, weight=1)
                main_frame.rowconfigure(1, weight=1)

                ttk.Label(main_frame, text="Scenario Control", font=("Arial", 14, "bold")).grid(row=0, column=0, columnspan=2, pady=(0, 12))

                from .road_config_panel import RoadConfigPanel
                def get_roads():
                    return (self.winRoadProxy.Project.Road(i).Name for i in range(self.winRoadProxy.Project.RoadsCount))
                def on_apply(plan):
                    try:
                        self.scenario.set_plan(plan)
                        enabled_roads = plan.enabled_roads()
                        self.logProxy.logger.info(f"Applied SimulationPlan: enabled={enabled_roads}")
                    except Exception as e:
                        self.logProxy.logger.error(f"on_apply plan failed: {e}")

                # Ensure we have a default plan for the road config panel
                if not self.scenario.plan:
                    self.scenario._ensure_default_plan()

                panel = RoadConfigPanel(
                    main_frame,
                    get_roads,
                    on_apply,
                    initial_plan=self.scenario.plan,
                    go_to_road=lambda name: self._go_to_road_by_name(name),
                    go_to_accident=lambda name: self._go_to_accident(name),
                    has_accident=lambda name: self.scenario.has_accident(name),
                    create_accident=lambda name, percent: self._create_accident(name, percent),
                )
                panel.grid(row=1, column=0, columnspan=2, sticky=(tk.W, tk.E))

                self.scenario_status_label = ttk.Label(main_frame, text="Ready", font=("Arial", 9))
                self.scenario_status_label.grid(row=2, column=0, columnspan=2, pady=(10, 0))
                # Emergency game status area
                self.emg_status = ttk.Label(main_frame, text="Emergency: --", font=("Arial", 10))
                self.emg_status.grid(row=5, column=0, columnspan=2, sticky=tk.W, pady=(6,0))

                self.follow_emergency_var = tk.BooleanVar(value=False)
                ttk.Checkbutton(main_frame, text="Follow Emergency Vehicle", variable=self.follow_emergency_var, command=lambda: None).grid(row=6, column=0, sticky=tk.W)

                # Instructions for emergency game
                instructions_frame = ttk.LabelFrame(main_frame, text="🚑 Emergency Game Instructions", padding="8")
                instructions_frame.grid(row=6, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(8, 0))
                
                ttk.Label(instructions_frame, text="1. Create accidents using '🚨 Accident' buttons above", font=("Arial", 9)).pack(anchor=tk.W)
                ttk.Label(instructions_frame, text="2. In UC-win/Road, manually enter driving mode (F1 or Navigation menu)", font=("Arial", 9)).pack(anchor=tk.W)
                ttk.Label(instructions_frame, text="3. Click '🚑 Start Emergency Game' to begin", font=("Arial", 9)).pack(anchor=tk.W)
                ttk.Label(instructions_frame, text="4. Drive to the nearest accident scene as fast as possible!", font=("Arial", 9)).pack(anchor=tk.W)
                

                # Emergency game controls
                ttk.Separator(main_frame, orient='horizontal').grid(row=7, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(10, 8))
                ttk.Label(main_frame, text="Emergency Game Controls", font=("Arial", 10, "bold")).grid(row=8, column=0, columnspan=2, sticky=tk.W, pady=(0, 5))
                
                # Emergency Game button
                btn_emergency_game = ttk.Button(main_frame, text="🚑 Start Emergency Game", command=self.start_emergency_game)
                btn_emergency_game.grid(row=9, column=0, sticky=tk.W, padx=(0, 10))
                
                btn_reset = ttk.Button(main_frame, text="🔄 Reset Emergency Game", command=lambda: self.scenario.reset_emergency_game())
                btn_reset.grid(row=9, column=1, sticky=tk.W)

                ttk.Button(main_frame, text="Close", command=self.scenarios_window.withdraw).grid(row=10, column=0, columnspan=2, pady=(12, 0))

            self.scenarios_window.deiconify()
            self.scenarios_window.lift()
        except Exception as e:
            self.logProxy.logger.error(f"Failed to create scenarios window: {e}")



    def start_emergency_game(self):
        """Start the emergency game with popup flow."""
        try:
            # Check if there are any accidents first
            if not self.scenario.accidents:
                from tkinter import messagebox

                # Use scenario window as parent for proper z-order
                messagebox.showwarning(
                    "🚨 No Accidents Found",
                    "You need to create at least one accident scene first!\n\n"
                    "Please:\n"
                    "1. Click '🚨 Accident' on any road to create an accident\n"
                    "2. Then try starting the emergency game again",
                    parent=self.scenarios_window
                )
                return
            
            # Start the emergency game
            self.scenario.start_emergency_game()
            
        except Exception as e:
            self.logProxy.logger.error(f"start_emergency_game failed: {e}")


    def KillRibbonUI(self):
        try:
            # Stop scenario activities
            if hasattr(self, 'scenario'):
                try:
                    self.scenario.stop_simulation()
                except Exception:
                    pass

            # Unregister events and delete all ribbon controls & groups, then remove tab
            try:
                self.CloseCallbackEvent()
            except Exception:
                pass

            try:
                if hasattr(self, 'camButton'):
                    self.DeleteControlFromParent(self.camButton, self.viewGroup)
                if hasattr(self, 'startButton'):
                    self.DeleteControlFromParent(self.startButton, self.controlGroup)
                if hasattr(self, 'stopButton'):
                    self.DeleteControlFromParent(self.stopButton, self.controlGroup)
                if hasattr(self, 'envWindowButton'):
                    self.DeleteControlFromParent(self.envWindowButton, self.featuresGroup)
                if hasattr(self, 'analysisWindowButton'):
                    self.DeleteControlFromParent(self.analysisWindowButton, self.featuresGroup)
                if hasattr(self, 'scenariosWindowButton'):
                    self.DeleteControlFromParent(self.scenariosWindowButton, self.featuresGroup)
            except Exception:
                pass

            try:
                if hasattr(self, 'ribbonTab') and self.ribbonTab and hasattr(self, 'viewGroup') and self.viewGroup:
                    self.ribbonTab.DeleteGroup(self.viewGroup)
                if hasattr(self, 'ribbonTab') and self.ribbonTab and hasattr(self, 'controlGroup') and self.controlGroup:
                    self.ribbonTab.DeleteGroup(self.controlGroup)
                if hasattr(self, 'ribbonTab') and self.ribbonTab and hasattr(self, 'featuresGroup') and self.featuresGroup:
                    self.ribbonTab.DeleteGroup(self.featuresGroup)
                if hasattr(self, 'ribbonTab') and self.ribbonTab and self.ribbonTab.RibbonGroupsCount == 0:
                    if hasattr(self, 'ribbonMenu') and self.ribbonMenu:
                        self.ribbonMenu.DeleteTab(self.ribbonTab)
                self.viewGroup = None
                self.controlGroup = None
                self.featuresGroup = None
                self.ribbonTab = None
                self.ribbonMenu = None
            except Exception:
                pass

            # Close Tk
            if hasattr(self, 'tk_root') and self.tk_root:
                try:
                    self.tk_root.quit()
                except Exception:
                    pass
        except Exception as e:
            self.logProxy.logger.error(f"Error during ribbon cleanup: {e}")

