"""
Catalog navigation screen for the NEXUS AUTOPARTS console application.

Provides a three-level drill-down through the parts hierarchy:
Categories -> Groups -> Parts.  An optional vehicle filter (mye_id)
restricts the parts list to those that fit a specific vehicle
configuration.
"""

from console.core.screens import Screen
from console.core.keybindings import Key
from console.config import APP_NAME, VERSION
from console.utils.formatting import truncate


# Footer labels for each navigation level
_FOOTER_CATEGORIES = [
    ("1-9", "Seleccionar"),
    ("Filtro", "Teclear"),
    ("F10", "Menu"),
    ("ESC", "Atras"),
]

_FOOTER_GROUPS = [
    ("1-9", "Seleccionar"),
    ("Filtro", "Teclear"),
    ("F10", "Menu"),
    ("ESC", "Atras"),
]

_FOOTER_PARTS = [
    ("1-9", "Ver parte"),
    ("ENTER", "Ver parte"),
    ("PgUp/Dn", "Paginar"),
    ("ESC", "Atras"),
]


class CatalogoScreen(Screen):
    """Hierarchical catalog browser: Categories -> Groups -> Parts."""

    def __init__(self):
        super().__init__(name="catalogo", title="Catalogo")
        self._filter_text = ""
        self._selected = 0
        self._items = []
        self._parts_data = []
        self._selected_part = 0

    # ------------------------------------------------------------------
    # Helpers
    # ------------------------------------------------------------------

    def _ensure_defaults(self, context):
        """Set default context values if missing."""
        context.setdefault("level", "categories")
        context.setdefault("mye_id", None)
        context.setdefault("brand", "")
        context.setdefault("model", "")
        context.setdefault("year", "")
        context.setdefault("engine", "")
        context.setdefault("category_id", None)
        context.setdefault("category_name", "")
        context.setdefault("group_id", None)
        context.setdefault("group_name", "")
        context.setdefault("page", 1)
        context.setdefault("per_page", 15)

    def _build_header_title(self, context):
        """Build the header title based on context."""
        level = context["level"]
        parts = []

        # Vehicle info if available
        if context.get("brand"):
            vehicle = " ".join(
                filter(None, [
                    context["brand"],
                    context["model"],
                    str(context["year"]) if context["year"] else "",
                ])
            )
            parts.append(vehicle)

        if level == "categories":
            parts.append("Categorias")
        elif level == "groups":
            parts.append(context.get("category_name", "Grupos"))
        elif level == "parts":
            cat = context.get("category_name", "")
            grp = context.get("group_name", "")
            if cat and grp:
                parts.append(f"{cat} > {grp}")
            elif grp:
                parts.append(grp)

        return " — ".join(parts) if parts else "CATALOGO DE CATEGORIAS"

    def _load_categories(self, db):
        """Load and filter categories."""
        categories = db.get_categories()
        if self._filter_text:
            ft = self._filter_text.upper()
            categories = [
                c for c in categories
                if ft in (c.get("name_es") or c.get("name") or "").upper()
                or ft in (c.get("name") or "").upper()
            ]
        self._items = [
            (str(i + 1), c.get("name_es") or c.get("name", ""), c["id"])
            for i, c in enumerate(categories)
        ]

    def _load_groups(self, db, category_id):
        """Load and filter groups for a category."""
        groups = db.get_groups(category_id)
        if self._filter_text:
            ft = self._filter_text.upper()
            groups = [
                g for g in groups
                if ft in (g.get("name_es") or g.get("name") or "").upper()
                or ft in (g.get("name") or "").upper()
            ]
        self._items = [
            (str(i + 1), g.get("name_es") or g.get("name", ""), g["id"])
            for i, g in enumerate(groups)
        ]

    def _load_parts(self, db, context):
        """Load parts for the current group/vehicle with pagination."""
        self._parts_data = db.get_parts(
            group_id=context.get("group_id"),
            mye_id=context.get("mye_id"),
            page=context.get("page", 1),
            per_page=context.get("per_page", 15),
        )

    def _reset_filter(self):
        """Reset filter text and selection."""
        self._filter_text = ""
        self._selected = 0

    # ------------------------------------------------------------------
    # Render
    # ------------------------------------------------------------------

    def render(self, context, db, renderer):
        self._ensure_defaults(context)
        level = context["level"]

        # Header
        header_title = self._build_header_title(context)
        renderer.draw_header(
            f" {APP_NAME} v{VERSION}",
            f" {header_title} ",
        )

        if level == "categories":
            self._load_categories(db)
            display_items = [(num, label) for num, label, _id in self._items]
            renderer.draw_filter_list(
                display_items,
                self._filter_text,
                self._selected,
                title="CATALOGO DE CATEGORIAS",
            )
            renderer.draw_footer(_FOOTER_CATEGORIES)

        elif level == "groups":
            self._load_groups(db, context["category_id"])
            display_items = [(num, label) for num, label, _id in self._items]
            renderer.draw_filter_list(
                display_items,
                self._filter_text,
                self._selected,
                title=context.get("category_name", "GRUPOS"),
            )
            renderer.draw_footer(_FOOTER_GROUPS)

        elif level == "parts":
            self._load_parts(db, context)
            headers = ["NUMERO OEM", "DESCRIPCION", "GRUPO", "ALT"]
            widths = [18, 30, 18, 5]
            rows = []
            for p in self._parts_data:
                alts = len(db.get_alternatives(p["id"]))
                rows.append((
                    truncate(p.get("oem_part_number", ""), 18),
                    truncate(
                        p.get("name_es") or p.get("name", ""), 30
                    ),
                    truncate(p.get("group_name", ""), 18),
                    str(alts) if alts > 0 else "",
                ))

            page = context.get("page", 1)
            renderer.draw_table(
                headers,
                rows,
                widths,
                page_info={"page": page, "total_pages": page, "total_rows": len(rows)},
                selected_row=self._selected_part,
            )
            renderer.draw_footer(_FOOTER_PARTS)

    # ------------------------------------------------------------------
    # Key handling
    # ------------------------------------------------------------------

    def on_key(self, key, context, db, renderer, nav):
        self._ensure_defaults(context)
        level = context["level"]

        if level in ("categories", "groups"):
            return self._handle_filter_level(key, context)
        elif level == "parts":
            return self._handle_parts_level(key, context)

        return None

    def _handle_filter_level(self, key, context):
        """Handle keys for categories and groups levels (filter list)."""
        level = context["level"]

        # ESC: go back
        if key == Key.ESCAPE:
            if level == "groups":
                context["level"] = "categories"
                context["category_id"] = None
                context["category_name"] = ""
                self._reset_filter()
                return None
            return "back"

        # Arrow navigation
        if key == Key.UP:
            if self._selected > 0:
                self._selected -= 1
            return None

        if key == Key.DOWN:
            if self._items and self._selected < len(self._items) - 1:
                self._selected += 1
            return None

        # ENTER: select current item
        if key == Key.ENTER:
            if self._items and 0 <= self._selected < len(self._items):
                return self._select_item(context, self._selected)
            return None

        # Number keys: direct selection (1-9)
        if 49 <= key <= 57:  # '1'..'9'
            idx = key - 49  # 0-based
            if 0 <= idx < len(self._items):
                return self._select_item(context, idx)
            return None

        # Backspace: remove last filter character
        if key in (Key.BACKSPACE, 8):
            if self._filter_text:
                self._filter_text = self._filter_text[:-1]
                self._selected = 0
            elif context["level"] == "groups":
                context["level"] = "categories"
                context["category_id"] = None
                context["category_name"] = ""
                self._reset_filter()
            else:
                return "back"
            return None

        # Printable characters: add to filter
        if 32 <= key <= 126:
            self._filter_text += chr(key)
            self._selected = 0
            return None

        return None

    def _select_item(self, context, idx):
        """Handle selection of an item at the given index."""
        _num, label, item_id = self._items[idx]
        level = context["level"]

        if level == "categories":
            context["level"] = "groups"
            context["category_id"] = item_id
            context["category_name"] = label
            self._reset_filter()
            return None

        elif level == "groups":
            context["level"] = "parts"
            context["group_id"] = item_id
            context["group_name"] = label
            context["page"] = 1
            self._selected_part = 0
            self._reset_filter()
            return None

        return None

    def _handle_parts_level(self, key, context):
        """Handle keys for the parts table level."""
        # ESC: go back to groups
        if key == Key.ESCAPE:
            context["level"] = "groups"
            context["group_id"] = None
            context["group_name"] = ""
            self._selected_part = 0
            self._reset_filter()
            return None

        # Arrow navigation
        if key == Key.UP:
            if self._selected_part > 0:
                self._selected_part -= 1
            return None

        if key == Key.DOWN:
            if self._parts_data and self._selected_part < len(self._parts_data) - 1:
                self._selected_part += 1
            return None

        # ENTER: view selected part detail
        if key == Key.ENTER:
            if self._parts_data and 0 <= self._selected_part < len(self._parts_data):
                part = self._parts_data[self._selected_part]
                return ("parte_detalle", {"part_id": part["id"]}, "Parte")
            return None

        # Number keys: direct selection (1-9)
        if 49 <= key <= 57:  # '1'..'9'
            idx = key - 49  # 0-based
            if 0 <= idx < len(self._parts_data):
                part = self._parts_data[idx]
                return ("parte_detalle", {"part_id": part["id"]}, "Parte")
            return None

        # PgDn: next page
        if key == Key.PGDN:
            context["page"] = context.get("page", 1) + 1
            self._selected_part = 0
            return None

        # PgUp: previous page
        if key == Key.PGUP:
            if context.get("page", 1) > 1:
                context["page"] = context["page"] - 1
                self._selected_part = 0
            return None

        return None
