Following this instruction :
1. Strictly adhere to PEP-8 standards, ensuring code is clean, well-structured, and follows Python's style guide for readability.
2. Use appropriate modules like `typing` for type hints, ensuring code clarity, maintainability, and leveraging Python's standard libraries effectively.
3. Focus on time, space, robustness, scalability; write optimized, efficient code that can handle large datasets and scale seamlessly.
4. Implement comprehensive error handling, catching exceptions gracefully, providing meaningful error messages, and ensuring code robustness under unexpected conditions.
5. Ensure the developer agent writes advanced, maintainable Python code, balancing performance and readability while adhering to best practices.


TASK : in the below we have choice upload video or realtime video recoding , (user choice) 

import os
import sys
import cv2
import time
import logging
from typing import List, Tuple
from datetime import datetime
from pathlib import Path

from ultralytics import YOLO
import plotly.graph_objs as go
import plotly.io as pio

# Configure logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s [%(levelname)s] %(message)s',
    handlers=[
        logging.StreamHandler(sys.stdout)
    ]
)

# Constants for traffic density thresholds
LOW_THRESHOLD = 10    # Less than 10 vehicles per frame
MEDIUM_THRESHOLD = 30 # 10 to 30 vehicles per frame
HIGH_THRESHOLD = 30   # More than 30 vehicles per frame

# Vehicle classes based on YOLOv8's COCO dataset
VEHICLE_CLASSES = {'car', 'truck', 'bus', 'motorbike', 'bicycle'}


def create_output_folder(folder_name: str) -> Path:
    """
    Create an output folder if it doesn't exist.

    :param folder_name: Name of the folder to create.
    :return: Path object of the created folder.
    """
    try:
        output_path = Path(folder_name)
        output_path.mkdir(parents=True, exist_ok=True)
        logging.info(f"Output folder is set to: {output_path.resolve()}")
        return output_path
    except Exception as e:
        logging.error(f"Failed to create output folder '{folder_name}': {e}")
        sys.exit(1)


def classify_traffic_density(vehicle_count: int) -> str:
    """
    Classify traffic density based on the number of vehicles detected.

    :param vehicle_count: Number of vehicles detected in the frame.
    :return: Traffic density category as a string.
    """
    if vehicle_count < LOW_THRESHOLD:
        return 'Low Traffic'
    elif LOW_THRESHOLD <= vehicle_count < MEDIUM_THRESHOLD:
        return 'Medium Traffic'
    else:
        return 'High Traffic'


def generate_html_report(timestamps: List[datetime],
                        vehicle_counts: List[int],
                        output_folder: Path) -> None:
    """
    Generate an HTML report with traffic density visualization using Plotly.

    :param timestamps: List of timestamps corresponding to each frame.
    :param vehicle_counts: List of vehicle counts per frame.
    :param output_folder: Path object where the report will be saved.
    """
    try:
        # Convert timestamps to string for better readability in the plot
        time_strings = [ts.strftime("%H:%M:%S") for ts in timestamps]

        # Create a line chart for vehicle counts over time
        trace = go.Scatter(
            x=time_strings,
            y=vehicle_counts,
            mode='lines+markers',
            name='Vehicle Count',
            line=dict(color='blue')
        )

        layout = go.Layout(
            title='Traffic Density Over Time',
            xaxis=dict(title='Time'),
            yaxis=dict(title='Number of Vehicles'),
            hovermode='closest'
        )

        fig = go.Figure(data=[trace], layout=layout)

        # Define the report file path with timestamp
        report_filename = f"traffic_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.html"
        report_path = output_folder / report_filename

        # Save the plotly figure as an HTML file
        pio.write_html(fig, file=report_path, auto_open=False)
        logging.info(f"HTML report generated at: {report_path.resolve()}")

    except Exception as e:
        logging.error(f"Failed to generate HTML report: {e}")


def load_yolo_model(model_path: str = 'yolov8n.pt') -> YOLO:
    """
    Load the YOLOv8 model.

    :param model_path: Path to the YOLOv8 weights file.
    :return: Loaded YOLO model.
    """
    try:
        model = YOLO(model_path)
        logging.info("YOLOv8 model loaded successfully.")
        return model
    except Exception as e:
        logging.error(f"Failed to load YOLOv8 model: {e}")
        sys.exit(1)


def process_video_stream(source: str,
                         model: YOLO,
                         output_folder: Path) -> None:
    """
    Process the video stream, perform object detection, and collect traffic metrics.

    :param source: Video source (0 for webcam or path to video file).
    :param model: Loaded YOLO model for object detection.
    :param output_folder: Path object where the report will be saved.
    """
    try:
        cap = cv2.VideoCapture(source)
        if not cap.isOpened():
            logging.error(f"Cannot open video source: {source}")
            sys.exit(1)
        else:
            logging.info(f"Video source '{source}' opened successfully.")

        timestamps: List[datetime] = []
        vehicle_counts: List[int] = []

        while True:
            ret, frame = cap.read()
            if not ret:
                logging.warning("No frame received. Exiting...")
                break

            timestamp = datetime.now()
            timestamps.append(timestamp)

            # Perform object detection
            results = model(frame, verbose=False)

            # Extract detected classes and count vehicles
            detections = results[0].boxes
            vehicle_count = 0
            for det in detections:
                cls_id = int(det.cls[0])
                cls_name = model.names[cls_id]
                if cls_name in VEHICLE_CLASSES:
                    vehicle_count += 1
                    # Draw bounding box
                    x1, y1, x2, y2 = map(int, det.xyxy[0])
                    cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
                    cv2.putText(frame, cls_name, (x1, y1 - 10),
                                cv2.FONT_HERSHEY_SIMPLEX, 0.9, (36,255,12), 2)

            vehicle_counts.append(vehicle_count)
            traffic_density = classify_traffic_density(vehicle_count)

            # Display traffic density on the frame
            cv2.putText(frame, f'Traffic: {traffic_density}', (50, 50),
                        cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)

            # Display the resulting frame
            cv2.imshow('Real-Time Traffic Monitoring', frame)

            # Break the loop on 'q' key press
            if cv2.waitKey(1) & 0xFF == ord('q'):
                logging.info("Exit signal received. Stopping video processing...")
                break

        # Release the capture and destroy all OpenCV windows
        cap.release()
        cv2.destroyAllWindows()

        # Generate the HTML report
        generate_html_report(timestamps, vehicle_counts, output_folder)

    except KeyboardInterrupt:
        logging.info("Keyboard interrupt received. Exiting gracefully...")
        cap.release()
        cv2.destroyAllWindows()
        generate_html_report(timestamps, vehicle_counts, output_folder)
    except Exception as e:
        logging.error(f"An error occurred during video processing: {e}")
        cap.release()
        cv2.destroyAllWindows()
        sys.exit(1)


def main() -> None:
    """
    Main function to set up and run the real-time traffic monitoring system.
    """
    # Define the video source (0 for default webcam or path to video file)
    video_source = 0  # Change to video file path if needed

    # Define the output folder for reports
    output_folder = create_output_folder('traffic_reports')

    # Load YOLOv8 model
    model = load_yolo_model()

    # Start processing the video stream
    process_video_stream(video_source, model, output_folder)


if __name__ == '__main__':
    main()