import tkinter as tk
from tkinter import ttk
from typing import Callable, Iterable, Optional, List, Dict
from .config import RoadConfig, SimulationPlan

class RoadConfigPanel(ttk.Frame):
    def __init__(
        self,
        master,
        get_roads: Callable[[], Iterable[str]],
        on_apply: Callable[[SimulationPlan], None],
        initial_plan: Optional[SimulationPlan] = None,
        go_to_road: Optional[Callable[[str], None]] = None,
        go_to_accident: Optional[Callable[[str], None]] = None,
        has_accident: Optional[Callable[[str], bool]] = None,
        create_accident: Optional[Callable[[str, float], None]] = None,
    ):
        super().__init__(master)
        self.on_apply = on_apply
        self.go_to_road = go_to_road or (lambda name: None)
        self.go_to_accident = go_to_accident or (lambda name: None)
        self.has_accident = has_accident or (lambda name: False)
        self.create_accident = create_accident or (lambda name, percent: None)

        self._go_acc_buttons: Dict[str, ttk.Button] = {}

        # Header controls
        header = ttk.Frame(self)
        header.grid(row=0, column=0, sticky=(tk.W, tk.E), pady=(0,6))
        ttk.Label(header, text="Per-road configuration", font=("Arial", 10, "bold")).grid(row=0, column=0, sticky=tk.W)
        self.batch_var = tk.BooleanVar(value=True)
        ttk.Checkbutton(header, text="Batch generate before Start", variable=self.batch_var).grid(row=0, column=1, padx=(12,0))
        ttk.Button(header, text="Apply", command=self._apply).grid(row=0, column=2, padx=(8,0))
        for c in range(3): header.columnconfigure(c, weight=1)

        # Scrollable rows
        canvas = tk.Canvas(self, borderwidth=0, highlightthickness=0)
        scrollbar = ttk.Scrollbar(self, orient="vertical", command=canvas.yview)
        self.rows_frame = ttk.Frame(canvas)
        self.rows_frame.bind("<Configure>", lambda _e: canvas.configure(scrollregion=canvas.bbox("all")))
        canvas.create_window((0,0), window=self.rows_frame, anchor="nw")
        canvas.configure(yscrollcommand=scrollbar.set, height=240)
        canvas.grid(row=1, column=0, sticky=(tk.N, tk.S, tk.W, tk.E))
        scrollbar.grid(row=1, column=1, sticky=(tk.N, tk.S))
        self.columnconfigure(0, weight=1)

        # Columns header row with better styling
        hdr = ttk.Frame(self.rows_frame)
        hdr.grid(row=0, column=0, sticky=(tk.W, tk.E), pady=(0, 8))
        
        # Create styled headers
        style = ttk.Style()
        style.configure("Header.TLabel", font=("Arial", 9, "bold"), background="#f0f0f0")
        
        ttk.Label(hdr, text="✓", style="Header.TLabel", width=3).grid(row=0, column=0, padx=(0, 2))
        ttk.Label(hdr, text="Road Name", style="Header.TLabel", width=27).grid(row=0, column=1, sticky=tk.W, padx=(0, 2))
        ttk.Label(hdr, text="Vehicles", style="Header.TLabel", width=10).grid(row=0, column=2, padx=(0, 2))
        ttk.Label(hdr, text="Min Speed", style="Header.TLabel", width=10).grid(row=0, column=3, padx=(0, 2))
        ttk.Label(hdr, text="Max Speed", style="Header.TLabel", width=10).grid(row=0, column=4, padx=(0, 2))
        ttk.Label(hdr, text="Actions", style="Header.TLabel", width=12).grid(row=0, column=5, padx=(0, 2))
        ttk.Label(hdr, text="Create Accident", style="Header.TLabel", width=18).grid(row=0, column=6, padx=(0, 2))
        ttk.Label(hdr, text="Position %", style="Header.TLabel", width=10).grid(row=0, column=8, padx=(0, 2))

        # Load rows
        self._row_vars: List[tuple[str, tk.BooleanVar, tk.IntVar, tk.DoubleVar, tk.DoubleVar, tk.DoubleVar]] = []
        plan_map = {c.name: c for c in (initial_plan.configs if initial_plan else [])}

        roads_list = list(get_roads())

        # Load configuration values for each road

        for idx, name in enumerate(roads_list):
            config = plan_map.get(name)
            if config:
                enabled = tk.BooleanVar(value=bool(config.enabled))
                vehicles = tk.IntVar(value=int(config.vehicles))
                min_speed = tk.DoubleVar(value=float(config.min_speed))
                max_speed = tk.DoubleVar(value=float(config.max_speed))
            else:
                enabled = tk.BooleanVar(value=True)
                vehicles = tk.IntVar(value=30)
                min_speed = tk.DoubleVar(value=20.0)
                max_speed = tk.DoubleVar(value=60.0)

            acc_percent = tk.DoubleVar(value=50.0)
            row = ttk.Frame(self.rows_frame)
            row.grid(row=idx+1, column=0, sticky=(tk.W, tk.E), pady=2)
            # Create simple checkbox
            enabled_check = ttk.Checkbutton(row, variable=enabled)
            enabled_check.grid(row=0, column=0)

            ttk.Label(row, text=name, width=32).grid(row=0, column=1, sticky=tk.W)

            vehicles_spin = ttk.Spinbox(row, from_=0, to=10000, width=8)
            vehicles_spin.grid(row=0, column=2)
            vehicles_spin.config(textvariable=vehicles)
            vehicles_spin.set(str(vehicles.get()))

            min_speed_spin = ttk.Spinbox(row, from_=0, to=200, increment=1.0, width=8)
            min_speed_spin.grid(row=0, column=3)
            min_speed_spin.config(textvariable=min_speed)
            min_speed_spin.set(str(min_speed.get()))

            max_speed_spin = ttk.Spinbox(row, from_=0, to=200, increment=1.0, width=8)
            max_speed_spin.grid(row=0, column=4)
            max_speed_spin.config(textvariable=max_speed)
            max_speed_spin.set(str(max_speed.get()))
            act = ttk.Frame(row)
            act.grid(row=0, column=5, sticky=(tk.W))
            ttk.Button(act, text="Go", command=lambda n=name: self.go_to_road(n)).grid(row=0, column=0)
            ttk.Button(act, text="🚨 Accident", command=lambda n=name, p=acc_percent: (self.create_accident(n, float(p.get())), self._update_acc_button(n))).grid(row=0, column=1, padx=(4,0))
            acc_btn = ttk.Button(act, text="📍 Go Accident", command=lambda n=name: self.go_to_accident(n))
            acc_btn.grid(row=0, column=2, padx=(4,0))
            acc_btn.state(["!disabled"] if self.has_accident(name) else ["disabled"])
            self._go_acc_buttons[name] = acc_btn
            
            # Replace Spinbox with Slider for percentage
            slider_frame = ttk.Frame(row)
            slider_frame.grid(row=0, column=6, padx=(8,0), sticky=(tk.W, tk.E))
            
            # Create percentage label that updates with slider
            percent_label = ttk.Label(slider_frame, text=f"{acc_percent.get():.0f}%", width=4)
            percent_label.pack(side=tk.LEFT, padx=(4,0))
            
            # Create slider with callback to update label
            def update_percent_label(*args):
                percent_label.config(text=f"{acc_percent.get():.0f}%")
            
            acc_percent.trace('w', update_percent_label)
            
            ttk.Scale(slider_frame, from_=0, to=100, orient=tk.HORIZONTAL,
                     variable=acc_percent, length=80).pack(side=tk.LEFT)
            self._row_vars.append((name, enabled, vehicles, min_speed, max_speed, acc_percent))

    def _update_acc_button(self, name: str):
        btn = self._go_acc_buttons.get(name)
        if btn is not None:
            if self.has_accident(name):
                btn.state(["!disabled"])
            else:
                btn.state(["disabled"])

    def _apply(self):
        configs = []
        for name, enabled, vehicles, min_speed, max_speed, _ in self._row_vars:
            cfg = RoadConfig(
                name=name,
                enabled=bool(enabled.get()),
                vehicles=int(vehicles.get()),
                min_speed=float(min_speed.get()),
                max_speed=float(max_speed.get()),
            )
            configs.append(cfg)
        plan = SimulationPlan(configs=configs)
        self.on_apply(plan)

    def batch_enabled(self) -> bool:
        return bool(self.batch_var.get())

