"""Tests for the MockWorldAdapter — full observe/act/speak cycle."""

from infrastructure.world.adapters.mock import MockWorldAdapter
from infrastructure.world.types import ActionStatus, CommandInput, PerceptionOutput


class TestMockWorldAdapter:
    def test_observe_returns_perception(self):
        adapter = MockWorldAdapter(location="Vivec")
        perception = adapter.observe()
        assert isinstance(perception, PerceptionOutput)
        assert perception.location == "Vivec"
        assert perception.raw == {"adapter": "mock"}

    def test_observe_entities(self):
        adapter = MockWorldAdapter(entities=["Jiub", "Silt Strider"])
        perception = adapter.observe()
        assert perception.entities == ["Jiub", "Silt Strider"]

    def test_act_logs_command(self):
        adapter = MockWorldAdapter()
        cmd = CommandInput(action="move", target="north")
        result = adapter.act(cmd)
        assert result.status == ActionStatus.SUCCESS
        assert "move" in result.message
        assert len(adapter.action_log) == 1
        assert adapter.action_log[0].command.action == "move"

    def test_act_multiple_commands(self):
        adapter = MockWorldAdapter()
        adapter.act(CommandInput(action="attack"))
        adapter.act(CommandInput(action="defend"))
        adapter.act(CommandInput(action="retreat"))
        assert len(adapter.action_log) == 3

    def test_speak_logs_message(self):
        adapter = MockWorldAdapter()
        adapter.speak("Hello, traveler!")
        assert len(adapter.speech_log) == 1
        assert adapter.speech_log[0]["message"] == "Hello, traveler!"
        assert adapter.speech_log[0]["target"] is None

    def test_speak_with_target(self):
        adapter = MockWorldAdapter()
        adapter.speak("Die, scum!", target="Cliff Racer")
        assert adapter.speech_log[0]["target"] == "Cliff Racer"

    def test_lifecycle(self):
        adapter = MockWorldAdapter()
        assert adapter.is_connected is False
        adapter.connect()
        assert adapter.is_connected is True
        adapter.disconnect()
        assert adapter.is_connected is False

    def test_full_observe_act_speak_cycle(self):
        """Acceptance criterion: full observe/act/speak cycle passes."""
        adapter = MockWorldAdapter(
            location="Seyda Neen",
            entities=["Fargoth", "Hrisskar"],
            events=["quest_started"],
        )
        adapter.connect()

        # Observe
        perception = adapter.observe()
        assert perception.location == "Seyda Neen"
        assert len(perception.entities) == 2
        assert "quest_started" in perception.events

        # Act
        result = adapter.act(CommandInput(action="talk", target="Fargoth"))
        assert result.status == ActionStatus.SUCCESS

        # Speak
        adapter.speak("Where is your ring, Fargoth?", target="Fargoth")
        assert len(adapter.speech_log) == 1

        adapter.disconnect()
        assert adapter.is_connected is False
