"""
D1 — Discover. The Clerk's shelf.

A featured collection as a split-pane hero on top, then an edge-to-edge rail of
"shelves you might not have noticed" — other collections + series, ending in the
peach "Bring your own" door into Add games. Reachable via the global nav.
"""

from __future__ import annotations

import pygame

from ..design import tokens as t
from ..shared import fonts, render, icons
from ..widgets import chrome, components as c, nav, hero as herow

BODY_TOP = t.Space.STATUS_BAR_HEIGHT
BODY_BOT = t.VIEWPORT_HEIGHT - t.Space.FOOTER_HINT_HEIGHT

# Layout (640×480). The chip strip sits between the hero and the rail —
# 7 curated chips backed by the enrichment vocabularies (mood/when/tag/
# difficulty). Hero is 32px shorter than the v3 spec to make room for
# the chips; rail position is unchanged so the bottom poster line stays
# consistent with Library/Add-games' bottom edge.
HERO = pygame.Rect(0, BODY_TOP, t.VIEWPORT_WIDTH, 178)     # 28..206
CHIP_Y = 212                                                 # 32-px strip
HEAD_Y = 250
CARD_X = 14
CARD_W, CARD_AH, CARD_GAP = 116, 150, 1
CARD_Y = 274

# Curated chip set — covers the four enrichment dimensions in one row.
# `(label, (kind, value))` shape mirrors addgames' chip tuples.
# Picked for diverse vocab + plenty of inventory in a 977-game library
# (no dead chips). The user-facing label is shorter than the canonical
# vocab token where the chip would otherwise look like jargon
# ("Speedrunner" vs "speedrunner-favorite").
CHIPS = (
    ("Cozy",              ("mood",       "cozy")),
    ("Tense",             ("mood",       "tense")),
    ("Quick break",       ("when",       "quick-break")),
    ("Couch co-op",       ("when",       "couch-co-op")),
    ("Newcomer-friendly", ("tag",        "newcomer-friendly")),
    ("Speedrunner",       ("tag",        "speedrunner-favorite")),
    ("Punishing",         ("difficulty", "punishing")),
)


class DiscoverScreen:
    name = "discover"

    def __init__(self, app):
        self.app = app
        self.nav = nav.NavBar("discover")
        cat = app.catalog
        cols = cat.collections
        self.featured = cols[0] if cols else None
        self.feat_games = cat.collection_games(self.featured["id"]) if self.featured else []

        # rail = remaining collections + a few series + the add-games door
        self.shelves = []
        for col in cols[1:]:
            games = cat.collection_games(col["id"])
            if games:
                self.shelves.append({"kind": "collection", "id": col["id"],
                                     "title": col["title"], "box": games[0],
                                     "sub": f"{len(games)} games · {col.get('aside', '')}"})
        sg = list(cat.series_groups().items())
        for name, games in sg[:4]:
            self.shelves.append({"kind": "series", "name": name, "title": f"{name} series",
                                 "box": games[0], "sub": f"{len(games)} entries"})
        if sg:
            self.shelves.append({"kind": "series_index", "title": "All series",
                                 "box": sg[0][1][0], "sub": f"{len(sg)} franchises"})
        self.shelves.append({"kind": "add", "title": "add games", "sub": "from outside"})

        # Three vertical "areas" — hero (top), chips (middle), rail (bottom).
        # Inside each, a horizontal cursor tracks the selected element.
        self.area = "hero"             # "hero" | "chips" | "rail"
        self.cidx = 0                   # chip cursor
        self.col = 0                    # rail cursor
        self.start = 0

    # ── input ────────────────────────────────────────────────────────
    def on_action(self, action):
        if self.nav.handle(self.app, action):
            return
        n = len(self.shelves)
        if action == "up":
            if self.area == "hero":
                self.nav.focus()
            elif self.area == "chips":
                self.area = "hero"
            else:
                self.area = "chips"
        elif action == "down":
            if self.area == "hero":
                self.area = "chips"
            elif self.area == "chips" and n:
                self.area = "rail"
        elif action == "left":
            if self.area == "chips":
                self.cidx = max(0, self.cidx - 1)
            elif self.area == "rail":
                self.col = max(0, self.col - 1)
        elif action == "right":
            if self.area == "chips":
                self.cidx = min(len(CHIPS) - 1, self.cidx + 1)
            elif self.area == "rail":
                self.col = min(n - 1, self.col + 1)
        elif action in ("azprev", "aznext"):       # right stick → fast scroll the active row
            step = 5 if action == "aznext" else -5
            if self.area == "rail":
                self.col = max(0, min(n - 1, self.col + step))
            elif self.area == "chips":
                self.cidx = max(0, min(len(CHIPS) - 1, self.cidx + step))
        elif action == "a":
            self._activate()
        elif action == "y":
            self.app.go_tab("search")
        elif action == "b":
            self.app.go_tab("home")

    def _activate(self):
        if self.area == "hero":
            if self.featured:
                self.app.open_collection(self.featured["id"])
            return
        if self.area == "chips":
            label, (kind, value) = CHIPS[self.cidx]
            games = self.app.catalog.games_by_filter(kind, value)
            self.app.open_filter(label, games)
            return
        item = self.shelves[self.col]
        if item["kind"] == "collection":
            self.app.open_collection(item["id"])
        elif item["kind"] == "series":
            self.app.open_series(item["name"])
        elif item["kind"] == "series_index":
            self.app.open_series_index()
        else:
            self.app.open_addgames()

    def update(self, dt_ms):
        pass

    # ── draw ─────────────────────────────────────────────────────────
    def draw(self, surf):
        self.nav.draw(surf, app=self.app)
        navf = self.nav.focused
        self._draw_hero(surf,  self.area == "hero"  and not navf)
        self._draw_chips(surf, self.area == "chips" and not navf)
        c.rail_header(surf, CARD_X, HEAD_Y, "Shelves you might not have noticed",
                      f"{len(self.shelves)} more", max_w=t.VIEWPORT_WIDTH - 2 * CARD_X)
        self._draw_rail(surf,  self.area == "rail"  and not navf)
        chrome.footer_hints(surf, [("A", "Open"), ("B", "Home"), ("Y", "Search")])

    def _draw_hero(self, surf, focused):
        if not self.featured:
            return
        cat = self.app.catalog
        ce = cat.continue_entries()
        last = ce[0]["game"]["title"] if ce else None
        eyebrow = f"If you finished {last[:18]}…" if last else "The Clerk's shelf tonight"
        first = self.feat_games[0] if self.feat_games else None
        art = cat.asset_path(first, "hero") if first else None
        quote = c.first_sentence(first.get("description", ""), cap=120) if first else ""
        herow.split_hero(surf, HERO, art_path=art, eyebrow=eyebrow,
                         title=self.featured["title"], title_style=t.Type.DISPLAY,
                         title_lines=2, meta=["collection", f"{len(self.feat_games)} picks"],
                         quote=quote, quote_lines=2, cta_label="Open the shelf",
                         cta_focused=focused, art_focus=(0.5, 0.35))

    def _draw_chips(self, surf, focused):
        """Horizontal chip strip backed by the enrichment vocab. Same
        pill aesthetic as Add-games' filter chips so the user reads them
        as "tap-to-narrow" affordances rather than ornament. There is no
        'currently applied' state — each chip is a one-tap deep-link to
        a filtered list — so we only render the cursor outline (focused
        chip) and the unfocused pill body."""
        gap = 5
        # Measure once per chip; nothing here changes between frames
        # for a given chip set, but it keeps the layout code uniform
        # with Add-games' chip strip (same idioms, same maintenance).
        widths = [fonts.measure(t.Type.BTN, lbl)[0] + 18 for lbl, _ in CHIPS]
        xs, acc = [], CARD_X
        for w in widths:
            xs.append(acc); acc += w + gap

        # Scroll so the focused chip is fully visible if the strip
        # overflows the viewport.
        off = 0
        if focused and CHIPS:
            cx, cw = xs[self.cidx], widths[self.cidx]
            right = t.VIEWPORT_WIDTH - CARD_X
            if cx < CARD_X:
                off = cx - CARD_X
            if cx + cw - off > right:
                off = cx + cw - right

        prev = surf.get_clip()
        surf.set_clip(pygame.Rect(0, CHIP_Y - 2, t.VIEWPORT_WIDTH, 28))
        for i, (label, spec) in enumerate(CHIPS):
            x = xs[i] - off
            cw = widths[i]
            if x + cw < 0 or x > t.VIEWPORT_WIDTH:
                continue
            is_cur = (focused and i == self.cidx)
            # Color hints the dimension the chip filters on — mood = peach,
            # when = cyan, tag = rose, difficulty = muted. Subtle but a
            # visual mnemonic across the strip.
            kind = spec[0]
            base_col = {
                "mood":       t.Color.ACCENT_PEACH,
                "when":       t.Color.ACCENT_CYAN,
                "tag":        t.Color.ACCENT_ROSE,
                "difficulty": t.Color.TEXT_SECONDARY,
            }.get(kind, t.Color.TEXT_MUTED)
            txt_col = t.Color.TEXT_PRIMARY if is_cur else base_col
            if is_cur:
                pygame.draw.rect(surf, t.with_alpha(base_col, 0.15),
                                 (x, CHIP_Y, cw, 22),
                                 border_radius=t.Radius.PILL)
                pygame.draw.rect(surf, t.with_alpha(t.Color.TEXT_PRIMARY, 0.30),
                                 (x, CHIP_Y, cw, 22), width=1,
                                 border_radius=t.Radius.PILL)
            else:
                pygame.draw.rect(surf, t.with_alpha(base_col, 0.08),
                                 (x, CHIP_Y, cw, 22),
                                 border_radius=t.Radius.PILL)
            label_h = fonts.measure(t.Type.BTN, label)[1]
            surf.blit(fonts.render(t.Type.BTN, label, txt_col),
                      (x + 9, CHIP_Y + (22 - label_h) // 2))
        surf.set_clip(prev)

    def _draw_rail(self, surf, active):
        n = len(self.shelves)
        view = (t.VIEWPORT_WIDTH - CARD_X) // (CARD_W + CARD_GAP)
        self.start = max(0, min(self.col - view + 2, max(0, n - view))) if active else 0
        for k in range(self.start, min(self.start + view + 1, n)):
            x = CARD_X + (k - self.start) * (CARD_W + CARD_GAP)
            self._card(surf, x, self.shelves[k],
                       focused=(active and k == self.col),
                       dim=(active and k != self.col))

    def _card(self, surf, x, item, *, focused, dim):
        ar = pygame.Rect(x, CARD_Y, CARD_W, CARD_AH)
        if item["kind"] != "add":
            c.poster_tile(surf, ar, path=self.app.catalog.asset_path(item["box"], "box"),
                          name=item["title"], sub=item["sub"], focused=focused, dim=dim)
            return
        # the peach "bring your own" door — a CTA, not a poster
        body = pygame.Surface((CARD_W, CARD_AH), pygame.SRCALPHA)
        pygame.draw.rect(body, t.with_alpha(t.Color.ACCENT_PEACH, 0.07),
                         (0, 0, CARD_W, CARD_AH), border_radius=8)
        pygame.draw.rect(body, t.with_alpha(t.Color.ACCENT_PEACH, 0.30),
                         (0, 0, CARD_W, CARD_AH), width=1, border_radius=8)
        box = 32
        ib = pygame.Surface((box, box), pygame.SRCALPHA)
        pygame.draw.rect(ib, t.with_alpha(t.Color.ACCENT_PEACH, 0.14), (0, 0, box, box),
                         border_radius=8)
        pygame.draw.rect(ib, t.with_alpha(t.Color.ACCENT_PEACH, 0.35), (0, 0, box, box),
                         width=1, border_radius=8)
        ic = icons.icon("ph-plus-circle", 18, t.Color.ACCENT_PEACH)
        ib.blit(ic, ((box - 18) // 2, (box - 18) // 2))
        body.blit(ib, ((CARD_W - box) // 2, CARD_AH // 2 - 28))
        eye = fonts.render(t.Type.EYEBROW, "SOURCES", t.Color.ACCENT_PEACH)
        body.blit(eye, ((CARD_W - eye.get_width()) // 2, CARD_AH // 2 + 10))
        ttl = fonts.render(t.Type.LABEL, "Bring your own", t.Color.TEXT_PRIMARY)
        body.blit(ttl, ((CARD_W - ttl.get_width()) // 2, CARD_AH // 2 + 26))
        if focused:
            glow, gpos = render.focus_glow(ar, 8); surf.blit(glow, gpos)
        surf.blit(body, ar.topleft)
        if focused:
            surf.blit(render.gradient_border((CARD_W, CARD_AH), 8), ar.topleft)
