"""Tests for zone export to TOML files."""

import pathlib
import tempfile

from mudlib.export import export_zone, export_zone_to_file
from mudlib.portal import Portal
from mudlib.zone import SpawnRule, Zone
from mudlib.zones import load_zone


def test_export_basic_zone():
    """Export a simple zone and verify TOML output has correct fields."""
    zone = Zone(
        name="test_zone",
        width=4,
        height=3,
        toroidal=False,
        terrain=[
            ["#", "#", "#", "#"],
            ["#", ".", ".", "#"],
            ["#", "#", "#", "#"],
        ],
        impassable={"#"},
        spawn_x=0,
        spawn_y=0,
    )
    # Set description as an attribute (zones loaded from TOML have this)
    zone.description = "a test zone"

    toml_str = export_zone(zone)

    # Verify basic fields are present
    assert 'name = "test_zone"' in toml_str
    assert 'description = "a test zone"' in toml_str
    assert "width = 4" in toml_str
    assert "height = 3" in toml_str
    assert "toroidal = false" in toml_str
    assert "spawn_x = 0" in toml_str
    assert "spawn_y = 0" in toml_str

    # Verify terrain section
    assert "[terrain]" in toml_str
    assert '"####"' in toml_str
    assert '"#..#"' in toml_str

    # Verify impassable tiles
    assert "[terrain.impassable]" in toml_str
    assert '"#"' in toml_str


def test_export_zone_round_trip():
    """Export a zone, load it back, verify it matches the original."""
    original = Zone(
        name="round_trip",
        width=5,
        height=4,
        toroidal=True,
        terrain=[
            [".", ".", ".", ".", "."],
            [".", "#", "#", "#", "."],
            [".", "#", ".", "#", "."],
            [".", ".", ".", ".", "."],
        ],
        impassable={"#"},
        spawn_x=2,
        spawn_y=1,
    )
    original.description = "round trip test"

    toml_str = export_zone(original)

    # Write to temp file and load back
    with tempfile.NamedTemporaryFile(mode="w", suffix=".toml", delete=False) as f:
        f.write(toml_str)
        temp_path = pathlib.Path(f.name)

    try:
        loaded = load_zone(temp_path)

        # Verify all fields match
        assert loaded.name == original.name
        assert loaded.description == original.description
        assert loaded.width == original.width
        assert loaded.height == original.height
        assert loaded.toroidal == original.toroidal
        assert loaded.spawn_x == original.spawn_x
        assert loaded.spawn_y == original.spawn_y
        assert loaded.terrain == original.terrain
        assert loaded.impassable == original.impassable
    finally:
        temp_path.unlink()


def test_export_zone_with_portals():
    """Zone with Portal objects exports [[portals]] sections."""
    zone = Zone(
        name="portal_zone",
        width=10,
        height=10,
        terrain=[["." for _ in range(10)] for _ in range(10)],
        impassable=set(),
    )
    zone.description = "a zone with portals"

    # Add portals
    Portal(
        name="tavern door",
        location=zone,
        x=5,
        y=3,
        target_zone="tavern",
        target_x=1,
        target_y=1,
    )
    Portal(
        name="forest path",
        aliases=["path", "entrance"],
        location=zone,
        x=2,
        y=7,
        target_zone="forest",
        target_x=10,
        target_y=5,
    )

    toml_str = export_zone(zone)

    # Verify portals section exists
    assert "[[portals]]" in toml_str

    # Verify first portal
    assert "x = 5" in toml_str
    assert "y = 3" in toml_str
    assert 'target = "tavern:1,1"' in toml_str
    assert 'label = "tavern door"' in toml_str

    # Verify second portal
    assert "x = 2" in toml_str
    assert "y = 7" in toml_str
    assert 'target = "forest:10,5"' in toml_str
    assert 'label = "forest path"' in toml_str
    assert 'aliases = ["path", "entrance"]' in toml_str


def test_export_zone_with_portals_round_trip():
    """Export a zone with portals, load it back, verify portals match."""
    zone = Zone(
        name="portal_round_trip",
        width=8,
        height=6,
        toroidal=False,
        terrain=[["." for _ in range(8)] for _ in range(6)],
        impassable=set(),
        spawn_x=0,
        spawn_y=0,
    )
    zone.description = "portal round trip test"

    # Add portals
    Portal(
        name="tavern door",
        location=zone,
        x=5,
        y=3,
        target_zone="tavern",
        target_x=1,
        target_y=2,
    )
    Portal(
        name="forest path",
        aliases=["path"],
        location=zone,
        x=2,
        y=4,
        target_zone="forest",
        target_x=10,
        target_y=5,
    )

    toml_str = export_zone(zone)

    # Write to temp file and load back
    with tempfile.NamedTemporaryFile(mode="w", suffix=".toml", delete=False) as f:
        f.write(toml_str)
        temp_path = pathlib.Path(f.name)

    try:
        loaded = load_zone(temp_path)

        # Verify basic zone fields
        assert loaded.name == zone.name
        assert loaded.description == zone.description
        assert loaded.width == zone.width
        assert loaded.height == zone.height

        # Verify portals were loaded correctly
        portals = [obj for obj in loaded._contents if isinstance(obj, Portal)]
        assert len(portals) == 2

        # Sort by y coordinate for consistent ordering
        portals.sort(key=lambda p: (p.y, p.x))

        # Verify first portal (tavern door at 5,3)
        assert portals[0].name == "tavern door"
        assert portals[0].x == 5
        assert portals[0].y == 3
        assert portals[0].target_zone == "tavern"
        assert portals[0].target_x == 1
        assert portals[0].target_y == 2

        # Verify second portal (forest path at 2,4)
        assert portals[1].name == "forest path"
        assert portals[1].x == 2
        assert portals[1].y == 4
        assert portals[1].target_zone == "forest"
        assert portals[1].target_x == 10
        assert portals[1].target_y == 5
        assert "path" in portals[1].aliases
    finally:
        temp_path.unlink()


def test_export_zone_with_spawn_point():
    """spawn_x/spawn_y are in the output."""
    zone = Zone(
        name="spawn_zone",
        width=10,
        height=10,
        terrain=[["." for _ in range(10)] for _ in range(10)],
        spawn_x=5,
        spawn_y=7,
    )
    zone.description = "a zone with spawn point"

    toml_str = export_zone(zone)

    assert "spawn_x = 5" in toml_str
    assert "spawn_y = 7" in toml_str


def test_export_zone_to_file():
    """Write TOML to a file, load it back."""
    zone = Zone(
        name="file_zone",
        width=3,
        height=3,
        terrain=[
            ["#", "#", "#"],
            ["#", ".", "#"],
            ["#", "#", "#"],
        ],
        impassable={"#"},
    )
    zone.description = "exported to file"

    with tempfile.TemporaryDirectory() as tmpdir:
        output_path = pathlib.Path(tmpdir) / "test_zone.toml"

        export_zone_to_file(zone, output_path)

        # Verify file exists
        assert output_path.exists()

        # Load it back
        loaded = load_zone(output_path)

        assert loaded.name == zone.name
        assert loaded.width == zone.width
        assert loaded.height == zone.height
        assert loaded.terrain == zone.terrain


def test_export_zone_with_ambient_messages():
    """Zone with ambient messages exports [ambient] section."""
    zone = Zone(
        name="ambient_zone",
        width=5,
        height=5,
        terrain=[["." for _ in range(5)] for _ in range(5)],
        ambient_messages=[
            "Birds chirp overhead.",
            "A cool breeze passes by.",
            "Leaves rustle in the distance.",
        ],
        ambient_interval=90,
    )
    zone.description = "a zone with ambient messages"

    toml_str = export_zone(zone)

    # Verify ambient section
    assert "[ambient]" in toml_str
    assert "interval = 90" in toml_str
    assert "Birds chirp overhead." in toml_str
    assert "A cool breeze passes by." in toml_str
    assert "Leaves rustle in the distance." in toml_str


def test_export_zone_with_spawn_rules():
    """Zone with spawn rules exports [[spawns]] sections."""
    zone = Zone(
        name="spawn_zone",
        width=10,
        height=10,
        terrain=[["." for _ in range(10)] for _ in range(10)],
        spawn_rules=[
            SpawnRule(mob="squirrel", max_count=2, respawn_seconds=180),
            SpawnRule(mob="crow", max_count=1, respawn_seconds=300),
        ],
    )

    toml_str = export_zone(zone)

    # Verify spawns sections
    assert "[[spawns]]" in toml_str
    assert 'mob = "squirrel"' in toml_str
    assert "max_count = 2" in toml_str
    assert "respawn_seconds = 180" in toml_str
    assert 'mob = "crow"' in toml_str
    assert "max_count = 1" in toml_str
    assert "respawn_seconds = 300" in toml_str


def test_export_safe_zone():
    """Export includes safe = true when zone is safe."""
    terrain = [["." for _ in range(3)] for _ in range(3)]
    zone = Zone(
        name="sanctuary",
        width=3,
        height=3,
        terrain=terrain,
        safe=True,
    )
    result = export_zone(zone)
    assert "safe = true" in result


def test_export_unsafe_zone_omits_safe():
    """Export omits safe field when zone is not safe (default)."""
    terrain = [["." for _ in range(3)] for _ in range(3)]
    zone = Zone(
        name="wilderness",
        width=3,
        height=3,
        terrain=terrain,
        safe=False,
    )
    result = export_zone(zone)
    assert "safe" not in result


def test_export_spawn_with_home_region():
    """Export includes home_region on spawn rules when present."""
    terrain = [["." for _ in range(5)] for _ in range(5)]
    zone = Zone(
        name="forest",
        width=5,
        height=5,
        terrain=terrain,
        spawn_rules=[
            SpawnRule(
                mob="squirrel",
                max_count=2,
                respawn_seconds=180,
                home_region={"x": [5, 15], "y": [3, 10]},
            )
        ],
    )
    result = export_zone(zone)
    assert "home_region" in result
    assert "x = [5, 15]" in result
    assert "y = [3, 10]" in result


def test_export_spawn_without_home_region():
    """Export omits home_region when not set."""
    terrain = [["." for _ in range(5)] for _ in range(5)]
    zone = Zone(
        name="forest",
        width=5,
        height=5,
        terrain=terrain,
        spawn_rules=[SpawnRule(mob="goblin", max_count=1)],
    )
    result = export_zone(zone)
    assert "home_region" not in result


def test_export_safe_zone_round_trip():
    """Safe zone survives export/import round-trip."""
    terrain = [["." for _ in range(3)] for _ in range(3)]
    zone = Zone(
        name="temple",
        width=3,
        height=3,
        terrain=terrain,
        safe=True,
    )

    with tempfile.NamedTemporaryFile(mode="w", suffix=".toml", delete=False) as f:
        f.write(export_zone(zone))
        temp_path = pathlib.Path(f.name)

    try:
        reloaded = load_zone(temp_path)
        assert reloaded.safe is True
    finally:
        temp_path.unlink()


def test_export_home_region_round_trip():
    """Home region on spawn rules survives export/import round-trip."""
    terrain = [["." for _ in range(5)] for _ in range(5)]
    zone = Zone(
        name="woods",
        width=5,
        height=5,
        terrain=terrain,
        spawn_rules=[
            SpawnRule(
                mob="deer",
                max_count=3,
                respawn_seconds=120,
                home_region={"x": [1, 4], "y": [1, 4]},
            )
        ],
    )

    with tempfile.NamedTemporaryFile(mode="w", suffix=".toml", delete=False) as f:
        f.write(export_zone(zone))
        temp_path = pathlib.Path(f.name)

    try:
        reloaded = load_zone(temp_path)
        assert len(reloaded.spawn_rules) == 1
        rule = reloaded.spawn_rules[0]
        assert rule.home_region == {"x": [1, 4], "y": [1, 4]}
    finally:
        temp_path.unlink()
