"""Zone registry and loading."""

from __future__ import annotations

import logging
import tomllib
from pathlib import Path

from mudlib.portal import Portal
from mudlib.zone import BoundaryRegion, SpawnRule, Zone

log = logging.getLogger(__name__)

# Module-level zone registry
zone_registry: dict[str, Zone] = {}


def register_zone(name: str, zone: Zone) -> None:
    """Register a zone by name.

    Args:
        name: Unique name for the zone
        zone: Zone instance to register
    """
    zone_registry[name] = zone


def get_zone(name: str) -> Zone | None:
    """Look up a zone by name.

    Args:
        name: Zone name to look up

    Returns:
        Zone instance if found, None otherwise
    """
    return zone_registry.get(name)


def load_zone(path: Path) -> Zone:
    """Load a zone from a TOML file.

    Args:
        path: Path to TOML file

    Returns:
        Zone instance loaded from file
    """
    with open(path, "rb") as f:
        data = tomllib.load(f)

    # Extract basic properties
    name = data["name"]
    description = data.get("description", "")
    width = data["width"]
    height = data["height"]
    toroidal = data.get("toroidal", True)
    spawn_x = data.get("spawn_x", 0)
    spawn_y = data.get("spawn_y", 0)
    safe = data.get("safe", False)

    # Parse terrain rows into 2D list
    terrain_rows = data.get("terrain", {}).get("rows", [])
    terrain = []
    for row in terrain_rows:
        terrain.append(list(row))

    # Parse impassable tiles
    impassable_list = data.get("terrain", {}).get("impassable", {}).get("tiles", [])
    impassable = set(impassable_list) if impassable_list else {"^", "~"}

    # Parse ambient messages
    ambient_data = data.get("ambient", {})
    ambient_messages = ambient_data.get("messages", [])
    ambient_interval = ambient_data.get("interval", 120)

    # Parse spawn rules
    spawns_data = data.get("spawns", [])
    spawn_rules = [
        SpawnRule(
            mob=spawn["mob"],
            max_count=spawn.get("max_count", 1),
            respawn_seconds=spawn.get("respawn_seconds", 300),
            home_region=spawn.get("home_region"),
        )
        for spawn in spawns_data
    ]

    # Parse boundaries
    boundaries_data = data.get("boundaries", [])
    boundaries = [
        BoundaryRegion(
            name=boundary["name"],
            x_min=boundary["x"][0],
            x_max=boundary["x"][1],
            y_min=boundary["y"][0],
            y_max=boundary["y"][1],
            on_enter_message=boundary.get("on_enter_message"),
            on_exit_message=boundary.get("on_exit_message"),
            on_exit_check=boundary.get("on_exit_check"),
            on_exit_fail=boundary.get("on_exit_fail"),
        )
        for boundary in boundaries_data
    ]

    zone = Zone(
        name=name,
        description=description,
        width=width,
        height=height,
        toroidal=toroidal,
        terrain=terrain,
        impassable=impassable,
        spawn_x=spawn_x,
        spawn_y=spawn_y,
        ambient_messages=ambient_messages,
        ambient_interval=ambient_interval,
        spawn_rules=spawn_rules,
        safe=safe,
        boundaries=boundaries,
    )

    # Load portals
    portals_data = data.get("portals", [])
    for portal_dict in portals_data:
        # Parse target string "zone_name:x,y"
        target = portal_dict["target"]
        try:
            target_zone, coords = target.split(":")
            target_x, target_y = map(int, coords.split(","))
        except ValueError:
            log.warning(
                "skipping portal '%s' at (%d, %d): malformed target '%s'",
                portal_dict["label"],
                portal_dict["x"],
                portal_dict["y"],
                target,
            )
            continue

        # Create portal (automatically added to zone._contents via Object.__post_init__)
        Portal(
            name=portal_dict["label"],
            aliases=portal_dict.get("aliases", []),
            target_zone=target_zone,
            target_x=target_x,
            target_y=target_y,
            location=zone,
            x=portal_dict["x"],
            y=portal_dict["y"],
        )

    return zone


def load_zones(directory: Path) -> dict[str, Zone]:
    """Load all zones from a directory.

    Args:
        directory: Path to directory containing zone TOML files

    Returns:
        Dict mapping zone names to Zone instances
    """
    zones = {}

    if not directory.exists():
        log.warning("zones directory does not exist: %s", directory)
        return zones

    for toml_file in directory.glob("*.toml"):
        try:
            zone = load_zone(toml_file)
            zones[zone.name] = zone
            log.debug("loaded zone '%s' from %s", zone.name, toml_file)
        except Exception as e:
            log.error("failed to load zone from %s: %s", toml_file, e, exc_info=True)

    return zones
