"""
edit_world.py — Edit an existing world's metadata.

Pre-fills all fields from the saved WorldMeta.  Saving overwrites the
existing world.dat in-place (folder path does not change).

Returns from update():
  "back"   → return to world manager (no changes saved)
  "saved"  → changes saved, return to world manager
"""

from __future__ import annotations

from typing import Optional

import pygame

from helpers.gui import GUIHandler, TextInput, theme
from helpers.i18n import t
from helpers.icons import get_icon, ICO_BACK
from helpers.spritesheet import SpriteSheet
from helpers.world_data import WorldMeta

# Reuse the helper classes from new_world (import selectively to avoid duplication)
from scenes.new_world import _DiffCard, _IconDialog, _load_icon_surf

_DIFF_EASY = "easy"
_DIFF_HARD = "hard"
_ICON_SIZE  = 52


class EditWorld:
    """
    Scene: Edit an existing world.

    Parameters
    ----------
    screen : pygame.Surface
    world_id : str
        The world_id of the world to edit.

    update() return values
    ----------------------
    "back"    → return to world manager (no changes)
    "saved"   → world saved, return to world manager
    None      → no transition
    """

    _ICON_BTN_SZ = 52

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

        # Load the world — fall back to an empty one if not found
        try:
            self._world = WorldMeta.load(world_id)
        except Exception:
            self._pending = "back"
            self._world = WorldMeta(name="", difficulty=_DIFF_EASY)

        self._difficulty: str = self._world.difficulty
        self._icon_id: int = self._world.icon_id

        try:
            self._prop_sheet: Optional[SpriteSheet] = SpriteSheet("wasteland_props.png")
        except Exception:
            self._prop_sheet = None

        self._gui = GUIHandler()
        self._name_input: Optional[TextInput] = None
        self._diff_cards: list[_DiffCard] = []
        self._last_size = (0, 0)

        self._icon_dialog: Optional[_IconDialog] = None
        self._icon_btn_rect = pygame.Rect(0, 0, self._ICON_BTN_SZ, self._ICON_BTN_SZ)
        self._icon_btn_hover: float = 0.0

        self._build(screen.get_size())

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

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

        self._gui.clear()

        # Header
        self._gui.panel(cx, 0, w, 62, color=theme.PANEL, alpha=220,
                        border_color=None, anchor="midtop")
        self._gui.panel(cx, 62, w, 2, color=theme.ACCENT, alpha=180,
                        border_color=None, border_width=0, anchor="midtop")
        self._gui.label(cx, 31, t("wm_edit"),
                        font_size=26, color=theme.TEXT, anchor="center")
        self._gui.small_button(
            pad, 31, t("back"),
            font_size=16, anchor="midleft",
            color=theme.TEXT_DIM, hover_color=theme.ACCENT,
            icon_surf=get_icon(ICO_BACK, 16),
            on_click=self._on_back,
        )

        form_x = cx - 380
        form_w = 760
        y = 90

        # ---- World Name ----
        self._gui.label(form_x, y, t("nw_name"), font_size=17, color=theme.TEXT_DIM)
        y += 28
        ti = TextInput(
            form_x, y, form_w, 50,
            placeholder=t("nw_name_ph"),
            max_length=40, font_size=24,
        )
        # Pre-fill with current name
        if self._name_input:
            ti.text = self._name_input.text
        else:
            ti.text = self._world.name
        self._name_input = ti
        self._gui.add(ti, name="name_input")
        y += 62

        # ---- Difficulty ----
        self._gui.label(form_x, y, t("nw_diff"), font_size=17, color=theme.TEXT_DIM)
        y += 28
        card_gap = 14
        card_w = (form_w - card_gap) // 2
        card_h = 145
        self._diff_cards = [
            _DiffCard(form_x,                     y, card_w, card_h, _DIFF_EASY),
            _DiffCard(form_x + card_w + card_gap, y, card_w, card_h, _DIFF_HARD),
        ]
        y += card_h + 22

        # ---- World Icon ----
        self._gui.label(form_x, y, t("nw_icon"), font_size=17, color=theme.TEXT_DIM)
        y += 28
        self._icon_btn_rect = pygame.Rect(form_x, y, self._ICON_BTN_SZ, self._ICON_BTN_SZ)
        y += self._ICON_BTN_SZ + 22

        # ---- Save button ----
        self._gui.button(
            cx, y, 260, 54, t("st_save"),
            font_size=24, anchor="midtop",
            on_click=self._on_save,
            name="btn_save",
        )

        sw, sh = size
        self._icon_dialog = _IconDialog(self._prop_sheet, sw, sh)

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

    def _on_back(self) -> None:
        self._pending = "world_manager"

    def _on_save(self) -> None:
        name = self._name_input.text.strip() if self._name_input else ""
        if not name:
            name = self._world.name or "Unnamed World"
        self._world.name = name
        self._world.difficulty = self._difficulty
        self._world.icon_id = self._icon_id
        self._world.save()
        self._pending = "world_manager"

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

    def update(self, dt: float, events: list[pygame.event.Event]) -> Optional[str]:
        if self._last_size != pygame.display.get_surface().get_size():
            self._build(pygame.display.get_surface().get_size())

        dialog_open = self._icon_dialog is not None and self._icon_dialog._open

        for event in events:
            if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
                if not dialog_open:
                    self._pending = "world_manager"

            if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                if not dialog_open:
                    for card in self._diff_cards:
                        if card.rect.collidepoint(event.pos):
                            self._difficulty = card.diff
                    if self._icon_btn_rect.collidepoint(event.pos):
                        if self._icon_dialog is not None:
                            self._icon_dialog.open(self._icon_id)

        if self._icon_dialog is not None:
            for event in events:
                self._icon_dialog.handle_event(event)
            if self._icon_dialog.done:
                self._icon_id = self._icon_dialog.selected_id
                self._icon_dialog.done = False

        if not dialog_open:
            self._gui.handle_events(events)

        self._gui.update(dt)

        for card in self._diff_cards:
            card.update(dt)

        if self._icon_dialog is not None:
            self._icon_dialog.update(dt)

        hov = self._icon_btn_rect.collidepoint(pygame.mouse.get_pos()) and not dialog_open
        self._icon_btn_hover += (1.0 if hov else 0.0 - self._icon_btn_hover) * min(1.0, 10.0 * 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())

        surface.fill(theme.BG)

        step = 48
        for gx in range(0, surface.get_width(), step):
            for gy in range(0, surface.get_height(), step):
                pygame.draw.circle(surface, (18, 32, 52), (gx, gy), 1)

        for card in self._diff_cards:
            card.draw(surface, selected=(card.diff == self._difficulty))

        self._draw_icon_button(surface)

        self._gui.draw(surface)

        if self._icon_dialog is not None:
            self._icon_dialog.draw(surface)

    def _draw_icon_button(self, surface: pygame.Surface) -> None:
        r = self._icon_btn_rect
        h = self._icon_btn_hover

        bg_col = (
            int(theme.PANEL[0] + (theme.BTN_HOVER_BG[0] - theme.PANEL[0]) * h),
            int(theme.PANEL[1] + (theme.BTN_HOVER_BG[1] - theme.PANEL[1]) * h),
            int(theme.PANEL[2] + (theme.BTN_HOVER_BG[2] - theme.PANEL[2]) * h),
        )
        bg = pygame.Surface((r.w, r.h), pygame.SRCALPHA)
        bg.fill((*bg_col, 220))
        surface.blit(bg, r.topleft)

        border_col = theme.ACCENT if h > 0.5 else theme.BORDER
        pygame.draw.rect(surface, border_col, r, width=1, border_radius=4)

        if self._prop_sheet is not None and self._icon_id >= 0:
            icon_surf = _load_icon_surf(self._prop_sheet, self._icon_id, _ICON_SIZE)
            pad = (r.w - _ICON_SIZE) // 2
            surface.blit(icon_surf, (r.x + pad, r.y + pad))
        else:
            q = theme.font(28).render(t("nw_icon_pick"), True, theme.TEXT_DIM)
            surface.blit(q, (r.centerx - q.get_width() // 2,
                              r.centery - q.get_height() // 2))
