"""
v3 split-pane hero banner: text panel on the left (~300px on near-black),
key-art flush to the right (380px) whose left edge dissolves into the panel via
a 90° fade. Used by Home, Library featured, and the Game-card header.
"""

from __future__ import annotations

from functools import lru_cache

import pygame

from ..design import tokens as t
from ..shared import fonts, render
from . import components as c, images

ART_W = 380
TEXT_X = 18
TEXT_W = 300


@lru_cache(maxsize=8)
def _art_fade(w: int, h: int) -> pygame.Surface:
    """90° fade: near-black at the left edge of the art → clear by ~50%, so the
    key-art dissolves seamlessly into the text panel. (No bottom vignette — it
    only created a flat translucent band over the right half.)"""
    s = pygame.Surface((w, h), pygame.SRCALPHA)
    bg = t.Color.BG_DEEP
    for x in range(w):
        f = x / w
        if f < 0.14:
            a = int(255 - (255 - 217) * (f / 0.14))      # 1.0 → .85
        elif f < 0.32:
            a = int(217 - (217 - 77) * ((f - 0.14) / 0.18))   # .85 → .30
        elif f < 0.50:
            a = int(77 * (1 - (f - 0.32) / 0.18))         # .30 → 0
        else:
            a = 0
        if a:
            s.fill((bg[0], bg[1], bg[2], a), (x, 0, 1, h))
    return s


def split_hero(surf, rect, *, art_path, eyebrow, title, title_style=None,
               title_lines=1, meta, rating=None, quote=None, quote_lines=4,
               cta_label=None, cta_focused=True, art_focus=(0.5, 0.35),
               text_top=14, eyebrow_color=t.Color.ACCENT_ROSE):
    """
    rect = full hero band (x=0, y, w=640, h). Draws art-right + fade + text-left.
    meta = list of plain segments (system/year/genre); rating appended as stars.
    """
    title_style = title_style or t.Type.HERO
    # ── art, right pane ──
    art_rect = pygame.Rect(rect.right - ART_W, rect.y, ART_W, rect.h)
    art = images.cover(art_path, ART_W, rect.h, radius=0, mode="cover", focus=art_focus)
    surf.blit(art, art_rect.topleft)
    surf.blit(_art_fade(ART_W, rect.h), art_rect.topleft)

    # ── text, left pane ──
    x = rect.x + TEXT_X
    y = rect.y + text_top
    c.clerk_eyebrow(surf, x, y, eyebrow, color=eyebrow_color)
    y += 18
    # Title: one line if it fits, otherwise wrap up to `max(title_lines, 2)`
    # lines (there's vertical room) and ellipsize only the last — long titles
    # like "Final Fantasy Tactics - The War of the Lions" stay readable.
    max_lines = max(title_lines, 2)
    if fonts.measure(title_style, title)[0] <= TEXT_W:
        lines = [title]
    else:
        lines = c.wrap_text(title_style, title, TEXT_W)[:max_lines]
    lh = int(title_style.size * 1.08)
    for i, ln in enumerate(lines):
        if i == len(lines) - 1:
            ln = c._ellipsize(title_style, ln, TEXT_W)
        surf.blit(fonts.render(title_style, ln, t.Color.TEXT_PRIMARY), (x, y))
        y += lh
    y += 3

    # meta — keep system+year+rating on the panel; drop genre rather than spill
    rating_w = (8 + 5 * (11 + 2) + 5 + fonts.measure(t.Type.MONO, f"{rating:.1f}")[0]
                ) if rating else 0
    segs = c.fit_meta(meta, TEXT_W - rating_w)
    sx = c.meta_line(surf, x, y, segs, color=t.Color.TEXT_SECONDARY)
    if rating:
        sx += 8
        cap_h = fonts.measure(t.Type.CAPTION, "0")[1]
        cy = y + cap_h // 2                       # vertical center of the meta row
        w = c.star_rating(surf, sx, cy - 5, rating, size=11)   # center 11px stars
        num = fonts.render(t.Type.MONO, f"{rating:.1f}", t.Color.TEXT_SECONDARY)
        surf.blit(num, (sx + w + 5, cy - num.get_height() // 2))
    y += 20

    if quote:
        # clamp the quote to the room left above the CTA so it never overflows
        limit = (rect.bottom - text_top - 30 - 8) if cta_label is not None \
            else (rect.bottom - text_top)
        line_h = 19                       # 1px tighter → fits a 3rd line in the 200px hero
        max_q = max(1, min(quote_lines, (limit - y) // line_h))
        c.clerk_quote(surf, x, y, quote, TEXT_W, max_lines=max_q,
                      color=t.Color.TEXT_SECONDARY, line_h=line_h, bar=False)

    # ── CTA pinned bottom-left ──
    if cta_label is not None:
        lab_w = fonts.measure(t.Type.BTN, cta_label)[0]
        cta = pygame.Rect(x, rect.bottom - text_top - 30, lab_w + 30 + 16, 30)
        c.button_primary(surf, cta, cta_label, focused=cta_focused)
        return cta
    return None
