"""Tests for {{ module_name }} robot arm interface.

These tests use the fake interface to validate the interface contract
without requiring actual hardware. They cover the full robot arm lifecycle:
connect, initialize, home, pick, place, move, shutdown, and disconnect.

Generated by: madsci new module --template module/robot_arm
Template version: {{ template_version }}
"""

import pytest

from {{ module_name }}_fake_interface import {{ module_name | pascal_case }}FakeInterface


class Test{{ module_name | pascal_case }}FakeInterface:
    """Test cases for the {{ module_name }} fake robot arm interface."""

    @pytest.fixture
    def interface(self) -> {{ module_name | pascal_case }}FakeInterface:
        """Create a test interface instance with low latency."""
        return {{ module_name | pascal_case }}FakeInterface(simulated_latency=0.01)

    def test_initial_state(self, interface: {{ module_name | pascal_case }}FakeInterface) -> None:
        """Test that interface starts disconnected and uninitialized."""
        assert not interface.is_connected
        assert not interface.is_initialized
        assert not interface.is_homed
        assert interface.operation_count == 0
        assert interface.movement_history == []

    def test_connect(self, interface: {{ module_name | pascal_case }}FakeInterface) -> None:
        """Test connection."""
        interface.connect()
        assert interface.is_connected
        assert not interface.is_initialized
        assert not interface.is_homed

    def test_disconnect(self, interface: {{ module_name | pascal_case }}FakeInterface) -> None:
        """Test disconnection."""
        interface.connect()
        interface.disconnect()
        assert not interface.is_connected
        assert not interface.is_initialized
        assert not interface.is_homed

    def test_initialize(self, interface: {{ module_name | pascal_case }}FakeInterface) -> None:
        """Test robot arm initialization."""
        interface.connect()
        interface.initialize()
        assert interface.is_initialized
        assert not interface.is_homed

    def test_initialize_requires_connection(
        self, interface: {{ module_name | pascal_case }}FakeInterface
    ) -> None:
        """Test that initialization requires connection."""
        with pytest.raises(RuntimeError, match="Not connected"):
            interface.initialize()

    def test_shutdown(self, interface: {{ module_name | pascal_case }}FakeInterface) -> None:
        """Test robot arm shutdown."""
        interface.connect()
        interface.initialize()
        interface.home()
        interface.shutdown()
        assert not interface.is_initialized
        assert not interface.is_homed
        assert interface.is_connected  # Still connected after shutdown

    def test_shutdown_requires_connection(
        self, interface: {{ module_name | pascal_case }}FakeInterface
    ) -> None:
        """Test that shutdown requires connection."""
        with pytest.raises(RuntimeError, match="Not connected"):
            interface.shutdown()

    def test_home(self, interface: {{ module_name | pascal_case }}FakeInterface) -> None:
        """Test homing the robot arm."""
        interface.connect()
        interface.initialize()
        interface.home()
        assert interface.is_homed
        assert interface.operation_count == 1
        position = interface.get_position()
        assert position == {"x": 0.0, "y": 0.0, "z": 0.0}

    def test_home_requires_connection(
        self, interface: {{ module_name | pascal_case }}FakeInterface
    ) -> None:
        """Test that homing requires connection."""
        with pytest.raises(RuntimeError, match="Not connected"):
            interface.home()

    def test_home_requires_initialization(
        self, interface: {{ module_name | pascal_case }}FakeInterface
    ) -> None:
        """Test that homing requires initialization."""
        interface.connect()
        with pytest.raises(RuntimeError, match="not initialized"):
            interface.home()

    def test_pick(self, interface: {{ module_name | pascal_case }}FakeInterface) -> None:
        """Test picking an item from a location."""
        interface.connect()
        interface.initialize()
        interface.home()
        result = interface.pick("sample_station", grip_force=5)

        assert result["action"] == "pick"
        assert result["location"] == "sample_station"
        assert result["parameters"] == {"grip_force": 5}
        assert result["success"] is True

    def test_pick_requires_connection(
        self, interface: {{ module_name | pascal_case }}FakeInterface
    ) -> None:
        """Test that pick requires connection."""
        with pytest.raises(RuntimeError, match="Not connected"):
            interface.pick("location")

    def test_pick_requires_initialization(
        self, interface: {{ module_name | pascal_case }}FakeInterface
    ) -> None:
        """Test that pick requires initialization."""
        interface.connect()
        with pytest.raises(RuntimeError, match="not initialized"):
            interface.pick("location")

    def test_pick_requires_homing(
        self, interface: {{ module_name | pascal_case }}FakeInterface
    ) -> None:
        """Test that pick requires homing."""
        interface.connect()
        interface.initialize()
        with pytest.raises(RuntimeError, match="not homed"):
            interface.pick("location")

    def test_place(self, interface: {{ module_name | pascal_case }}FakeInterface) -> None:
        """Test placing an item at a location."""
        interface.connect()
        interface.initialize()
        interface.home()
        interface.pick("source")
        result = interface.place("destination", settle_time=1.0)

        assert result["action"] == "place"
        assert result["location"] == "destination"
        assert result["parameters"] == {"settle_time": 1.0}
        assert result["success"] is True

    def test_place_requires_connection(
        self, interface: {{ module_name | pascal_case }}FakeInterface
    ) -> None:
        """Test that place requires connection."""
        with pytest.raises(RuntimeError, match="Not connected"):
            interface.place("location")

    def test_place_requires_initialization(
        self, interface: {{ module_name | pascal_case }}FakeInterface
    ) -> None:
        """Test that place requires initialization."""
        interface.connect()
        with pytest.raises(RuntimeError, match="not initialized"):
            interface.place("location")

    def test_place_requires_homing(
        self, interface: {{ module_name | pascal_case }}FakeInterface
    ) -> None:
        """Test that place requires homing."""
        interface.connect()
        interface.initialize()
        with pytest.raises(RuntimeError, match="not homed"):
            interface.place("location")

    def test_move(self, interface: {{ module_name | pascal_case }}FakeInterface) -> None:
        """Test moving the arm to a position."""
        interface.connect()
        interface.initialize()
        interface.home()
        result = interface.move(100.0, 200.0, 50.0, speed=25.0)

        assert result["action"] == "move"
        assert result["position"] == {"x": 100.0, "y": 200.0, "z": 50.0}
        assert result["speed"] == 25.0
        assert result["success"] is True

        position = interface.get_position()
        assert position == {"x": 100.0, "y": 200.0, "z": 50.0}

    def test_move_requires_connection(
        self, interface: {{ module_name | pascal_case }}FakeInterface
    ) -> None:
        """Test that move requires connection."""
        with pytest.raises(RuntimeError, match="Not connected"):
            interface.move(0.0, 0.0, 0.0)

    def test_move_requires_initialization(
        self, interface: {{ module_name | pascal_case }}FakeInterface
    ) -> None:
        """Test that move requires initialization."""
        interface.connect()
        with pytest.raises(RuntimeError, match="not initialized"):
            interface.move(0.0, 0.0, 0.0)

    def test_move_requires_homing(
        self, interface: {{ module_name | pascal_case }}FakeInterface
    ) -> None:
        """Test that move requires homing."""
        interface.connect()
        interface.initialize()
        with pytest.raises(RuntimeError, match="not homed"):
            interface.move(0.0, 0.0, 0.0)

    def test_get_position(self, interface: {{ module_name | pascal_case }}FakeInterface) -> None:
        """Test getting the current arm position."""
        interface.connect()
        position = interface.get_position()
        assert position == {"x": 0.0, "y": 0.0, "z": 0.0}

    def test_get_position_requires_connection(
        self, interface: {{ module_name | pascal_case }}FakeInterface
    ) -> None:
        """Test that get_position requires connection."""
        with pytest.raises(RuntimeError, match="Not connected"):
            interface.get_position()

    def test_get_status(self, interface: {{ module_name | pascal_case }}FakeInterface) -> None:
        """Test status retrieval."""
        interface.connect()
        interface.initialize()
        interface.home()
        status = interface.get_status()

        assert status["connected"] is True
        assert status["initialized"] is True
        assert status["homed"] is True
        assert status["holding_item"] is False
        assert status["position"] == {"x": 0.0, "y": 0.0, "z": 0.0}

    def test_get_status_requires_connection(
        self, interface: {{ module_name | pascal_case }}FakeInterface
    ) -> None:
        """Test that status retrieval requires connection."""
        with pytest.raises(RuntimeError, match="Not connected"):
            interface.get_status()

    def test_get_status_after_pick(
        self, interface: {{ module_name | pascal_case }}FakeInterface
    ) -> None:
        """Test that status reflects holding item after pick."""
        interface.connect()
        interface.initialize()
        interface.home()
        interface.pick("station_a")
        status = interface.get_status()
        assert status["holding_item"] is True

    def test_get_status_after_place(
        self, interface: {{ module_name | pascal_case }}FakeInterface
    ) -> None:
        """Test that status reflects not holding item after place."""
        interface.connect()
        interface.initialize()
        interface.home()
        interface.pick("station_a")
        interface.place("station_b")
        status = interface.get_status()
        assert status["holding_item"] is False

    def test_operation_count(self, interface: {{ module_name | pascal_case }}FakeInterface) -> None:
        """Test that operation count increments correctly."""
        interface.connect()
        interface.initialize()
        interface.home()
        assert interface.operation_count == 1  # home counts as an operation

        interface.pick("station_a")
        assert interface.operation_count == 2

        interface.place("station_b")
        assert interface.operation_count == 3

        interface.move(10.0, 20.0, 30.0)
        assert interface.operation_count == 4

    def test_movement_history(self, interface: {{ module_name | pascal_case }}FakeInterface) -> None:
        """Test that movement history is tracked correctly."""
        interface.connect()
        interface.initialize()
        interface.home()
        interface.pick("station_a")
        interface.move(100.0, 200.0, 50.0, speed=25.0)

        history = interface.movement_history
        assert len(history) == 3

        assert history[0]["operation"] == "home"
        assert history[0]["position"] == {"x": 0.0, "y": 0.0, "z": 0.0}

        assert history[1]["operation"] == "pick"
        assert history[1]["location"] == "station_a"

        assert history[2]["operation"] == "move"
        assert history[2]["position"] == {"x": 100.0, "y": 200.0, "z": 50.0}
        assert history[2]["speed"] == 25.0

    def test_get_state(self, interface: {{ module_name | pascal_case }}FakeInterface) -> None:
        """Test internal state retrieval."""
        interface.connect()
        interface.initialize()
        interface.home()
        interface.pick("station_a")

        state = interface.get_state()

        assert state["connected"] is True
        assert state["initialized"] is True
        assert state["homed"] is True
        assert state["holding_item"] is True
        assert state["operation_count"] == 2
        assert state["last_operation"] == "pick"
        assert "last_operation_time" in state

    def test_reset_state(self, interface: {{ module_name | pascal_case }}FakeInterface) -> None:
        """Test state reset."""
        interface.connect()
        interface.initialize()
        interface.home()
        interface.pick("station_a")
        interface.reset_state()

        assert interface.operation_count == 0
        assert interface.movement_history == []
        state = interface.get_state()
        assert "last_operation" not in state
