"""Tests for container state display in look and inventory commands."""

from unittest.mock import AsyncMock, MagicMock

import pytest

from mudlib.container import Container
from mudlib.player import Player
from mudlib.thing import Thing
from mudlib.zone import Zone


@pytest.fixture
def mock_writer():
    writer = MagicMock()
    writer.write = MagicMock()
    writer.drain = AsyncMock()
    return writer


@pytest.fixture
def mock_reader():
    return MagicMock()


@pytest.fixture
def test_zone():
    terrain = [["." for _ in range(10)] for _ in range(10)]
    return Zone(
        name="testzone",
        width=10,
        height=10,
        toroidal=True,
        terrain=terrain,
    )


@pytest.fixture
def player(mock_reader, mock_writer, test_zone):
    p = Player(
        name="TestPlayer",
        x=5,
        y=5,
        reader=mock_reader,
        writer=mock_writer,
        location=test_zone,
    )
    return p


# --- look command container display ---


@pytest.mark.asyncio
async def test_look_shows_closed_container(player, test_zone, mock_writer):
    """look shows closed containers with (closed) suffix."""
    from mudlib.commands.look import cmd_look

    Container(name="chest", location=test_zone, x=5, y=5, closed=True)
    await cmd_look(player, "")
    output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
    assert "chest (closed)" in output


@pytest.mark.asyncio
async def test_look_shows_open_empty_container(player, test_zone, mock_writer):
    """look shows open empty containers with (open, empty) suffix."""
    from mudlib.commands.look import cmd_look

    Container(name="chest", location=test_zone, x=5, y=5, closed=False)
    await cmd_look(player, "")
    output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
    assert "chest (open, empty)" in output


@pytest.mark.asyncio
async def test_look_shows_open_container_with_contents(player, test_zone, mock_writer):
    """look shows open containers with their contents."""
    from mudlib.commands.look import cmd_look

    chest = Container(name="chest", location=test_zone, x=5, y=5, closed=False)
    Thing(name="rock", location=chest)
    Thing(name="coin", location=chest)
    await cmd_look(player, "")
    output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
    assert "chest (open, containing: rock, coin)" in output


@pytest.mark.asyncio
async def test_look_shows_regular_things_unchanged(player, test_zone, mock_writer):
    """look shows regular Things without container suffixes."""
    from mudlib.commands.look import cmd_look

    Thing(name="rock", location=test_zone, x=5, y=5)
    await cmd_look(player, "")
    output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
    assert "On the ground: rock" in output
    assert "(closed)" not in output
    assert "(open" not in output


# --- inventory command container display ---


@pytest.mark.asyncio
async def test_inventory_shows_closed_container(player, mock_writer):
    """inventory shows closed containers with (closed) suffix."""
    from mudlib.commands.things import cmd_inventory

    Container(name="sack", location=player, closed=True)
    await cmd_inventory(player, "")
    output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
    assert "sack (closed)" in output


@pytest.mark.asyncio
async def test_inventory_shows_open_empty_container(player, mock_writer):
    """inventory shows open empty containers with (open, empty) suffix."""
    from mudlib.commands.things import cmd_inventory

    Container(name="sack", location=player, closed=False)
    await cmd_inventory(player, "")
    output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
    assert "sack (open, empty)" in output


@pytest.mark.asyncio
async def test_inventory_shows_container_with_contents(player, mock_writer):
    """inventory shows open containers with their contents."""
    from mudlib.commands.things import cmd_inventory

    sack = Container(name="sack", location=player, closed=False)
    Thing(name="rock", location=sack)
    Thing(name="gem", location=sack)
    await cmd_inventory(player, "")
    output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
    assert "sack (open, containing: rock, gem)" in output


@pytest.mark.asyncio
async def test_inventory_shows_regular_things_unchanged(player, mock_writer):
    """inventory shows regular Things without container suffixes."""
    from mudlib.commands.things import cmd_inventory

    Thing(name="rock", location=player)
    await cmd_inventory(player, "")
    output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
    assert "  rock\r\n" in output
    assert "(closed)" not in output
    assert "(open" not in output
