"""
Pestaña de pulseras activas.
Muestra una tabla con barras de progreso de tiempo en tiempo real.

Fases:
  VERDE  (grace)   -> tiempo de gracia (1 min en TEST_MODE): barra llena, se va vaciando
  AZUL   (playing) -> tiempo de juego  (1 min en TEST_MODE): barra llena de nuevo, vaciando
  ROJO   (expired) -> tiempo terminado: barra roja + alerta RETIRAR MANILLA hasta devolucion

Header derecho muestra stats de stock en tiempo real:
  Stock | Listas para usar | Activas | Vencidas | Por retirar
"""
import customtkinter as ctk
import threading
import time as _time
from datetime import datetime, timedelta
import wristband_tracker
import api
import session

# ---------------------------------------------------------------------------
# Deteccion de desactivaciones de hardware en hilo de fondo
# ---------------------------------------------------------------------------
_deact_pending = [0]   # contador; accedido por _tick (hilo principal) y hilo de fondo


def _start_deactivation_poller():
    def _loop():
        while True:
            try:
                count = api.get_deactivations()
                if count > 0:
                    _deact_pending[0] += count
            except Exception:
                pass
            _time.sleep(2)
    t = threading.Thread(target=_loop, daemon=True)
    t.start()


_start_deactivation_poller()

PHASE_COLORS = {
    "grace":   "#4caf50",   # verde brillante
    "playing": "#2196f3",   # azul
    "expired": "#f44336",   # rojo
    "anulada": "#ff9800",   # naranja
}
PHASE_LABELS = {
    "grace":   "Gracia",
    "playing": "Jugando",
    "expired": "Vencida",
    "anulada": "ANULADA",
}

BAR_WIDTH  = 140
BAR_HEIGHT = 16
REFRESH_MS = 500    # actualizar 2 veces por segundo


class ActiveWristbandsTab(ctk.CTkFrame):
    """Panel completo de la pestana 'Activas'. Se auto-actualiza cada 500ms."""

    def __init__(self, parent, **kwargs):
        super().__init__(parent, fg_color="transparent", **kwargs)
        self._row_widgets: dict[str, dict] = {}   # wristband_id -> widgets
        self._stat_labels: dict[str, ctk.CTkLabel] = {}
        self._build()
        self._tick()

    # ------------------------------------------------------------------
    # UI fija
    # ------------------------------------------------------------------

    def _build(self):
        # Cabecera de columnas
        header = ctk.CTkFrame(self, fg_color=("#1a1a2e", "#0a0a1a"), corner_radius=8)
        header.pack(fill="x", padx=8, pady=(8, 2))

        # RIGHT side: stats de stock (packed FIRST para anclar al borde derecho)
        stats_frame = ctk.CTkFrame(
            header,
            fg_color=("#111827", "#080810"),
            corner_radius=8,
        )
        stats_frame.pack(side="right", padx=8, pady=5)

        # Etiquetas (packed right-to-left dentro del frame)
        for key, text, color in [
            ("retirar",  "Por retirar: —", "#888888"),
            ("vencidas", "Vencidas: —",    "#888888"),
            ("activas",  "Activas: —",     "#2196f3"),
            ("listas",   "Listas: —",      "#4caf50"),
            ("stock",    "Stock: —",       "#aaaaaa"),
        ]:
            lbl = ctk.CTkLabel(
                stats_frame,
                text=text,
                font=ctk.CTkFont(size=11, weight="bold"),
                text_color=color,
            )
            lbl.pack(side="right", padx=8, pady=5)
            self._stat_labels[key] = lbl

        # Separador visual entre stats y columnas
        ctk.CTkLabel(
            header, text="|",
            font=ctk.CTkFont(size=18),
            text_color=("#2a3050", "#1e2438"),
        ).pack(side="right", padx=2)

        # LEFT side: encabezados de columna
        for text, width in [
            ("Nombre",  170),
            ("Codigo",   70),
            ("Entrada",  60),
            ("Salida",   60),
            ("Estado",  200),   # barra + label fase
            ("",        164),   # alerta RETIRAR MANILLA
            ("",         84),   # boton Devolver
            ("",         84),   # boton Anular
        ]:
            ctk.CTkLabel(
                header, text=text, width=width,
                font=ctk.CTkFont(size=11, weight="bold"),
                text_color="#4fc3f7", anchor="center",
            ).pack(side="left", padx=4, pady=8)

        # Lista scrolleable
        self._scroll = ctk.CTkScrollableFrame(
            self, fg_color=("gray88", "#0d1117"), corner_radius=8,
        )
        self._scroll.pack(fill="both", expand=True, padx=8, pady=(0, 8))

        self._lbl_empty = ctk.CTkLabel(
            self._scroll,
            text="No hay pulseras activas en este momento.",
            font=ctk.CTkFont(size=13),
            text_color="#555555",
        )
        self._lbl_empty.pack(expand=True, pady=30)

    # ------------------------------------------------------------------
    # Tick de actualizacion
    # ------------------------------------------------------------------

    def _tick(self):
        active = wristband_tracker.get_active()
        active_ids = {e["id"] for e in active}

        # Eliminar filas de pulseras ya devueltas
        for wid in list(self._row_widgets.keys()):
            if wid not in active_ids:
                widgets = self._row_widgets.pop(wid)
                if "frame" in widgets:
                    try:
                        widgets["frame"].destroy()
                    except Exception:
                        pass

        # Agregar filas nuevas
        for entry in active:
            if entry["id"] not in self._row_widgets:
                self._add_row(entry)

        # Actualizar barras — llama get_phase() que actualiza entry["status"]
        for entry in active:
            self._update_bar(entry)

        # Procesar desactivaciones DESPUES de actualizar barras,
        # para que entry["status"] ya refleje la fase real (expired, etc.)
        while _deact_pending[0] > 0:
            _deact_pending[0] -= 1
            for entry in wristband_tracker.get_active():
                if entry.get("status") == "expired":
                    wristband_tracker.mark_returned(entry["id"])
                    break

        # Actualizar stats de stock
        self._update_stats()

        # Mensaje de vacio
        if active:
            self._lbl_empty.pack_forget()
        else:
            self._lbl_empty.pack(expand=True, pady=30)

        self.after(REFRESH_MS, self._tick)

    # ------------------------------------------------------------------
    # Filas
    # ------------------------------------------------------------------

    def _add_row(self, entry: dict):
        row = ctk.CTkFrame(
            self._scroll,
            fg_color=("#1e2130", "#12151f"),
            corner_radius=8,
            border_width=1,
            border_color=("#2a3050", "#1e2438"),
        )
        row.pack(fill="x", pady=3, padx=2)

        # Nombre + referencia (apilados verticalmente)
        name_cell = ctk.CTkFrame(row, fg_color="transparent", width=170)
        name_cell.pack(side="left", padx=(12, 4), pady=6)
        name_cell.pack_propagate(False)

        ctk.CTkLabel(
            name_cell,
            text=_trunc(entry["name"], 20),
            font=ctk.CTkFont(size=12, weight="bold"),
            text_color="#e0e0e0", anchor="w",
        ).pack(anchor="w")

        ref = entry.get("reference", "").strip()
        if ref:
            ctk.CTkLabel(
                name_cell,
                text=_trunc(f"Ref: {ref}", 22),
                font=ctk.CTkFont(size=10),
                text_color="#666666", anchor="w",
            ).pack(anchor="w")

        # Codigo
        ctk.CTkLabel(
            row,
            text=entry["code"],
            font=ctk.CTkFont(family="Consolas", size=11),
            text_color="#888888", width=70, anchor="center",
        ).pack(side="left", padx=4)

        # Hora entrada
        ctk.CTkLabel(
            row,
            text=entry["start_time"].strftime("%H:%M"),
            font=ctk.CTkFont(size=11), text_color="#aaaaaa",
            width=60, anchor="center",
        ).pack(side="left", padx=4)

        # Hora salida estimada
        total_mins = entry["grace_minutes"] + entry["real_play_minutes"]
        salida_str = (entry["start_time"] + timedelta(minutes=total_mins)).strftime("%H:%M")
        ctk.CTkLabel(
            row,
            text=salida_str,
            font=ctk.CTkFont(size=11), text_color="#aaaaaa",
            width=60, anchor="center",
        ).pack(side="left", padx=4)

        # --- Barra de progreso ---
        bar = ctk.CTkProgressBar(
            row,
            width=BAR_WIDTH,
            height=BAR_HEIGHT,
            corner_radius=5,
            fg_color=("#3a3a3a", "#252525"),
            progress_color="#4caf50",
        )
        bar.set(1.0)
        bar.pack(side="left", padx=(8, 4))

        # Etiqueta de fase
        lbl_phase = ctk.CTkLabel(
            row, text="Gracia",
            font=ctk.CTkFont(size=10, weight="bold"),
            text_color="#4caf50",
            width=54, anchor="w",
        )
        lbl_phase.pack(side="left", padx=2)

        # Alerta RETIRAR MANILLA — siempre presente, visible solo en fase roja
        lbl_alert = ctk.CTkLabel(
            row,
            text="",
            font=ctk.CTkFont(size=12, weight="bold"),
            text_color="#ffffff",
            fg_color="transparent",
            corner_radius=6,
            width=164,
            height=32,
            anchor="center",
        )
        lbl_alert.pack(side="left", padx=(4, 4))

        # Boton devolver
        ctk.CTkButton(
            row, text="Devolver",
            width=76, height=30, corner_radius=6,
            fg_color="#37474f", hover_color="#546e7a",
            font=ctk.CTkFont(size=11),
            command=lambda wid=entry["id"]: wristband_tracker.mark_returned(wid),
        ).pack(side="left", padx=(4, 4))

        # Boton anular (visible solo si tiene permiso lb_vender)
        if session.tiene_permiso("lb_vender"):
            ctk.CTkButton(
                row, text="Anular",
                width=76, height=30, corner_radius=6,
                fg_color="#5a1010", hover_color="#7f0000",
                font=ctk.CTkFont(size=11),
                command=lambda e=entry: self._open_anular(e),
            ).pack(side="left", padx=(0, 6))

        self._row_widgets[entry["id"]] = {
            "frame":     row,
            "bar":       bar,
            "lbl_phase": lbl_phase,
            "lbl_alert": lbl_alert,
        }

    def _update_bar(self, entry: dict):
        widgets = self._row_widgets.get(entry["id"])
        if not widgets:
            return

        phase, progress = wristband_tracker.get_phase(entry)
        color = PHASE_COLORS[phase]
        label = PHASE_LABELS[phase]

        bar: ctk.CTkProgressBar  = widgets["bar"]
        lbl: ctk.CTkLabel        = widgets["lbl_phase"]
        lbl_alert: ctk.CTkLabel  = widgets["lbl_alert"]

        bar.configure(progress_color=color)
        bar.set(progress)
        lbl.configure(text=label, text_color=color)

        # Alerta visible en fase roja o anulada
        if phase == "expired":
            lbl_alert.configure(
                text="\u26A0  RETIRAR MANILLA",
                fg_color="#b71c1c",
                text_color="#ffffff",
            )
        elif phase == "anulada":
            lbl_alert.configure(
                text="\u26D4  ANULADA",
                fg_color="#e65100",
                text_color="#ffffff",
            )
        else:
            lbl_alert.configure(text="", fg_color="transparent")

    # ------------------------------------------------------------------
    # Stats de stock
    # ------------------------------------------------------------------

    def _update_stats(self):
        """Actualiza los contadores de stock en el header."""
        stock_total = api.get_stock_total()
        stats = wristband_tracker.get_stats()

        listas   = max(0, stock_total - stats["total_active"])
        playing  = stats["playing"]
        expired  = stats["expired"]
        returned = stats["returned_today"]

        self._stat_labels["stock"].configure(
            text=f"Stock: {stock_total}",
        )
        self._stat_labels["listas"].configure(
            text=f"Listas: {listas}",
            text_color="#4caf50" if listas > 0 else "#f44336",
        )
        self._stat_labels["activas"].configure(
            text=f"Activas: {playing}",
        )
        self._stat_labels["vencidas"].configure(
            text=f"Vencidas: {returned}",
        )
        self._stat_labels["retirar"].configure(
            text=f"Por retirar: {expired}",
            text_color="#f44336" if expired > 0 else "#888888",
        )

    def _open_anular(self, entry: dict):
        """Abre el dialogo de anulacion para una pulsera activa."""
        from ui.anular_dialog import AnularDialog
        import session as _session
        _u = _session.get_user()
        cashier = _u.get("display_name", _u.get("username", "caja1"))
        AnularDialog(
            self.winfo_toplevel(),
            entry=entry,
            cashier=cashier,
        )

def _trunc(text: str, max_len: int) -> str:
    return text if len(text) <= max_len else text[:max_len - 1] + "…"
