"""
main_menu.py — Main Menu scene for Powernet.

Features
--------
• Circuit-board background (static, deterministic)
• "POWERNET" title with a calm neon-glow pulse + music-reactive beat burst
• Three main buttons: Play · Settings · Credits
• Copyright notice (clickable → opens gmrze.net) + version label
• Music: managed by helpers.music.music_manager (cycles automatically)
• "Now Playing: …" slide-in alert on track change

Returns from update():
  "world_manager"  → open world selection screen
  "settings"       → settings menu
  "credits"        → credits scene
  "quit"           → quit application
"""

from __future__ import annotations

import random
import webbrowser
from datetime import datetime
from typing import Optional

import pygame

from helpers.gui import Alert, GlowLabel, GUIHandler, Label, theme
from helpers.i18n import t
from helpers.music import MUSIC_END, music_manager
from helpers.settings import get_settings

_AUTHOR_URL = "https://gmrze.net"


# ---------------------------------------------------------------------------
# Background helpers
# ---------------------------------------------------------------------------


def _build_circuit_bg(w: int, h: int) -> pygame.Surface:
    surf = pygame.Surface((w, h))
    surf.fill(theme.BG)
    rng = random.Random(42)
    step = 48
    dot  = (18, 32, 52)
    line = (14, 26, 44)
    for gx in range(0, w + step, step):
        for gy in range(0, h + step, step):
            pygame.draw.circle(surf, dot, (gx, gy), 1)
    for _ in range(60):
        gx = rng.randrange(0, w // step) * step
        gy = rng.randrange(0, h // step) * step
        pygame.draw.line(surf, line, (gx, gy), (gx + rng.randint(1, 5) * step, gy), 1)
    for _ in range(60):
        gx = rng.randrange(0, w // step) * step
        gy = rng.randrange(0, h // step) * step
        pygame.draw.line(surf, line, (gx, gy), (gx, gy + rng.randint(1, 4) * step), 1)
    return surf


# ---------------------------------------------------------------------------
# MainMenu scene
# ---------------------------------------------------------------------------


class MainMenu:
    """Main menu scene."""

    def __init__(self, screen: pygame.Surface) -> None:
        self._pending: Optional[str] = None

        self._bg: Optional[pygame.Surface] = None
        self._gui = GUIHandler()
        self._last_size = (0, 0)
        self._title: Optional[GlowLabel | Label] = None

        # Alert for "Now Playing"
        self._alert: Optional[Alert] = None

        # Startup fade-in
        self._fade_alpha: float = 255.0

        # Start music (only if not already playing from a previous scene)
        if not music_manager.is_playing:
            music_manager.start(0)
            self._show_now_playing()

        self._build(screen.get_size())

    # ------------------------------------------------------------------
    # Music
    # ------------------------------------------------------------------

    def _show_now_playing(self) -> None:
        self._alert = Alert(
            t("now_playing", track=music_manager.track_name),
            duration=4.0, font_size=17,
        )
        self._last_track_idx = music_manager.track_idx

    # ------------------------------------------------------------------
    # Build
    # ------------------------------------------------------------------

    def _build(self, size: tuple[int, int]) -> None:
        w, h = size
        self._last_size = size
        cx, cy = w // 2, h // 2

        self._bg = _build_circuit_bg(w, h)

        # ---- GUI ----
        self._gui.clear()

        # Panel behind the buttons
        panel_w, panel_h = 450, 318
        self._gui.panel(cx, cy + 44, panel_w, panel_h,
                        color=theme.PANEL, alpha=200,
                        border_color=theme.BORDER, border_width=1, anchor="center")
        self._gui.panel(cx, cy + 44 - panel_h // 2, panel_w, 3,
                        color=theme.ACCENT, alpha=230,
                        border_color=None, border_width=0, anchor="midtop")

        # Title (glow or plain, based on settings)
        settings = get_settings()
        if settings.title_glow:
            title: GlowLabel | Label = GlowLabel(
                cx, cy - 128, "POWERNET",
                font_size=110,
                color=theme.TEXT_TITLE,
                glow_color=theme.ACCENT_GLOW,
                anchor="center",
                pulse=True,
                pulse_speed=0.55,
                pulse_range=(0.88, 1.0),
            )
        else:
            title = Label(
                cx, cy - 128, "POWERNET",
                font_size=110,
                color=theme.TEXT_TITLE,
                anchor="center",
            )
        self._title = title
        self._gui.add(title, name="title")

        # Subtitle
        self._gui.label(cx, cy - 46,
                        t("subtitle"),
                        font_size=16, color=theme.TEXT_DIM, anchor="center")
        self._gui.divider(cx, cy - 22, 370, anchor="midtop")

        # Main buttons
        btn_w, btn_h, gap = 410, 58, 12
        total_h = 3 * btn_h + 2 * gap
        first_y = cy + 44 - total_h // 2

        self._gui.button(cx, first_y,             btn_w, btn_h, t("play"),
                         font_size=30, anchor="midtop",
                         on_click=self._on_play, name="btn_play")
        self._gui.button(cx, first_y + btn_h + gap, btn_w, btn_h, t("settings"),
                         font_size=30, anchor="midtop",
                         on_click=self._on_settings)
        self._gui.button(cx, first_y + 2*(btn_h+gap), btn_w, btn_h, t("credits"),
                         font_size=30, anchor="midtop",
                         on_click=self._on_credits)

        # Footer — copyright (clickable) + version
        pad = 18
        self._gui.small_button(
            pad, h - pad,
            f"© {datetime.now().year} gmrze  ·  gmrze.net",
            font_size=17, anchor="bottomleft",
            color=(150, 165, 185), hover_color=theme.ACCENT,
            on_click=lambda: webbrowser.open(_AUTHOR_URL),
        )
        self._gui.label(
            w - pad, h - pad,
            "v 0.1.0",
            font_size=17, color=(110, 140, 170), anchor="bottomright",
        )

    # ------------------------------------------------------------------
    # Callbacks
    # ------------------------------------------------------------------

    def _on_play(self)     -> None: self._pending = "world_manager"
    def _on_settings(self) -> None: self._pending = "settings"
    def _on_credits(self)  -> None: self._pending = "credits"

    # ------------------------------------------------------------------
    # Scene interface
    # ------------------------------------------------------------------

    def update(self, dt: float, events: list[pygame.event.Event]) -> Optional[str]:
        for event in events:
            if event.type in (pygame.VIDEORESIZE, pygame.WINDOWRESIZED):
                new = pygame.display.get_surface().get_size()
                if new != self._last_size:
                    self._build(new)
            if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
                self._pending = "quit"
            if event.type == MUSIC_END:
                # main.py handles next_track() globally; we only show the alert here
                self._show_now_playing()

        self._gui.handle_events(events)
        self._gui.update(dt)

        # Music-reactive title (only GlowLabel supports beat)
        if isinstance(self._title, GlowLabel):
            self._title.beat = music_manager.beat_phase()

        # Startup fade-in
        if self._fade_alpha > 0:
            self._fade_alpha = max(0.0, self._fade_alpha - dt * 400)

        if self._alert and not self._alert.done:
            self._alert.update(dt)

        result, self._pending = self._pending, None
        return result

    def draw(self, surface: pygame.Surface) -> None:
        if surface.get_size() != self._last_size:
            self._build(surface.get_size())

        if self._bg:
            surface.blit(self._bg, (0, 0))
        else:
            surface.fill(theme.BG)

        self._gui.draw(surface)

        if self._alert and not self._alert.done:
            self._alert.draw(surface)

        self._draw_scanlines(surface)

        # Startup fade-in overlay
        if self._fade_alpha > 0:
            fade = pygame.Surface(surface.get_size(), pygame.SRCALPHA)
            fade.fill((0, 0, 0, int(self._fade_alpha)))
            surface.blit(fade, (0, 0))

    @staticmethod
    def _draw_scanlines(surface: pygame.Surface) -> None:
        w, h = surface.get_size()
        key = f"_sl_{w}_{h}"
        if not hasattr(MainMenu, key):
            sl = pygame.Surface((w, h), pygame.SRCALPHA)
            for y in range(0, h, 3):
                pygame.draw.line(sl, (0, 0, 0, 16), (0, y), (w, y))
            setattr(MainMenu, key, sl)
        surface.blit(getattr(MainMenu, key), (0, 0))
