"""
Dialogo de reporte diario.
Muestra el total de ventas, ingresos y desglose por paquete del dia.
Fuente primaria: GET /api/reports/daily.
Fuente secundaria (offline): wristband_tracker local.
"""
import threading
import customtkinter as ctk
from datetime import date
import api
import wristband_tracker


class ReportDialog(ctk.CTkToplevel):
    def __init__(self, parent, **kwargs):
        super().__init__(parent, **kwargs)
        self.title("Reporte del Dia")
        self.geometry("480x520")
        self.resizable(False, True)
        self.grab_set()
        self.lift()
        self.focus_force()

        # Centrar
        self.update_idletasks()
        px = parent.winfo_rootx() + parent.winfo_width()  // 2 - 240
        py = parent.winfo_rooty() + parent.winfo_height() // 2 - 260
        self.geometry(f"+{px}+{py}")

        self._build()
        self._load()

    def _build(self):
        # Titulo
        ctk.CTkLabel(
            self,
            text=f"Reporte — {date.today().strftime('%d/%m/%Y')}",
            font=ctk.CTkFont(size=17, weight="bold"),
            text_color="#4fc3f7",
        ).pack(padx=24, pady=(18, 8), anchor="w")

        # Totales
        totals_frame = ctk.CTkFrame(
            self, fg_color=("#1e2130", "#12151f"),
            corner_radius=10, border_width=1, border_color="#2a3050",
        )
        totals_frame.pack(padx=24, pady=4, fill="x")

        self._lbl_sales = ctk.CTkLabel(
            totals_frame, text="Ventas: —",
            font=ctk.CTkFont(size=14, weight="bold"),
            text_color="#e0e0e0", anchor="w",
        )
        self._lbl_sales.pack(padx=16, pady=(12, 2), anchor="w")

        self._lbl_revenue = ctk.CTkLabel(
            totals_frame, text="Ingresos: —",
            font=ctk.CTkFont(size=14, weight="bold"),
            text_color="#4caf50", anchor="w",
        )
        self._lbl_revenue.pack(padx=16, pady=(2, 12), anchor="w")

        # Desglose
        ctk.CTkLabel(
            self, text="Desglose por paquete:",
            font=ctk.CTkFont(size=13, weight="bold"),
            text_color="#aaaaaa",
        ).pack(padx=24, pady=(12, 4), anchor="w")

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

        self._lbl_empty = ctk.CTkLabel(
            self._scroll, text="Sin ventas registradas hoy.",
            font=ctk.CTkFont(size=12), text_color="#555555",
        )
        self._lbl_empty.pack(pady=20)

        # Fuente del reporte
        self._lbl_source = ctk.CTkLabel(
            self, text="", font=ctk.CTkFont(size=10), text_color="#555555"
        )
        self._lbl_source.pack(padx=24, pady=(0, 4), anchor="e")

        # Botones
        btn_row = ctk.CTkFrame(self, fg_color="transparent")
        btn_row.pack(pady=(0, 8))

        self._btn_print = ctk.CTkButton(
            btn_row, text="🖨  Imprimir Cierre",
            width=160, height=36,
            fg_color="#1b5e20", hover_color="#2e7d32",
            font=ctk.CTkFont(size=13, weight="bold"),
            command=self._print_cierre,
            state="disabled",
        )
        self._btn_print.pack(side="left", padx=(0, 8))

        ctk.CTkButton(
            btn_row, text="Cerrar",
            width=100, height=36,
            fg_color="#333333", hover_color="#444444",
            command=self.destroy,
        ).pack(side="left")

        self._lbl_print_status = ctk.CTkLabel(
            self, text="", font=ctk.CTkFont(size=11), text_color="#888888"
        )
        self._lbl_print_status.pack(pady=(0, 8))

    def _load(self):
        """Carga el reporte en un hilo para no bloquear la UI."""
        self._report_data = None
        self._lbl_sales.configure(text="Cargando...")
        threading.Thread(target=self._fetch, daemon=True).start()

    def _fetch(self):
        data = api.get_daily_report()
        if "error" in data:
            data   = self._local_report()
            source = "Fuente: datos locales (servidor no disponible)"
        else:
            source = "Fuente: servidor"
        self.after(0, lambda: self._render(data, source))

    def _print_cierre(self):
        """Imprime el cierre de caja en la impresora termica."""
        if not self._report_data:
            return
        self._btn_print.configure(state="disabled", text="Imprimiendo...")
        self._lbl_print_status.configure(text="Enviando a impresora...", text_color="#aaaaaa")

        def _do():
            try:
                import printing
                printing.ReporteCierre.desde_reporte(self._report_data)
                self.after(0, lambda: self._lbl_print_status.configure(
                    text="Impreso correctamente.", text_color="#4caf50"))
            except Exception as e:
                msg = str(e)
                self.after(0, lambda: self._lbl_print_status.configure(
                    text=f"Error: {msg}", text_color="#f44336"))
            finally:
                self.after(0, lambda: self._btn_print.configure(
                    state="normal", text="🖨  Imprimir Cierre"))

        threading.Thread(target=_do, daemon=True).start()

    def _local_report(self) -> dict:
        """Genera un reporte minimo desde los datos en memoria."""
        today = date.today().isoformat()
        all_entries = wristband_tracker.get_all()
        by_pkg: dict[str, dict] = {}
        total_revenue = 0.0
        total_sales = 0

        for e in all_entries:
            # Solo contar devueltas (ventas completadas)
            # En modo offline contamos todas las activas + devueltas como vendidas
            pkg_id   = e.get("package_id", "custom")
            pkg_name = e.get("package_name", pkg_id)
            # Obtener precio: guardado en el paquete, o 0
            # (sale_dialog guarda "amount" en el entry solo si lo recibimos del server,
            #  en modo offline no lo guardamos — reportamos 0 si no hay info)
            amount = 0.0

            if pkg_id not in by_pkg:
                by_pkg[pkg_id] = {"name": pkg_name, "count": 0, "subtotal": 0.0}
            by_pkg[pkg_id]["count"] += 1
            by_pkg[pkg_id]["subtotal"] += amount
            total_revenue += amount
            total_sales += 1

        return {
            "date":          today,
            "total_sales":   total_sales,
            "total_revenue": total_revenue,
            "by_package":    list(by_pkg.values()),
        }

    def _render(self, data: dict, source: str):
        self._report_data = data
        self._btn_print.configure(state="normal")
        total_sales   = data.get("total_sales", 0)
        total_revenue = data.get("total_revenue", 0.0)
        by_package    = data.get("by_package", [])

        self._lbl_sales.configure(
            text=f"Ventas totales: {total_sales}",
        )
        self._lbl_revenue.configure(
            text=f"Ingresos: ${total_revenue:,.2f}",
        )
        self._lbl_source.configure(text=source)

        # Limpiar scroll
        for w in self._scroll.winfo_children():
            w.destroy()

        if not by_package:
            ctk.CTkLabel(
                self._scroll, text="Sin ventas registradas hoy.",
                font=ctk.CTkFont(size=12), text_color="#555555",
            ).pack(pady=20)
            return

        # Cabecera
        hdr = ctk.CTkFrame(
            self._scroll, fg_color=("#1a1a2e", "#0a0a1a"), corner_radius=6
        )
        hdr.pack(fill="x", pady=(0, 4), padx=2)
        for text, width in [("Paquete", 200), ("Cantidad", 80), ("Subtotal", 100)]:
            ctk.CTkLabel(
                hdr, text=text, width=width,
                font=ctk.CTkFont(size=11, weight="bold"),
                text_color="#4fc3f7", anchor="center",
            ).pack(side="left", padx=6, pady=6)

        # Filas
        for pkg in by_package:
            row = ctk.CTkFrame(
                self._scroll, fg_color=("gray82", "#12151f"), corner_radius=6
            )
            row.pack(fill="x", pady=2, padx=2)

            ctk.CTkLabel(
                row, text=pkg.get("name", "—"), width=200,
                font=ctk.CTkFont(size=12), text_color="#e0e0e0", anchor="w",
            ).pack(side="left", padx=(12, 4), pady=6)

            ctk.CTkLabel(
                row, text=str(pkg.get("count", 0)), width=80,
                font=ctk.CTkFont(size=12), text_color="#cccccc", anchor="center",
            ).pack(side="left", padx=4)

            subtotal = pkg.get("subtotal", 0.0)
            ctk.CTkLabel(
                row, text=f"${subtotal:,.2f}", width=100,
                font=ctk.CTkFont(size=12, weight="bold"),
                text_color="#4caf50", anchor="center",
            ).pack(side="left", padx=4)
