"""Tests for furniture persistence in home zones."""

import logging
import tomllib

import pytest

from mudlib.entity import Entity
from mudlib.housing import (
    create_home_zone,
    init_housing,
    load_home_zone,
    save_home_zone,
)
from mudlib.portal import Portal
from mudlib.thing import Thing
from mudlib.things import ThingTemplate, spawn_thing, thing_templates
from mudlib.zones import zone_registry


@pytest.fixture(autouse=True)
def _clean_registries():
    """Clear registries between tests."""
    saved_zones = dict(zone_registry)
    saved_templates = dict(thing_templates)
    zone_registry.clear()
    thing_templates.clear()
    yield
    zone_registry.clear()
    zone_registry.update(saved_zones)
    thing_templates.clear()
    thing_templates.update(saved_templates)


def test_save_furniture_in_zone_toml(tmp_path):
    """save_home_zone() writes furniture to TOML."""
    init_housing(tmp_path)

    # Create zone
    zone = create_home_zone("Alice")

    # Add a thing template
    table_template = ThingTemplate(
        name="table",
        description="A wooden table",
        portable=False,
    )
    thing_templates["table"] = table_template

    # Spawn furniture in the zone
    spawn_thing(table_template, zone, x=3, y=4)

    # Save
    save_home_zone("Alice", zone)

    # Read the TOML file
    zone_file = tmp_path / "alice.toml"
    with open(zone_file, "rb") as f:
        data = tomllib.load(f)

    # Check furniture section
    assert "furniture" in data
    assert len(data["furniture"]) == 1
    assert data["furniture"][0]["template"] == "table"
    assert data["furniture"][0]["x"] == 3
    assert data["furniture"][0]["y"] == 4


def test_load_furniture_from_toml(tmp_path):
    """load_home_zone() spawns furniture from TOML."""
    init_housing(tmp_path)

    # Create zone to get the file
    _ = create_home_zone("Bob")
    zone_file = tmp_path / "bob.toml"

    # Add furniture entries to the TOML
    with open(zone_file) as f:
        content = f.read()
    content += """
[[furniture]]
template = "chair"
x = 5
y = 6
"""
    with open(zone_file, "w") as f:
        f.write(content)

    # Add template
    chair_template = ThingTemplate(
        name="chair",
        description="A wooden chair",
        portable=True,
    )
    thing_templates["chair"] = chair_template

    # Clear registry and load
    zone_registry.clear()
    loaded = load_home_zone("Bob")

    assert loaded is not None

    # Check that furniture was spawned
    chairs = [
        obj
        for obj in loaded._contents
        if isinstance(obj, Thing) and obj.name == "chair"
    ]
    assert len(chairs) == 1
    assert chairs[0].x == 5
    assert chairs[0].y == 6
    assert chairs[0].description == "A wooden chair"


def test_furniture_round_trip(tmp_path):
    """Furniture survives save -> load cycle."""
    init_housing(tmp_path)

    # Create zone
    zone = create_home_zone("Charlie")

    # Add templates
    table_template = ThingTemplate(name="table", description="A table", portable=False)
    chair_template = ThingTemplate(name="chair", description="A chair", portable=True)
    thing_templates["table"] = table_template
    thing_templates["chair"] = chair_template

    # Spawn furniture
    spawn_thing(table_template, zone, x=3, y=4)
    spawn_thing(chair_template, zone, x=3, y=5)

    # Save
    save_home_zone("Charlie", zone)

    # Clear registry and load
    zone_registry.clear()
    loaded = load_home_zone("Charlie")

    assert loaded is not None

    # Check furniture
    tables = [obj for obj in loaded._contents if obj.name == "table"]
    chairs = [obj for obj in loaded._contents if obj.name == "chair"]

    assert len(tables) == 1
    assert tables[0].x == 3
    assert tables[0].y == 4

    assert len(chairs) == 1
    assert chairs[0].x == 3
    assert chairs[0].y == 5


def test_multiple_furniture_items(tmp_path):
    """Multiple furniture items save and load correctly."""
    init_housing(tmp_path)

    zone = create_home_zone("Dave")

    # Add templates
    chair_template = ThingTemplate(name="chair", description="A chair", portable=True)
    thing_templates["chair"] = chair_template

    # Spawn multiple chairs
    spawn_thing(chair_template, zone, x=2, y=2)
    spawn_thing(chair_template, zone, x=3, y=2)
    spawn_thing(chair_template, zone, x=4, y=2)

    # Save
    save_home_zone("Dave", zone)

    # Load
    zone_registry.clear()
    loaded = load_home_zone("Dave")

    assert loaded is not None

    chairs = [obj for obj in loaded._contents if obj.name == "chair"]
    assert len(chairs) == 3

    # Check positions
    positions = {(c.x, c.y) for c in chairs}
    assert positions == {(2, 2), (3, 2), (4, 2)}


def test_load_unknown_template_skips(tmp_path, caplog):
    """Unknown template name in TOML is skipped with warning."""
    caplog.set_level(logging.WARNING)
    init_housing(tmp_path)

    # Create zone
    _ = create_home_zone("Eve")
    zone_file = tmp_path / "eve.toml"

    # Add furniture with unknown template
    with open(zone_file) as f:
        content = f.read()
    content += """
[[furniture]]
template = "unknown_thing"
x = 1
y = 1
"""
    with open(zone_file, "w") as f:
        f.write(content)

    # Load
    zone_registry.clear()
    loaded = load_home_zone("Eve")

    assert loaded is not None

    # Check that no furniture was spawned
    things = [obj for obj in loaded._contents if isinstance(obj, Thing)]
    assert len(things) == 0

    # Check that warning was logged
    assert "unknown_thing" in caplog.text.lower()


def test_save_excludes_entities(tmp_path):
    """Entities in zone are NOT saved as furniture."""
    init_housing(tmp_path)

    zone = create_home_zone("Frank")

    # Add an entity to the zone
    _ = Entity(name="test_mob", location=zone, x=5, y=5)

    # Save
    save_home_zone("Frank", zone)

    # Read the TOML
    zone_file = tmp_path / "frank.toml"
    with open(zone_file, "rb") as f:
        data = tomllib.load(f)

    # Furniture section should not exist or be empty
    furniture = data.get("furniture", [])
    assert len(furniture) == 0


def test_save_excludes_portals(tmp_path):
    """Portals are NOT saved as furniture."""
    init_housing(tmp_path)

    zone = create_home_zone("Grace")

    # Add a portal to the zone
    _ = Portal(
        name="exit",
        description="An exit",
        location=zone,
        x=1,
        y=1,
        target_zone="overworld",
        target_x=10,
        target_y=10,
    )

    # Save
    save_home_zone("Grace", zone)

    # Read the TOML
    zone_file = tmp_path / "grace.toml"
    with open(zone_file, "rb") as f:
        data = tomllib.load(f)

    # Furniture section should not exist or be empty
    furniture = data.get("furniture", [])
    assert len(furniture) == 0
