"""Tests for zone loading from TOML files."""

import pathlib
import tempfile

from mudlib.portal import Portal
from mudlib.zones import load_zone, load_zones


def test_load_zone():
    """Load a zone from TOML file."""
    # Create a temporary TOML file
    with tempfile.NamedTemporaryFile(mode="w", suffix=".toml", delete=False) as f:
        f.write("""
name = "test_zone"
description = "a test zone"
width = 4
height = 3
toroidal = false

[terrain]
rows = [
    "####",
    "#..#",
    "####",
]

[terrain.impassable]
tiles = ["#"]
""")
        temp_path = pathlib.Path(f.name)

    try:
        zone = load_zone(temp_path)

        assert zone.name == "test_zone"
        assert zone.width == 4
        assert zone.height == 3
        assert zone.toroidal is False
        assert len(zone.terrain) == 3
        assert zone.terrain[0] == ["#", "#", "#", "#"]
        assert zone.terrain[1] == ["#", ".", ".", "#"]
        assert zone.terrain[2] == ["#", "#", "#", "#"]
        assert zone.impassable == {"#"}
    finally:
        temp_path.unlink()


def test_load_zone_toroidal():
    """Load a toroidal zone."""
    with tempfile.NamedTemporaryFile(mode="w", suffix=".toml", delete=False) as f:
        f.write("""
name = "toroidal_zone"
description = "a toroidal test zone"
width = 3
height = 2
toroidal = true

[terrain]
rows = [
    "...",
    "...",
]
""")
        temp_path = pathlib.Path(f.name)

    try:
        zone = load_zone(temp_path)

        assert zone.toroidal is True
        # Default impassable set from Zone class
        assert zone.impassable == {"^", "~"}
    finally:
        temp_path.unlink()


def test_load_zones_from_directory():
    """Load all zones from a directory."""
    with tempfile.TemporaryDirectory() as tmpdir:
        tmpdir_path = pathlib.Path(tmpdir)

        # Create two zone files
        zone1_path = tmpdir_path / "zone1.toml"
        zone1_path.write_text("""
name = "zone1"
description = "first zone"
width = 2
height = 2
toroidal = false

[terrain]
rows = [
    "..",
    "..",
]
""")

        zone2_path = tmpdir_path / "zone2.toml"
        zone2_path.write_text("""
name = "zone2"
description = "second zone"
width = 3
height = 3
toroidal = true

[terrain]
rows = [
    "###",
    "#.#",
    "###",
]
""")

        # Create a non-TOML file that should be ignored
        (tmpdir_path / "readme.txt").write_text("not a zone file")

        zones = load_zones(tmpdir_path)

        assert len(zones) == 2
        assert "zone1" in zones
        assert "zone2" in zones
        assert zones["zone1"].name == "zone1"
        assert zones["zone2"].name == "zone2"


def test_load_tavern_zone():
    """Load the actual tavern zone file."""
    # This tests the real tavern.toml file in content/zones/
    project_root = pathlib.Path(__file__).resolve().parents[1]
    tavern_path = project_root / "content" / "zones" / "tavern.toml"

    zone = load_zone(tavern_path)

    assert zone.name == "tavern"
    assert zone.width == 8
    assert zone.height == 6
    assert zone.toroidal is False
    assert zone.spawn_x == 1
    assert zone.spawn_y == 1
    assert len(zone.terrain) == 6
    assert zone.terrain[0] == ["#", "#", "#", "#", "#", "#", "#", "#"]
    assert zone.terrain[5] == ["#", "#", "#", "#", ".", "#", "#", "#"]
    assert zone.impassable == {"#"}
    # Check that interior is passable
    assert zone.is_passable(1, 1)
    assert zone.is_passable(4, 3)
    # Check that walls are impassable
    assert not zone.is_passable(0, 0)
    assert not zone.is_passable(7, 0)


def test_load_zone_with_spawn_point():
    """Load a zone with spawn_x and spawn_y defined."""
    with tempfile.NamedTemporaryFile(mode="w", suffix=".toml", delete=False) as f:
        f.write("""
name = "spawn_zone"
description = "a zone with spawn point"
width = 10
height = 10
spawn_x = 5
spawn_y = 7

[terrain]
rows = [
    "..........",
    "..........",
    "..........",
    "..........",
    "..........",
    "..........",
    "..........",
    "..........",
    "..........",
    "..........",
]
""")
        temp_path = pathlib.Path(f.name)

    try:
        zone = load_zone(temp_path)

        assert zone.spawn_x == 5
        assert zone.spawn_y == 7
    finally:
        temp_path.unlink()


def test_load_zone_default_spawn_point():
    """Load a zone without spawn point defined defaults to (0, 0)."""
    with tempfile.NamedTemporaryFile(mode="w", suffix=".toml", delete=False) as f:
        f.write("""
name = "default_spawn"
description = "a zone without spawn point"
width = 5
height = 5

[terrain]
rows = [
    ".....",
    ".....",
    ".....",
    ".....",
    ".....",
]
""")
        temp_path = pathlib.Path(f.name)

    try:
        zone = load_zone(temp_path)

        assert zone.spawn_x == 0
        assert zone.spawn_y == 0
    finally:
        temp_path.unlink()


def test_load_zone_with_portals():
    """Load a zone with portals defined."""
    with tempfile.NamedTemporaryFile(mode="w", suffix=".toml", delete=False) as f:
        f.write("""
name = "portal_zone"
description = "a zone with portals"
width = 10
height = 10

[terrain]
rows = [
    "..........",
    "..........",
    "..........",
    "..........",
    "..........",
    "..........",
    "..........",
    "..........",
    "..........",
    "..........",
]

[[portals]]
x = 5
y = 3
target = "tavern:1,1"
label = "tavern door"

[[portals]]
x = 2
y = 7
target = "forest:10,5"
label = "forest path"
""")
        temp_path = pathlib.Path(f.name)

    try:
        zone = load_zone(temp_path)

        # Find portals in zone contents
        portals = [obj for obj in zone._contents if isinstance(obj, Portal)]
        assert len(portals) == 2

        # Check first portal (tavern door at 5,3)
        tavern_portal = [p for p in portals if p.name == "tavern door"][0]
        assert tavern_portal.x == 5
        assert tavern_portal.y == 3
        assert tavern_portal.target_zone == "tavern"
        assert tavern_portal.target_x == 1
        assert tavern_portal.target_y == 1
        assert tavern_portal.location == zone

        # Check second portal (forest path at 2,7)
        forest_portal = [p for p in portals if p.name == "forest path"][0]
        assert forest_portal.x == 2
        assert forest_portal.y == 7
        assert forest_portal.target_zone == "forest"
        assert forest_portal.target_x == 10
        assert forest_portal.target_y == 5
        assert forest_portal.location == zone

        # Verify portals are at correct coordinates
        contents_at_5_3 = zone.contents_at(5, 3)
        assert tavern_portal in contents_at_5_3

        contents_at_2_7 = zone.contents_at(2, 7)
        assert forest_portal in contents_at_2_7
    finally:
        temp_path.unlink()


def test_load_zone_without_portals():
    """Load a zone without portals section works fine."""
    with tempfile.NamedTemporaryFile(mode="w", suffix=".toml", delete=False) as f:
        f.write("""
name = "no_portals"
description = "a zone without portals"
width = 3
height = 3

[terrain]
rows = [
    "...",
    "...",
    "...",
]
""")
        temp_path = pathlib.Path(f.name)

    try:
        zone = load_zone(temp_path)

        # Should have no portals
        portals = [obj for obj in zone._contents if isinstance(obj, Portal)]
        assert len(portals) == 0
    finally:
        temp_path.unlink()


def test_load_zone_portal_with_aliases():
    """Portal can have optional aliases field in TOML."""
    with tempfile.NamedTemporaryFile(mode="w", suffix=".toml", delete=False) as f:
        f.write("""
name = "alias_zone"
description = "a zone with aliased portal"
width = 5
height = 5

[terrain]
rows = [
    ".....",
    ".....",
    ".....",
    ".....",
    ".....",
]

[[portals]]
x = 2
y = 2
target = "elsewhere:0,0"
label = "mysterious gateway"
aliases = ["gateway", "gate", "portal"]
""")
        temp_path = pathlib.Path(f.name)

    try:
        zone = load_zone(temp_path)

        portals = [obj for obj in zone._contents if isinstance(obj, Portal)]
        assert len(portals) == 1

        portal = portals[0]
        assert portal.name == "mysterious gateway"
        assert portal.aliases == ["gateway", "gate", "portal"]
    finally:
        temp_path.unlink()


def test_tavern_has_portal_to_hub():
    """Tavern zone has a portal at the door leading to hub zone."""
    project_root = pathlib.Path(__file__).resolve().parents[1]
    tavern_path = project_root / "content" / "zones" / "tavern.toml"

    zone = load_zone(tavern_path)

    # Find portals in zone
    portals = [obj for obj in zone._contents if isinstance(obj, Portal)]
    assert len(portals) == 1

    # Check portal is at the door (4, 5) and leads to hub
    portal = portals[0]
    assert portal.name == "the tavern door"
    assert portal.x == 4
    assert portal.y == 5
    assert portal.target_zone == "hub"
    assert portal.target_x == 14
    assert portal.target_y == 7

    # Verify portal is accessible at door coordinates
    contents_at_door = zone.contents_at(4, 5)
    assert portal in contents_at_door
