"""Read-only list of pallets currently parked in the non-shelved virtual cell."""

from __future__ import annotations

import tkinter as tk
from tkinter import messagebox, ttk
from typing import Any

import customtkinter as ctk

from busy_overlay import InlineBusyOverlay
from gestione_aree import AsyncRunner
from locale_text import load_locale_catalog, text as loc_text
from runtime_support import log_exception
from ui_tables import style_treeview, zebra_tag
from ui_theme import theme_color, theme_font, theme_section, theme_value
from version_info import module_version, versioned_title
from window_placement import place_window_fullsize_below_parent_later

__version__ = module_version(__name__)


SQL_NON_SCAFFALATE = """
WITH trace_rows AS (
    SELECT
        Pallet,
        MIN(Lotto) AS Lotto,
        MIN(Prodotto) AS Prodotto,
        MIN(Descrizione) AS Descrizione
    FROM dbo.vXTracciaProdotti
    GROUP BY Pallet
)
SELECT
    g.BarcodePallet AS UDC,
    g.IDCella,
    CONCAT(RTRIM(c.Corsia), '.', RTRIM(CAST(c.Colonna AS varchar(32))), '.', RTRIM(CAST(c.Fila AS varchar(32)))) AS Ubicazione,
    t.Lotto,
    t.Prodotto,
    t.Descrizione
FROM dbo.XMag_GiacenzaPallet AS g
LEFT JOIN dbo.Celle AS c
  ON c.ID = g.IDCella
LEFT JOIN trace_rows AS t
  ON t.Pallet COLLATE Latin1_General_CI_AS =
     g.BarcodePallet COLLATE Latin1_General_CI_AS
WHERE g.IDCella = 1000
ORDER BY g.BarcodePallet;
"""


def _rows_to_dicts(res: dict[str, Any] | None) -> list[dict[str, Any]]:
    if not isinstance(res, dict):
        return []
    rows = res.get("rows") or []
    cols = res.get("columns") or []
    if rows and isinstance(rows[0], dict):
        return [row for row in rows if isinstance(row, dict)]
    out: list[dict[str, Any]] = []
    for row in rows:
        if isinstance(row, (list, tuple)) and cols:
            out.append({str(cols[i]): row[i] for i in range(min(len(cols), len(row)))})
    return out


class UDCNonScaffalateWindow(ctk.CTkToplevel):
    """Window showing current UDCs in the conventional 5E1.1 non-shelved cell."""

    def __init__(self, parent: tk.Widget, db_client, session=None):
        super().__init__(parent)
        self.db_client = db_client
        self.session = session
        self._theme = theme_section("non_shelved_window", theme_section("search_window", {}))
        self._locale_catalog = load_locale_catalog()
        self._async = AsyncRunner(self)
        self._busy = InlineBusyOverlay(self, self._theme)
        self._load_in_progress = False

        self.title(versioned_title(loc_text("non_shelved.title", catalog=self._locale_catalog, default="UDC non scaffalate"), __name__))
        self.geometry(str(theme_value(self._theme, "window_geometry", "1000x650")))
        minsize = theme_value(self._theme, "window_minsize", [820, 520])
        self.minsize(int(minsize[0]), int(minsize[1]))
        try:
            self.configure(fg_color=theme_color(self._theme, "window_fg_color", ("#efefef", "#2f2f2f")))
        except Exception:
            pass

        self._build_ui()
        self.after(250, self._load)

    def _is_alive(self) -> bool:
        try:
            return bool(self.winfo_exists())
        except tk.TclError:
            return False

    def _hide_busy_safe(self) -> None:
        try:
            self._busy.hide()
        except Exception as exc:
            log_exception(__name__, exc, context="hide busy UDC non scaffalate")

    def _build_ui(self) -> None:
        self.grid_rowconfigure(1, weight=1)
        self.grid_columnconfigure(0, weight=1)

        top = ctk.CTkFrame(
            self,
            fg_color=theme_color(self._theme, "toolbar_frame_fg_color", ("#d7d7d7", "#3b3b3b")),
        )
        top.grid(row=0, column=0, sticky="ew", padx=8, pady=8)
        top.grid_columnconfigure(2, weight=1)

        label_font = theme_font(self._theme, "toolbar_label_font", ("Segoe UI", 10, "bold"))
        button_font = theme_font(self._theme, "toolbar_button_font", ("Segoe UI", 10, "bold"))
        ctk.CTkLabel(
            top,
            text=loc_text("non_shelved.subtitle", catalog=self._locale_catalog, default="Cella convenzionale: 5E1.1 (codice 1000 / barcode 9001000)"),
            font=label_font,
        ).grid(row=0, column=0, sticky="w", padx=(0, 12))
        ctk.CTkButton(
            top,
            text=loc_text("non_shelved.refresh", catalog=self._locale_catalog, default="Aggiorna"),
            command=self._load,
            font=button_font,
        ).grid(row=0, column=1, sticky="w")

        wrap = ctk.CTkFrame(self)
        wrap.grid(row=1, column=0, sticky="nsew", padx=8, pady=(0, 8))
        wrap.grid_rowconfigure(0, weight=1)
        wrap.grid_columnconfigure(0, weight=1)

        cols = ("UDC", "IDCella", "Ubicazione", "Lotto", "Prodotto", "Descrizione")
        self.tree = ttk.Treeview(wrap, columns=cols, show="headings")
        headings = {
            "UDC": ("UDC", 120, "w"),
            "IDCella": ("IDCella", 80, "e"),
            "Ubicazione": ("Ubicazione", 130, "w"),
            "Lotto": ("Lotto", 140, "w"),
            "Prodotto": ("Prodotto", 150, "w"),
            "Descrizione": ("Descrizione", 340, "w"),
        }
        for col in cols:
            text, width, anchor = headings[col]
            self.tree.heading(col, text=text)
            self.tree.column(col, width=width, anchor=anchor, stretch=True)
        style_treeview(
            self.tree,
            style_name="NonShelved.Treeview",
            rowheight=22,
            font=("", 9),
            heading_font=("", 9, "bold"),
        )

        sy = ttk.Scrollbar(wrap, orient="vertical", command=self.tree.yview)
        sx = ttk.Scrollbar(wrap, orient="horizontal", command=self.tree.xview)
        self.tree.configure(yscrollcommand=sy.set, xscrollcommand=sx.set)
        self.tree.grid(row=0, column=0, sticky="nsew")
        sy.grid(row=0, column=1, sticky="ns")
        sx.grid(row=1, column=0, sticky="ew")

    def _load(self) -> None:
        if self._load_in_progress or not self._is_alive():
            return

        async def job():
            return await self.db_client.query_json(SQL_NON_SCAFFALATE, as_dict_rows=True)

        self._load_in_progress = True
        try:
            self._busy.show(loc_text("non_shelved.busy", catalog=self._locale_catalog, default="Carico UDC non scaffalate..."))
            self._async.run(job(), self._on_loaded, self._on_error)
        except Exception as exc:
            self._load_in_progress = False
            self._hide_busy_safe()
            log_exception(__name__, exc, context="avvio caricamento UDC non scaffalate")
            messagebox.showerror(
                loc_text("non_shelved.title", catalog=self._locale_catalog, default="UDC non scaffalate"),
                str(exc),
                parent=self if self._is_alive() else None,
            )

    def _on_loaded(self, res: dict[str, Any] | None) -> None:
        self._load_in_progress = False
        self._hide_busy_safe()
        if not self._is_alive():
            return
        try:
            rows = _rows_to_dicts(res)
            self.tree.delete(*self.tree.get_children(""))
            for index, row in enumerate(rows):
                self.tree.insert(
                    "",
                    "end",
                    values=(
                        row.get("UDC") or "",
                        row.get("IDCella") or "",
                        row.get("Ubicazione") or "",
                        row.get("Lotto") or "",
                        row.get("Prodotto") or "",
                        row.get("Descrizione") or "",
                    ),
                    tags=(zebra_tag(index),),
                )
        except Exception as exc:
            log_exception(__name__, exc, context="render UDC non scaffalate")
            messagebox.showerror(
                loc_text("non_shelved.title", catalog=self._locale_catalog, default="UDC non scaffalate"),
                str(exc),
                parent=self,
            )

    def _on_error(self, exc: BaseException) -> None:
        self._load_in_progress = False
        self._hide_busy_safe()
        log_exception(__name__, exc, context="query UDC non scaffalate")
        if not self._is_alive():
            return
        messagebox.showerror(
            loc_text("non_shelved.title", catalog=self._locale_catalog, default="UDC non scaffalate"),
            str(exc),
            parent=self,
        )


def open_udc_non_scaffalate_window(parent: tk.Misc, db_client, session=None) -> tk.Misc:
    """Open the non-shelved UDC window."""

    win = UDCNonScaffalateWindow(parent, db_client, session=session)
    place_window_fullsize_below_parent_later(parent, win)
    return win
