"""
Panel principal del POS ICEBERG Manillas.
Layout: header minimalista + zona de contenido switchable (sin tabs).

Navegacion por menu de usuario:
  - Pantalla principal: grid de combos (PackageSelector)
  - Configuracion: grid de combos en modo edicion
  - Activas: ActiveWristbandsTab
  - Impresora: panel de configuracion de impresora

Disenado como CTkFrame para embeber dentro de AppWindow (ventana unica).
"""
import tkinter as tk
import customtkinter as ctk
from typing import Callable, Optional

import printing


class MainWindow(ctk.CTkFrame):
    """Panel raiz de la aplicacion, embebible en AppWindow."""

    def __init__(self, parent, user: dict = None,
                 on_logout: Optional[Callable] = None):
        super().__init__(parent, fg_color="#060b18", corner_radius=0)
        self._user = user or {}
        self._on_logout = on_logout

        self._current_view = "packages"
        self._content: Optional[ctk.CTkFrame] = None
        self._popup: Optional[ctk.CTkToplevel] = None

        self.grid_rowconfigure(0, weight=0)
        self.grid_rowconfigure(1, weight=1)
        self.grid_columnconfigure(0, weight=1)

        self._build_header()
        self._switch_view("packages")

    # ==================================================================
    # Header
    # ==================================================================

    def _build_header(self):
        self.header = ctk.CTkFrame(
            self, height=52, corner_radius=0, fg_color="#0a1628",
        )
        self.header.grid(row=0, column=0, sticky="nsew")
        self.header.grid_propagate(False)

        # --- LEFT ---

        # Boton Volver (oculto por defecto)
        self._btn_back = ctk.CTkButton(
            self.header,
            text="  Volver",
            font=ctk.CTkFont(size=13),
            text_color="#00d4ff",
            fg_color="transparent",
            hover_color="#152540",
            corner_radius=8,
            height=34, width=90,
            command=lambda: self._switch_view("packages"),
        )
        # No se packea — se muestra/oculta con _update_back_btn

        # Nombre del cajero (boton clickeable -> menu)
        cashier_name = self._user.get("display_name", "Cajero")
        self._btn_user = ctk.CTkButton(
            self.header,
            text=f"  {cashier_name}  ",
            font=ctk.CTkFont(size=14, weight="bold"),
            text_color="#e8edf5",
            fg_color="transparent",
            hover_color="#152540",
            corner_radius=8,
            height=36,
            command=self._toggle_user_menu,
        )
        self._btn_user.pack(side="left", padx=(16, 4), pady=8)

        # Badge OFFLINE
        if self._user.get("offline"):
            ctk.CTkLabel(
                self.header,
                text=" OFFLINE ",
                font=ctk.CTkFont(size=9, weight="bold"),
                text_color="#ffffff",
                fg_color="#ff4444",
                corner_radius=4,
            ).pack(side="left", padx=(0, 6), pady=16)

        # --- RIGHT (de derecha a izquierda) ---

        # Estado hardware
        self.lbl_hw_status = ctk.CTkLabel(
            self.header,
            text="  Conectando...",
            font=ctk.CTkFont(size=12),
            text_color="#4a5568",
        )
        self.lbl_hw_status.pack(side="right", padx=(8, 16))

        # Reloj
        self.lbl_clock = ctk.CTkLabel(
            self.header,
            text="00:00:00",
            font=ctk.CTkFont(family="Segoe UI", size=15, weight="bold"),
            text_color="#e8edf5",
        )
        self.lbl_clock.pack(side="right", padx=(0, 14))

        # Fecha
        self.lbl_date = ctk.CTkLabel(
            self.header,
            text="--/--/----",
            font=ctk.CTkFont(family="Segoe UI", size=12),
            text_color="#7a8ba8",
        )
        self.lbl_date.pack(side="right", padx=(0, 6))

    def _update_back_btn(self):
        """Muestra u oculta el boton Volver segun la vista actual."""
        if self._current_view != "packages":
            self._btn_back.pack(side="left", padx=(12, 0), pady=8, before=self._btn_user)
        else:
            self._btn_back.pack_forget()

    # ==================================================================
    # Menu de usuario
    # ==================================================================

    def _toggle_user_menu(self):
        if self._popup is not None:
            try:
                self._popup.destroy()
            except Exception:
                pass
            self._popup = None
            return
        self._show_user_menu()

    def _show_user_menu(self):
        cashier_name = self._user.get("display_name", "Cajero")
        role = self._user.get("role", "")
        btn = self._btn_user
        root = self.winfo_toplevel()

        popup = ctk.CTkToplevel(root)
        popup.overrideredirect(True)
        popup.configure(fg_color="#0f1d32")
        popup.resizable(False, False)
        self._popup = popup

        _fid = [None]

        def _close():
            if self._popup is not None:
                try:
                    self._popup.destroy()
                except Exception:
                    pass
                self._popup = None
            if _fid[0] is not None:
                try:
                    root.unbind("<Button-1>", _fid[0])
                except Exception:
                    pass
                _fid[0] = None

        # Contenido del menu
        inner = ctk.CTkFrame(popup, fg_color="#0f1d32", corner_radius=12,
                              border_width=1, border_color="#1a3050")
        inner.pack(fill="both", expand=True, padx=1, pady=1)

        # Nombre + rol
        ctk.CTkLabel(
            inner, text=cashier_name,
            font=ctk.CTkFont(size=18, weight="bold"),
            text_color="#e8edf5",
        ).pack(padx=24, pady=(16, 2))

        if role:
            ctk.CTkLabel(
                inner, text=role,
                font=ctk.CTkFont(size=13),
                text_color="#7a8ba8",
            ).pack(padx=24, pady=(0, 10))

        ctk.CTkFrame(inner, height=1, fg_color="#1a3050").pack(fill="x", padx=12)

        # Opciones de menu
        perms = self._user.get("permissions", [])
        has_all = "all" in perms

        menu_items = [
            ("  Configuracion", "config", True),
            ("  Activas", "activas", True),
            ("  Impresora", "printer", True),
        ]

        for text, view, has_perm in menu_items:
            if not has_perm:
                continue
            ctk.CTkButton(
                inner, text=text,
                font=ctk.CTkFont(size=14),
                fg_color="transparent",
                hover_color="#152540",
                text_color="#e8edf5",
                anchor="w", height=44,
                corner_radius=6,
                command=lambda v=view: [_close(), self._navigate_to(v)],
            ).pack(fill="x", padx=10, pady=(4, 0))

        ctk.CTkFrame(inner, height=1, fg_color="#1a3050").pack(fill="x", padx=12, pady=(8, 0))

        # Cerrar sesion
        ctk.CTkButton(
            inner, text="  Cerrar sesion",
            font=ctk.CTkFont(size=14, weight="bold"),
            fg_color="transparent",
            hover_color="#2a0f18",
            text_color="#ff6666",
            anchor="w", height=48,
            corner_radius=6,
            command=lambda: [_close(), self._logout()],
        ).pack(fill="x", padx=10, pady=(4, 12))

        popup.update_idletasks()

        # Posicionar debajo del boton, alineado a la izquierda
        x = btn.winfo_rootx()
        y = btn.winfo_rooty() + btn.winfo_height() + 4
        popup.geometry(f"+{x}+{y}")
        popup.lift()

        def _setup_bind():
            _fid[0] = root.bind("<Button-1>", lambda e: _close(), add="+")

        root.after(200, _setup_bind)

    def _logout(self):
        if self._on_logout:
            self._on_logout()

    # ==================================================================
    # Navegacion con control de permisos
    # ==================================================================

    def _navigate_to(self, view_name: str):
        """Navega a una vista, pidiendo autenticacion elevada si es necesario."""
        if view_name == "config":
            perms = self._user.get("permissions", [])
            if "all" in perms or "lb_paquetes" in perms:
                self._switch_view("config")
            else:
                self._request_config_auth()
        else:
            self._switch_view(view_name)

    def _request_config_auth(self):
        """Muestra el dialog de autenticacion elevada para acceder a config."""
        from ui.config_auth_dialog import ConfigAuthDialog
        ConfigAuthDialog(
            self.winfo_toplevel(),
            on_success=lambda: self._switch_view("config"),
        )

    # ==================================================================
    # Sistema de vistas
    # ==================================================================

    def _switch_view(self, view_name: str):
        # Destruir contenido actual
        if self._content is not None:
            self._content.destroy()
            self._content = None

        self._current_view = view_name
        self._update_back_btn()

        # Zona de contenido
        self._content = ctk.CTkFrame(self, fg_color="transparent")
        self._content.grid(row=1, column=0, sticky="nsew")

        if view_name == "packages":
            self._build_packages_view()
        elif view_name == "config":
            self._build_config_view()
        elif view_name == "activas":
            self._build_activas_view()
        elif view_name == "printer":
            self._build_printer_view()

    # ------------------------------------------------------------------
    # Vista: Paquetes (pantalla principal)
    # ------------------------------------------------------------------

    def _build_packages_view(self):
        from ui.package_selector import PackageSelector

        cashier = self._user.get("display_name", self._user.get("username", "caja1"))
        self._pkg_selector = PackageSelector(
            self._content,
            cashier=cashier,
            on_sale_complete=self._on_sale_complete,
            on_navigate=self._navigate_to,
            mode="sale",
        )
        self._pkg_selector.pack(fill="both", expand=True)

    def _on_sale_complete(self, result: dict):
        """Callback tras venta exitosa. Disponible externamente."""
        pass

    # ------------------------------------------------------------------
    # Vista: Configuracion (combos en modo edicion)
    # ------------------------------------------------------------------

    def _build_config_view(self):
        from ui.package_selector import PackageSelector

        # Titulo de seccion
        hdr = ctk.CTkFrame(self._content, fg_color="transparent")
        hdr.pack(fill="x", padx=16, pady=(12, 4))
        ctk.CTkLabel(
            hdr, text="Configuracion de Combos",
            font=ctk.CTkFont(size=18, weight="bold"),
            text_color="#00d4ff",
        ).pack(side="left")
        ctk.CTkLabel(
            hdr, text="Toca un combo para editarlo  |  Toca + para crear uno nuevo",
            font=ctk.CTkFont(size=11),
            text_color="#7a8ba8",
        ).pack(side="left", padx=(16, 0))

        cashier = self._user.get("display_name", self._user.get("username", "caja1"))
        pkg_sel = PackageSelector(
            self._content,
            cashier=cashier,
            mode="config",
        )
        pkg_sel.pack(fill="both", expand=True)

    # ------------------------------------------------------------------
    # Vista: Activas (pulseras activas)
    # ------------------------------------------------------------------

    def _build_activas_view(self):
        from ui.active_wristbands_tab import ActiveWristbandsTab

        active_tab = ActiveWristbandsTab(self._content)
        active_tab.pack(fill="both", expand=True)

    # ------------------------------------------------------------------
    # Vista: Impresora
    # ------------------------------------------------------------------

    def _build_printer_view(self):
        zone = self._content

        # Titulo
        ctk.CTkLabel(
            zone, text="Configuracion de Impresora",
            font=ctk.CTkFont(size=18, weight="bold"),
            text_color="#00d4ff",
        ).pack(anchor="w", padx=32, pady=(28, 4))

        ctk.CTkLabel(
            zone, text="Configura la impresora termica para recibos de venta",
            font=ctk.CTkFont(size=12),
            text_color="#7a8ba8",
        ).pack(anchor="w", padx=32, pady=(0, 20))

        # Card contenedora
        card = ctk.CTkFrame(
            zone, fg_color="#0f1d32", corner_radius=14,
            border_width=1, border_color="#1a3050",
        )
        card.pack(fill="x", padx=32, pady=(0, 16))

        # --- Toggle habilitar impresora ---
        cfg = printing.load_config()
        self._print_enabled = ctk.BooleanVar(value=cfg.get("auto_print", True))

        toggle_row = ctk.CTkFrame(card, fg_color="transparent")
        toggle_row.pack(fill="x", padx=24, pady=(20, 12))

        ctk.CTkLabel(
            toggle_row, text="Impresora habilitada",
            font=ctk.CTkFont(size=14),
            text_color="#e8edf5",
        ).pack(side="left")

        ctk.CTkSwitch(
            toggle_row,
            text="",
            variable=self._print_enabled,
            onvalue=True, offvalue=False,
            progress_color="#00d4ff",
            button_color="#e8edf5",
            command=self._on_printer_toggle,
        ).pack(side="right")

        ctk.CTkFrame(card, height=1, fg_color="#1a3050").pack(fill="x", padx=16)

        # --- Seleccion de impresora ---
        printer_row = ctk.CTkFrame(card, fg_color="transparent")
        printer_row.pack(fill="x", padx=24, pady=(16, 8))

        ctk.CTkLabel(
            printer_row, text="Impresora:",
            font=ctk.CTkFont(size=13),
            text_color="#7a8ba8",
            width=120, anchor="w",
        ).pack(side="left")

        printers = printing.get_printers() or ["(Sin impresoras)"]
        current = cfg.get("printer_name", "")
        if current and current not in printers:
            printers = [current] + printers

        self._printer_var = ctk.StringVar(value=current or printers[0])
        self._combo_printer = ctk.CTkComboBox(
            printer_row,
            variable=self._printer_var,
            values=printers,
            width=300, height=34,
            state="readonly",
        )
        self._combo_printer.pack(side="left", padx=(0, 8))

        ctk.CTkButton(
            printer_row, text="↺",
            width=34, height=34, corner_radius=6,
            fg_color="#152540", hover_color="#1a3050",
            font=ctk.CTkFont(size=14),
            command=self._refresh_printers,
        ).pack(side="left")

        # --- Tamaño de papel ---
        paper_row = ctk.CTkFrame(card, fg_color="transparent")
        paper_row.pack(fill="x", padx=24, pady=(8, 20))

        ctk.CTkLabel(
            paper_row, text="Tamaño de papel:",
            font=ctk.CTkFont(size=13),
            text_color="#7a8ba8",
            width=120, anchor="w",
        ).pack(side="left")

        self._paper_var = ctk.StringVar(value=cfg.get("paper_size", "80mm"))
        ctk.CTkComboBox(
            paper_row,
            variable=self._paper_var,
            values=["80mm", "58mm"],
            width=140, height=34,
            state="readonly",
        ).pack(side="left")

        # --- Botones ---
        btn_row = ctk.CTkFrame(zone, fg_color="transparent")
        btn_row.pack(fill="x", padx=32, pady=(8, 0))

        ctk.CTkButton(
            btn_row, text="Guardar cambios",
            width=160, height=38, corner_radius=8,
            fg_color="#00d4ff", hover_color="#00a8cc",
            text_color="#060b18",
            font=ctk.CTkFont(size=13, weight="bold"),
            command=self._save_printer_config,
        ).pack(side="left", padx=(0, 8))

        ctk.CTkButton(
            btn_row, text="Configuracion avanzada",
            width=180, height=38, corner_radius=8,
            fg_color="#152540", hover_color="#1a3050",
            text_color="#7a8ba8",
            font=ctk.CTkFont(size=12),
            command=self._open_ticket_config,
        ).pack(side="left")

        # Status
        self._lbl_printer_status = ctk.CTkLabel(
            zone, text="",
            font=ctk.CTkFont(size=11),
            text_color="#7a8ba8",
        )
        self._lbl_printer_status.pack(anchor="w", padx=32, pady=(8, 0))

    def _on_printer_toggle(self):
        pass  # Se guarda al presionar "Guardar cambios"

    def _refresh_printers(self):
        printers = printing.get_printers() or ["(Sin impresoras)"]
        self._combo_printer.configure(values=printers)
        if self._printer_var.get() not in printers:
            self._combo_printer.set(printers[0])

    def _save_printer_config(self):
        cfg = printing.load_config()
        cfg["printer_name"] = self._printer_var.get()
        cfg["auto_print"] = self._print_enabled.get()
        cfg["paper_size"] = self._paper_var.get()
        printing.save_config(cfg)
        self._lbl_printer_status.configure(
            text="Configuracion guardada.", text_color="#00e676",
        )

    def _open_ticket_config(self):
        from ui.supervisor_pin_dialog import SupervisorPinDialog
        SupervisorPinDialog(
            self.winfo_toplevel(),
            reason="Configuracion avanzada de impresora",
            accion="config_impresora",
            required_permiso="config_impresora",
            on_result=lambda ok: self._do_open_ticket_config() if ok else None,
        )

    def _do_open_ticket_config(self):
        from ui.ticket_config_dialog import TicketConfigDialog
        TicketConfigDialog(self.winfo_toplevel())

    # ==================================================================
    # API publica (para main.py)
    # ==================================================================

    def set_clock(self, time_str: str, date_str: str = ""):
        self.lbl_clock.configure(text=time_str)
        if date_str:
            self.lbl_date.configure(text=date_str)

    def set_server_status(self, reachable: bool):
        if reachable:
            self.lbl_hw_status.configure(
                text="● Servidor conectado", text_color="#00e676",
            )
        else:
            self.lbl_hw_status.configure(
                text="● Servidor desconectado", text_color="#ff4444",
            )
