"""
Q1 — Quick Menu (the in-game Guide overlay).

Shown over a frozen game: a glass panel with the one focused Resume, the four
things players actually want (save / load / screenshot / restart), the assist
row mirrored from the game card, and brightness/volume. Brightness and volume
drive the REAL backlight / ALSA level (the same elements as the Display & Sound
sliders); the save / load / screenshot tiles are still UI-only. B resumes,
Y quits to AAhead — opened from the game card's Guide.
"""

from __future__ import annotations

import pygame

from ..design import tokens as t
from ..shared import fonts, render, icons
from ..widgets import components as c, images
from ..control.shared import backend

PANEL = pygame.Rect(16, 50, t.VIEWPORT_WIDTH - 32, t.VIEWPORT_HEIGHT - 100)
PAD_X, PAD_T = 18, 16
INNER_X = PANEL.x + PAD_X
INNER_W = PANEL.w - 2 * PAD_X

TILES = [("ph-floppy-disk", "Save state", "slot 1 · ready"),
         ("ph-folder-open", "Load state", "3 saves on file"),
         ("ph-camera", "Screenshot", "last · 4m ago"),
         ("ph-arrow-clockwise", "Restart", "with confirm")]
ROW_LENS = [1, len(TILES), 1, 1, 1]       # resume · tiles · assist · brightness · volume
R_BRIGHT, R_VOL = 3, 4


class QuickMenu:
    name = "quick_menu"

    def __init__(self, app, game):
        self.app = app
        self.game = game
        self.row = 0          # 0 resume · 1 tiles · 2 assist · 3 sliders
        self.col = 0
        self.bright, self.vol = 72, 48
        live = backend.display_brightness()        # real backlight (shared element)
        if live is not None:
            self.bright = live
        vlive = backend.volume_get()               # real ALSA level (shared element)
        if vlive is not None:
            self.vol = vlive

    # ── input ────────────────────────────────────────────────────────
    def on_action(self, action):
        if action in ("b",):                       # B always resumes
            self.app.pop(); return
        if action == "y":                          # quit to AAhead
            self.app.go_tab("home"); return
        if action == "x":
            self.app.toast("Sleep — tap power to wake"); return
        if action == "up":
            self.row = max(0, self.row - 1)
            self.col = min(self.col, ROW_LENS[self.row] - 1)
        elif action == "down":
            self.row = min(len(ROW_LENS) - 1, self.row + 1)
            self.col = min(self.col, ROW_LENS[self.row] - 1)
        elif action == "left":
            if self.row == R_BRIGHT:
                self.bright = max(5, self.bright - 5)      # drives the real backlight
                backend.display_set_brightness(self.bright)
            elif self.row == R_VOL:
                self.vol = max(0, self.vol - 5)
                backend.volume_set(self.vol)
            else:
                self.col = max(0, self.col - 1)
        elif action == "right":
            if self.row == R_BRIGHT:
                self.bright = min(100, self.bright + 5)
                backend.display_set_brightness(self.bright)
            elif self.row == R_VOL:
                self.vol = min(100, self.vol + 5)
                backend.volume_set(self.vol)
            else:
                self.col = min(ROW_LENS[self.row] - 1, self.col + 1)
        elif action == "a":
            self._activate()

    def _activate(self):
        if self.row == 0:
            self.app.pop()
        elif self.row == 1:
            msg = {0: "State saved to slot 1", 1: "Load a save state",
                   2: "Screenshot saved", 3: "Restart game?"}[self.col]
            self.app.toast(msg)
        elif self.row == 2:
            self.app.open_assist(self.game)            # "+2 more" → real assist panel
        # sliders: Left/Right adjust; A is a no-op

    def update(self, dt_ms):
        pass

    # ── draw ─────────────────────────────────────────────────────────
    def draw(self, surf):
        cat = self.app.catalog
        # frozen game — blurred backdrop + extra veil
        surf.blit(images.backdrop(cat.asset_path(self.game, "hero")
                                  or cat.asset_path(self.game, "box"),
                                  t.VIEWPORT_WIDTH, t.VIEWPORT_HEIGHT, darken=0.6), (0, 0))
        veil = pygame.Surface((t.VIEWPORT_WIDTH, t.VIEWPORT_HEIGHT), pygame.SRCALPHA)
        veil.fill(t.with_alpha(t.Color.BG_DEEP, 0.45))
        surf.blit(veil, (0, 0))
        # pause stamp + clock
        c.clerk_eyebrow(surf, 16, 18, "Paused", color=t.Color.TEXT_SECONDARY)
        clk = fonts.render(t.Type.MONO, "22:14   82%", t.Color.TEXT_SECONDARY)
        surf.blit(clk, (t.VIEWPORT_WIDTH - 16 - clk.get_width(), 16))
        # glass panel
        panel = pygame.Surface((PANEL.w, PANEL.h), pygame.SRCALPHA)
        pygame.draw.rect(panel, t.with_alpha(t.Color.SURFACE_ELEVATED, 0.86),
                         (0, 0, PANEL.w, PANEL.h), border_radius=14)
        pygame.draw.rect(panel, t.with_alpha(t.Color.TEXT_PRIMARY, 0.06),
                         (0, 0, PANEL.w, PANEL.h), width=1, border_radius=14)
        surf.blit(panel, PANEL.topleft)

        y = PANEL.y + PAD_T
        y = self._draw_top(surf, y)
        y = self._draw_resume(surf, y + 12, focused=(self.row == 0))
        y = self._draw_tiles(surf, y + 12)
        y = self._draw_assist(surf, y + 12)
        self._draw_sliders(surf, y + 12)
        self._draw_foot(surf)

    def _draw_top(self, surf, y):
        cat = self.app.catalog
        box = images.cover(cat.asset_path(self.game, "box"), 56, 40, radius=5, mode="cover")
        surf.blit(box, (INNER_X, y))
        tx = INNER_X + 56 + 14
        nm = fonts.render(t.Type.ROW_TITLE, c._ellipsize(t.Type.ROW_TITLE, self.game["title"], 320),
                          t.Color.TEXT_PRIMARY)
        surf.blit(nm, (tx, y + 2))
        segs = c.fit_meta([self.game["system"], self.game.get("year"),
                           (self.game.get("genre") or [None])[0]], 360)
        c.meta_line(surf, tx, y + 22, segs, color=t.Color.TEXT_MUTED)
        # session, right-aligned
        lab = fonts.render(t.Type.EYEBROW, "THIS SESSION", t.Color.TEXT_MUTED)
        ses = fonts.render(t.Type.MONO, "1h 12m", t.Color.TEXT_SECONDARY)
        rx = PANEL.right - PAD_X
        surf.blit(lab, (rx - lab.get_width(), y + 2))
        surf.blit(ses, (rx - ses.get_width(), y + 16))
        yb = y + 44
        pygame.draw.line(surf, t.with_alpha(t.Color.TEXT_PRIMARY, 0.06),
                         (INNER_X, yb), (PANEL.right - PAD_X, yb), 1)
        return yb

    def _draw_resume(self, surf, y, *, focused):
        r = pygame.Rect(INNER_X, y, INNER_W, 46)
        body = pygame.Surface((r.w, r.h), pygame.SRCALPHA)
        pygame.draw.rect(body, t.Color.TEXT_PRIMARY, (0, 0, r.w, r.h), border_radius=10)
        d = 22
        pygame.draw.circle(body, t.Color.BG_DEEP, (12 + d // 2, r.h // 2), d // 2)
        bl = fonts.render(t.Type.GP, "B", t.Color.TEXT_PRIMARY)
        body.blit(bl, (12 + d // 2 - bl.get_width() // 2, r.h // 2 - bl.get_height() // 2))
        tx = 12 + d + 12
        body.blit(fonts.render(t.Type.LABEL, "Resume", t.Color.BG_DEEP), (tx, 9))
        sub = fonts.render(t.Type.CAPTION, "just where you left off — nothing lost",
                           t.with_alpha(t.Color.BG_DEEP, 0.65))
        body.blit(sub, (tx, 26))
        if focused:
            glow, gpos = render.focus_glow(r, 10); surf.blit(glow, gpos)
        surf.blit(body, r.topleft)
        if focused:
            surf.blit(render.gradient_border((r.w, r.h), 10), r.topleft)
        return r.bottom

    def _draw_tiles(self, surf, y):
        gap = 8
        tw = (INNER_W - gap * 3) // 4
        th = 66
        for i, (icon, lbl, sub) in enumerate(TILES):
            x = INNER_X + i * (tw + gap)
            r = pygame.Rect(x, y, tw, th)
            focused = (self.row == 1 and self.col == i)
            body = pygame.Surface((r.w, r.h), pygame.SRCALPHA)
            pygame.draw.rect(body, t.with_alpha(t.Color.TEXT_PRIMARY, 0.03),
                             (0, 0, r.w, r.h), border_radius=10)
            if not focused:
                pygame.draw.rect(body, t.with_alpha(t.Color.TEXT_PRIMARY, 0.05),
                                 (0, 0, r.w, r.h), width=1, border_radius=10)
            ic = icons.icon(icon, 18, t.Color.TEXT_SECONDARY)
            body.blit(ic, (10, 10))
            body.blit(fonts.render(t.Type.LABEL, lbl, t.Color.TEXT_PRIMARY), (10, 32))
            body.blit(fonts.render(t.Type.TILE_SUB, sub, t.Color.TEXT_MUTED), (10, 48))
            if focused:
                glow, gpos = render.focus_glow(r, 10); surf.blit(glow, gpos)
            surf.blit(body, r.topleft)
            if focused:
                surf.blit(render.gradient_border((r.w, r.h), 10), r.topleft)
        return y + th

    def _draw_assist(self, surf, y):
        # In-game compact preview of THIS game's tweaks — peach tile shows the
        # first two curated cheat labels + a "+N more" pill counting the rest.
        # The toggle dot mirrors the player's actual enabled state (lit when
        # ≥1 cheat is on, dim otherwise). A on this row opens AssistScreen
        # for full toggles. Pure mock content (the old "endless lives ·
        # continues · no timer" hardcode) was misleading once real curation
        # landed — every game was claiming the same three tweaks.
        curated = self.app.catalog.cheats_for(self.game["id"])
        enabled = self.app.library.play_state().enabled_cheats(self.game["id"])
        labels = [c.get("label", "") for c in (curated or []) if c.get("label")]
        n_on = sum(1 for l in labels if l in enabled)

        r = pygame.Rect(INNER_X, y, INNER_W, 40)
        focused = (self.row == 2)
        body = pygame.Surface((r.w, r.h), pygame.SRCALPHA)
        pygame.draw.rect(body, t.with_alpha(t.Color.ACCENT_PEACH, 0.06), (0, 0, r.w, r.h),
                         border_radius=10)
        pygame.draw.rect(body, t.with_alpha(t.Color.ACCENT_PEACH, 0.20), (0, 0, r.w, r.h),
                         width=1, border_radius=10)
        # toggle reflects "any cheat on" — gray pill when none enabled
        tg = pygame.Rect(10, (r.h - 16) // 2, 28, 16)
        on_state = n_on > 0
        pygame.draw.rect(body, t.with_alpha(t.Color.ACCENT_PEACH if on_state else
                                             t.Color.TEXT_PRIMARY,
                                             0.5 if on_state else 0.12),
                         tg, border_radius=999)
        knob_x = tg.right - 8 if on_state else tg.left + 8
        pygame.draw.circle(body, t.Color.ACCENT_PEACH if on_state else
                                  t.Color.TEXT_MUTED,
                           (knob_x, tg.centery), 6)
        tx = 48
        ttl = fonts.render(t.Type.CAPTION, "How do you want to play?", t.Color.TEXT_SECONDARY)
        body.blit(ttl, (tx, 6))
        # Top-line label: first curated cheat (or "No tweaks" placeholder)
        headline = labels[0] if labels else "No tweaks for this game"
        nm = fonts.render(t.Type.LABEL, headline, t.Color.TEXT_PRIMARY)
        body.blit(nm, (tx + ttl.get_width() + 8, 5))
        # Sub-line: 1-2 more labels (real content, never hardcoded)
        sub_text = " · ".join(labels[1:3]) if len(labels) > 1 else ""
        if sub_text:
            bullets = fonts.render(t.Type.TILE_SUB, sub_text, t.Color.TEXT_MUTED)
            body.blit(bullets, (tx, 22))
        # "+N more" pill — only when there's actually +N
        more = max(0, len(labels) - 3)
        if more:
            pill = fonts.render(t.Type.TILE_SUB, f"+{more} more", t.Color.ACCENT_PEACH)
            pr = pygame.Rect(r.w - 14 - pill.get_width() - 16, (r.h - 18) // 2,
                             pill.get_width() + 16, 18)
            pygame.draw.rect(body, t.with_alpha(t.Color.ACCENT_PEACH, 0.12), pr,
                             border_radius=999)
            body.blit(pill, (pr.x + 8, pr.y + (18 - pill.get_height()) // 2))
        if focused:
            glow, gpos = render.focus_glow(r, 10); surf.blit(glow, gpos)
        surf.blit(body, r.topleft)
        if focused:
            surf.blit(render.gradient_border((r.w, r.h), 10), r.topleft)
        return r.bottom

    def _draw_sliders(self, surf, y):
        # stacked, full-width — Left/Right adjusts the FOCUSED slider (real control)
        for icon, lbl, val, rowidx in [("ph-sun", "Brightness", self.bright, R_BRIGHT),
                                       ("ph-speaker-high", "Volume", self.vol, R_VOL)]:
            focused = (self.row == rowidx)
            ic = icons.icon(icon, 16, t.Color.TEXT_SECONDARY)
            surf.blit(ic, (INNER_X, y + 1))
            cx = INNER_X + 22
            cw = INNER_W - 22
            lab = fonts.render(t.Type.CAPTION, lbl,
                               t.Color.TEXT_PRIMARY if focused else t.Color.TEXT_SECONDARY)
            surf.blit(lab, (cx, y))
            arrows = f"< {val}% >" if focused else f"{val}%"
            vs = fonts.render(t.Type.TILE_SUB, arrows,
                              t.Color.TEXT_SECONDARY if focused else t.Color.TEXT_MUTED)
            surf.blit(vs, (INNER_X + INNER_W - vs.get_width(), y + 1))
            pygame.draw.rect(surf, t.with_alpha(t.Color.TEXT_PRIMARY, 0.10),
                             (cx, y + 18, cw, 5), border_radius=3)
            fill_w = max(4, int(cw * val / 100))
            if focused:
                surf.blit(render.linear_gradient((fill_w, 5), t.Color.ACCENT_ROSE,
                                                 t.Color.ACCENT_CYAN, 0.0), (cx, y + 18))
            else:
                pygame.draw.rect(surf, t.Color.TEXT_SECONDARY, (cx, y + 18, fill_w, 5),
                                 border_radius=3)
            y += 30

    def _draw_foot(self, surf):
        y = PANEL.bottom - PAD_T - 8                       # a touch more air
        items = [("B", "Resume"), ("A", "Open"), ("X", "Sleep"), ("Y", "Quit to AAhead")]
        x = INNER_X
        for key, lbl in items:
            gp = pygame.Rect(x, y, 18, 18)
            pygame.draw.rect(surf, t.Color.SURFACE_ELEVATED, gp, border_radius=999)
            pygame.draw.rect(surf, t.Color.BORDER_BRIGHT, gp, width=1, border_radius=999)
            ks = fonts.render(t.Type.GP, key, t.Color.TEXT_PRIMARY)
            surf.blit(ks, (gp.centerx - ks.get_width() // 2, gp.centery - ks.get_height() // 2))
            ls = fonts.render(t.Type.CAPTION, lbl, t.Color.TEXT_SECONDARY)
            surf.blit(ls, (x + 22, y + (18 - ls.get_height()) // 2))
            x += 22 + ls.get_width() + 16
