"""
H1 — Home (design v3). The Clerk's stage.

Split-pane 21:9 hero (text left on near-black, key-art right with a 90° fade)
+ edge-to-edge poster rails whose focus is lift + blur + info overlay. Bigger
type, quiet 28px chrome — legible in hand on a 3.5" screen. L/R cycles the pick.
"""

from __future__ import annotations

import pygame

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

BODY_TOP = t.Space.STATUS_BAR_HEIGHT          # 28
BODY_BOT = t.VIEWPORT_HEIGHT - t.Space.FOOTER_HINT_HEIGHT   # 452
VIEWPORT_H = BODY_BOT - BODY_TOP              # 424

HERO_H = 200
RAILS_CY = HERO_H + 8
RAIL_HEADER_H = 22
TILE_W, TILE_ART_H = 128, 160     # genre/playtime overlay the art; only name sits below
TILE_GAP = 1
TILE_BELOW_H = 18                  # just the name below the card
TILE_CELL_H = TILE_ART_H + 4 + TILE_BELOW_H
RAIL_CONTENT_H = RAIL_HEADER_H + 6 + TILE_CELL_H
RAIL_STRIDE = RAIL_CONTENT_H + 10


class HomeScreen:
    name = "home"

    def __init__(self, app, cold=None):
        self.app = app
        cat = app.catalog
        ce = cat.continue_entries()
        # H0 cold-start = a fresh device with nothing played yet
        self.cold = (not ce) if cold is None else cold
        self._cont = {e["game"]["id"]: e for e in ce}
        self.featured = ([e["game"] for e in ce]
                         or cat.collection_games("essentials")[:6] or cat.games[:6])
        self.hero_idx = 0

        rails = []
        if ce:
            rails.append(("Continue where you left off", f"{len(ce)} games",
                          [e["game"] for e in ce]))
        for col in cat.collections:
            rails.append((col["title"], col.get("aside", ""), cat.collection_games(col["id"])))
        favs = cat.favorites()
        if favs:
            rails.append(("Your favorites", f"{len(favs)}", favs))
        self.rails = rails

        # H0 doors → Library / Add games
        self.doors = [("library", "Wander the shelf", "every game, by system", "ph-list"),
                      ("add", "Bring your own", "from an outside source", "ph-plus-circle")]
        self.row = 0
        self.cols = [0] * len(rails)
        self.dcol = 0
        self.scroll = 0
        self.nav = nav.NavBar("home")

    # ── input ────────────────────────────────────────────────────────
    def on_action(self, action):
        if self.nav.handle(self.app, action):
            return
        if self.cold:
            self._cold_action(action)
            return
        if action == "up":
            if self.row == 0:
                self.nav.focus()
            else:
                self.row -= 1
        elif action == "down":
            self.row = min(len(self.rails), self.row + 1)
        elif action == "left":
            if self.row > 0:
                i = self.row - 1
                self.cols[i] = max(0, self.cols[i] - 1)
        elif action == "right":
            if self.row > 0:
                i = self.row - 1
                self.cols[i] = min(len(self.rails[i][2]) - 1, self.cols[i] + 1)
        elif action in ("azprev", "aznext"):       # right stick → fast scroll the rail
            if self.row > 0:
                i = self.row - 1
                step = 5 if action == "aznext" else -5
                self.cols[i] = max(0, min(len(self.rails[i][2]) - 1, self.cols[i] + step))
        elif action in ("l", "r") and self.row == 0 and self.featured:
            self.hero_idx = (self.hero_idx + (1 if action == "r" else -1)) % len(self.featured)
        elif action == "a":
            g = self._focused()
            if g:
                self.app.open_game(g["id"])
        elif action == "y":
            self.app.go_tab("search")
        elif action == "b":
            self.app.go_tab("discover")        # v5: B is a shortcut to Discover
        elif action == "x":
            self.app.open_control()        # X → Settings (AAhead Control)

    def _cold_action(self, action):
        if action == "up":
            if self.row == 0:
                self.nav.focus()
            else:
                self.row = 0
        elif action == "down":
            if self.row == 0:
                self.row = 1
        elif action == "left":
            if self.row == 1:
                self.dcol = max(0, self.dcol - 1)
        elif action == "right":
            if self.row == 1:
                self.dcol = min(len(self.doors) - 1, self.dcol + 1)
        elif action in ("l", "r") and self.row == 0 and self.featured:
            self.hero_idx = (self.hero_idx + (1 if action == "r" else -1)) % len(self.featured)
        elif action == "a":
            if self.row == 0 and self.featured:
                self.app.open_game(self.featured[self.hero_idx]["id"])
            elif self.row == 1:
                key = self.doors[self.dcol][0]
                self.app.go_tab("library") if key == "library" else self.app.open_addgames()
        elif action == "y":
            self.app.go_tab("search")
        elif action == "b":
            self.app.go_tab("discover")

    def _focused(self):
        if self.row == 0:
            return self.featured[self.hero_idx] if self.featured else None
        games = self.rails[self.row - 1][2]
        return games[self.cols[self.row - 1]] if games else None

    def update(self, dt_ms):
        pass

    # ── scroll ───────────────────────────────────────────────────────
    def _row_bounds(self, row):
        if row == 0:
            return 0, HERO_H
        top = RAILS_CY + (row - 1) * RAIL_STRIDE
        return top, top + RAIL_CONTENT_H

    def _update_scroll(self):
        maxs = max(0, RAILS_CY + len(self.rails) * RAIL_STRIDE - VIEWPORT_H)
        top, bot = self._row_bounds(self.row)
        if self.row == 0:
            self.scroll = 0
        else:
            if top - 8 < self.scroll:
                self.scroll = top - 8
            if bot + 8 > self.scroll + VIEWPORT_H:
                self.scroll = bot + 8 - VIEWPORT_H
        self.scroll = max(0, min(self.scroll, maxs))

    def _sy(self, cy):
        return BODY_TOP + cy - self.scroll

    # ── draw ─────────────────────────────────────────────────────────
    def draw(self, surf):
        if self.cold:
            self._draw_cold(surf)
            return
        self._update_scroll()
        self.nav.draw(surf, app=self.app)
        clip = pygame.Rect(0, BODY_TOP, t.VIEWPORT_WIDTH, VIEWPORT_H)
        surf.set_clip(clip)
        self._draw_hero(surf)
        self._draw_rails(surf)
        surf.set_clip(None)
        c.scroll_fade(surf, bottom=BODY_BOT)
        chrome.footer_hints(surf, [("A", "Play"), ("Y", "Search"), ("B", "Discover")])

    # ── H0 cold-start: welcome hero + two doors ──────────────────────
    def _draw_cold(self, surf):
        from ..shared import render, icons
        self.nav.draw(surf, app=self.app)
        cat = self.app.catalog
        g = self.featured[self.hero_idx] if self.featured else None
        if g:
            rect = pygame.Rect(0, BODY_TOP, t.VIEWPORT_WIDTH, 240)
            quote = (f"Trust me on the first pick — start with {g['title']}. "
                     + c.first_sentence(g.get("description", ""), cap=90))
            herow.split_hero(surf, rect, art_path=cat.asset_path(g, "hero"),
                             eyebrow="The Clerk · tonight", title="Welcome.",
                             title_style=t.Type.HERO_CARD, meta=[], rating=None,
                             quote=quote, quote_lines=3, cta_label="Start playing",
                             cta_focused=(self.row == 0 and not self.nav.focused),
                             art_focus=(0.5, 0.35))
        # two doors
        top, h = 278, 150
        w = (t.VIEWPORT_WIDTH - 28 - 10) // 2
        for i, (key, label, sub, icon) in enumerate(self.doors):
            x = 14 + i * (w + 10)
            r = pygame.Rect(x, top, w, h)
            focused = (self.row == 1 and self.dcol == i and not self.nav.focused)
            accent = t.Color.ACCENT_PEACH if key == "add" else t.Color.ACCENT_CYAN
            body = pygame.Surface((w, h), pygame.SRCALPHA)
            tint = 0.07 if key == "add" else 0.03
            pygame.draw.rect(body, t.with_alpha(accent, tint), (0, 0, w, h), border_radius=12)
            pygame.draw.rect(body, t.with_alpha(accent, 0.30 if key == "add" else 0.14),
                             (0, 0, w, h), width=1, border_radius=12)
            bd = 40
            ib = pygame.Surface((bd, bd), pygame.SRCALPHA)
            pygame.draw.rect(ib, t.with_alpha(accent, 0.14), (0, 0, bd, bd), border_radius=10)
            ic = icons.icon(icon, 20, accent)
            ib.blit(ic, ((bd - 20) // 2, (bd - 20) // 2))
            body.blit(ib, (18, 24))
            body.blit(fonts.render(t.Type.ROW_TITLE, label, t.Color.TEXT_PRIMARY), (18, 76))
            body.blit(fonts.render(t.Type.CAPTION, sub, t.Color.TEXT_MUTED), (18, 98))
            if focused:
                glow, gpos = render.focus_glow(r, 12); surf.blit(glow, gpos)
            surf.blit(body, r.topleft)
            if focused:
                surf.blit(render.gradient_border((w, h), 12), r.topleft)
        chrome.footer_hints(surf, [("A", "Start"), ("Y", "Search"), ("B", "Discover")])

    def _draw_hero(self, surf):
        if not self.featured:
            return
        g = self.featured[self.hero_idx]
        cat = self.app.catalog
        rect = pygame.Rect(0, self._sy(0), t.VIEWPORT_WIDTH, HERO_H)
        if rect.bottom < BODY_TOP or rect.top > BODY_BOT:
            return
        ent = self._cont.get(g["id"])
        eyebrow = "Tonight, the Clerk picks" if self._cont else "New here? Start with this"
        meta = [g["system"], g.get("year"), (g.get("genre") or [None])[0]]
        cta = f"Continue · {ent['playtime']}" if ent else "Play"
        herow.split_hero(surf, rect, art_path=cat.asset_path(g, "hero"),
                         eyebrow=eyebrow, title=g["title"], title_style=t.Type.HERO,
                         meta=meta, rating=g.get("rating"),
                         quote=c.first_sentence(g.get("description", ""), cap=140),
                         quote_lines=4, cta_label=cta,
                         cta_focused=(self.row == 0 and not self.nav.focused),
                         art_focus=(0.5, 0.35))

    def _draw_rails(self, surf):
        cat = self.app.catalog
        # tiles that FULLY fit from the 14px left margin (keeps the focused tile,
        # incl. its lift, from clipping off the right edge); +1 more is the peek
        fit = (t.VIEWPORT_WIDTH - 14) // (TILE_W + TILE_GAP)
        for ri, (title, aside, games) in enumerate(self.rails):
            top, _ = self._row_bounds(ri + 1)
            sy = self._sy(top)
            if sy > BODY_BOT or sy + RAIL_CONTENT_H < BODY_TOP:
                continue
            active = (self.row == ri + 1 and not self.nav.focused)
            c.rail_header(surf, 14, sy, title, aside, max_w=t.VIEWPORT_WIDTH - 28)
            ty = sy + RAIL_HEADER_H + 6
            col = self.cols[ri]
            start = max(0, min(col - (fit - 1), max(0, len(games) - fit))) if active else 0
            # focused tile drawn last (so its lift overlaps neighbors)
            order = list(range(start, min(start + fit + 1, len(games))))
            for k in order:
                if active and k == col:
                    continue
                self._tile(surf, cat, games[k], 14 + (k - start) * (TILE_W + TILE_GAP), ty,
                           dim=active)
            if active and start <= col < len(games):
                self._tile(surf, cat, games[col], 14 + (col - start) * (TILE_W + TILE_GAP),
                           ty, focused=True)

    def _tile(self, surf, cat, g, x, y, *, focused=False, dim=False):
        rect = pygame.Rect(x, y, TILE_W, TILE_ART_H)
        ent = self._cont.get(g["id"])
        # meta as stacked pills (genre, then playtime in cyan) — each on its own
        # line so the playtime never gets cut the way 'genre · 12h 47m' did
        chips = []
        if ent:                                          # playtime on top…
            chips.append((ent["playtime"], t.Color.ACCENT_CYAN))
        genre = (g.get("genre") or [None])[0]
        if genre:                                        # …genre under it
            chips.append((genre, t.Color.TEXT_SECONDARY))
        c.poster_tile(surf, rect, path=cat.asset_path(g, "box"), name=g["title"],
                      badge=c.rating_badge(g.get("rating")), badge_r=c.sys_year(g),
                      chips=chips, focused=focused, dim=dim)
