"""
loading_screen.py — Brief loading screen shown before entering the Game scene.

Shows world name, difficulty, and a progress bar that fills over ~1 second.
After loading completes, returns "play_ready:<world_id>".
"""

from __future__ import annotations

from typing import Optional

import pygame

from helpers.gui import UITheme
from helpers.world_data import WorldMeta, TEX_BASE


class LoadingScreen:
    """
    Transient loading scene.

    update() returns ``"play_ready:<world_id>"`` once loading is done.
    """

    _LOAD_TIME = 1.2   # seconds to fill the bar
    _HOLD_TIME = 0.2   # brief pause at 100% before transitioning

    def __init__(self, screen: pygame.Surface, world_id: str) -> None:
        self._screen    = screen
        self._world_id  = world_id
        self._theme     = UITheme()
        self._elapsed   = 0.0
        self._done      = False

        # Load world meta
        try:
            self._meta: Optional[WorldMeta] = WorldMeta.load(world_id)
        except FileNotFoundError:
            self._meta = None

        # Load icon sprite
        self._icon: Optional[pygame.Surface] = self._load_icon()

    # ---- icon ----

    def _load_icon(self) -> Optional[pygame.Surface]:
        if self._meta is None:
            return None
        info = self._meta.icon_info
        path = TEX_BASE / info.get("path", "")
        try:
            raw = pygame.image.load(str(path)).convert_alpha()
            return pygame.transform.scale(raw, (80, 80))
        except Exception:
            return None

    # ---- update ----

    def update(self, dt: float, events: list[pygame.event.Event]) -> Optional[str]:
        for e in events:
            if e.type == pygame.QUIT:
                return "back"

        self._elapsed += dt

        total = self._LOAD_TIME + self._HOLD_TIME
        if self._elapsed >= total:
            return f"play_ready:{self._world_id}"

        return None

    # ---- draw ----

    def draw(self, screen: pygame.Surface) -> None:
        th = self._theme
        screen.fill(th.BG)

        sw, sh = screen.get_size()
        cx     = sw // 2
        cy     = sh // 2

        # ---- Icon ----
        if self._icon:
            screen.blit(self._icon, (cx - 40, cy - 120))

        # ---- World name ----
        if self._meta:
            name_s = th.font(28).render(self._meta.name, True, th.TEXT)
            screen.blit(name_s, (cx - name_s.get_width() // 2, cy - 28))

            diff_col = (80, 220, 120) if self._meta.difficulty == "easy" else (230, 100, 60)
            diff_s   = th.font(18).render(self._meta.difficulty_label, True, diff_col)
            screen.blit(diff_s, (cx - diff_s.get_width() // 2, cy + 10))
        else:
            err_s = th.font(21).render("World not found", True, (200, 60, 60))
            screen.blit(err_s, (cx - err_s.get_width() // 2, cy - 10))

        # ---- Progress bar ----
        bar_w = min(400, sw - 80)
        bar_h = 12
        bar_x = cx - bar_w // 2
        bar_y = cy + 50

        progress = min(1.0, self._elapsed / max(0.001, self._LOAD_TIME))

        pygame.draw.rect(screen, (20, 35, 55), (bar_x, bar_y, bar_w, bar_h), border_radius=5)
        fill_w = int(bar_w * progress)
        if fill_w > 0:
            bar_col = (
                int(232 * (1 - progress) + 79 * progress),
                int(137 * (1 - progress) + 195 * progress),
                int(12  * (1 - progress) + 247 * progress),
            )
            pygame.draw.rect(screen, bar_col, (bar_x, bar_y, fill_w, bar_h), border_radius=5)
        pygame.draw.rect(screen, th.BORDER, (bar_x, bar_y, bar_w, bar_h), 1, border_radius=5)

        # "Loading…" label
        lbl_s = th.font(16).render("Loading…" if progress < 1.0 else "Ready!", True, th.TEXT_DIM)
        screen.blit(lbl_s, (cx - lbl_s.get_width() // 2, bar_y + bar_h + 10))
