"""Tests for {{ interface_name }} Modbus interface.

Generated by: madsci new comm --template comm/modbus
Template version: {{ template_version }}
"""

import pytest

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


class Test{{ interface_name | pascal_case }}FakeInterface:
    """Test cases for the fake Modbus interface."""

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

    def test_initial_state(self, interface: {{ interface_name | pascal_case }}FakeInterface) -> None:
        """Test that the interface starts disconnected."""
        assert not interface.is_connected
        assert interface.operation_count == 0

    def test_connect_disconnect(self, interface: {{ interface_name | pascal_case }}FakeInterface) -> None:
        """Test connecting and disconnecting."""
        interface.connect()
        assert interface.is_connected
        interface.disconnect()
        assert not interface.is_connected

    def test_invalid_protocol(self) -> None:
        """Test that an invalid protocol raises ValueError."""
        with pytest.raises(ValueError, match="Unsupported protocol"):
            {{ interface_name | pascal_case }}FakeInterface(protocol="ascii")

    def test_read_holding_registers(self, interface: {{ interface_name | pascal_case }}FakeInterface) -> None:
        """Test reading holding registers."""
        interface.connect()
        values = interface.read_holding_registers(address=0, count=3)
        assert values == [0, 0, 0]
        assert interface.operation_count == 1

    def test_read_holding_registers_requires_connection(
        self, interface: {{ interface_name | pascal_case }}FakeInterface
    ) -> None:
        """Test that reading registers requires connection."""
        with pytest.raises(RuntimeError, match="Not connected"):
            interface.read_holding_registers(address=0, count=1)

    def test_write_register(self, interface: {{ interface_name | pascal_case }}FakeInterface) -> None:
        """Test writing and reading back a single register."""
        interface.connect()
        interface.write_register(address=5, value=1234)
        values = interface.read_holding_registers(address=5, count=1)
        assert values == [1234]

    def test_write_register_requires_connection(
        self, interface: {{ interface_name | pascal_case }}FakeInterface
    ) -> None:
        """Test that writing a register requires connection."""
        with pytest.raises(RuntimeError, match="Not connected"):
            interface.write_register(address=0, value=1)

    def test_write_registers(self, interface: {{ interface_name | pascal_case }}FakeInterface) -> None:
        """Test writing and reading back multiple registers."""
        interface.connect()
        interface.write_registers(address=10, values=[100, 200, 300])
        values = interface.read_holding_registers(address=10, count=3)
        assert values == [100, 200, 300]

    def test_write_registers_requires_connection(
        self, interface: {{ interface_name | pascal_case }}FakeInterface
    ) -> None:
        """Test that writing multiple registers requires connection."""
        with pytest.raises(RuntimeError, match="Not connected"):
            interface.write_registers(address=0, values=[1, 2])

    def test_read_input_registers(self, interface: {{ interface_name | pascal_case }}FakeInterface) -> None:
        """Test reading input registers."""
        interface.set_input_register(address=0, value=999)
        interface.connect()
        values = interface.read_input_registers(address=0, count=1)
        assert values == [999]

    def test_read_input_registers_requires_connection(
        self, interface: {{ interface_name | pascal_case }}FakeInterface
    ) -> None:
        """Test that reading input registers requires connection."""
        with pytest.raises(RuntimeError, match="Not connected"):
            interface.read_input_registers(address=0, count=1)

    def test_read_coils(self, interface: {{ interface_name | pascal_case }}FakeInterface) -> None:
        """Test reading coils."""
        interface.connect()
        coils = interface.read_coils(address=0, count=4)
        assert coils == [False, False, False, False]

    def test_read_coils_requires_connection(
        self, interface: {{ interface_name | pascal_case }}FakeInterface
    ) -> None:
        """Test that reading coils requires connection."""
        with pytest.raises(RuntimeError, match="Not connected"):
            interface.read_coils(address=0, count=1)

    def test_write_coil(self, interface: {{ interface_name | pascal_case }}FakeInterface) -> None:
        """Test writing and reading back a single coil."""
        interface.connect()
        interface.write_coil(address=3, value=True)
        coils = interface.read_coils(address=3, count=1)
        assert coils == [True]

    def test_write_coil_requires_connection(
        self, interface: {{ interface_name | pascal_case }}FakeInterface
    ) -> None:
        """Test that writing a coil requires connection."""
        with pytest.raises(RuntimeError, match="Not connected"):
            interface.write_coil(address=0, value=True)

    def test_coils_mixed_state(self, interface: {{ interface_name | pascal_case }}FakeInterface) -> None:
        """Test reading coils with mixed on/off state."""
        interface.connect()
        interface.write_coil(address=0, value=True)
        interface.write_coil(address=1, value=False)
        interface.write_coil(address=2, value=True)
        coils = interface.read_coils(address=0, count=3)
        assert coils == [True, False, True]

    def test_reset(self, interface: {{ interface_name | pascal_case }}FakeInterface) -> None:
        """Test that reset clears all registers, coils, and counters."""
        interface.connect()
        interface.write_register(address=0, value=42)
        interface.write_coil(address=0, value=True)
        interface.reset()
        assert interface.operation_count == 0
        # Registers and coils should be zeroed
        values = interface.read_holding_registers(address=0, count=1)
        assert values == [0]
        coils = interface.read_coils(address=0, count=1)
        assert coils == [False]

    def test_operation_count_tracks_all_ops(
        self, interface: {{ interface_name | pascal_case }}FakeInterface
    ) -> None:
        """Test that operation count tracks all register and coil operations."""
        interface.connect()
        interface.read_holding_registers(address=0, count=1)
        interface.write_register(address=0, value=1)
        interface.read_coils(address=0, count=1)
        interface.write_coil(address=0, value=True)
        interface.read_input_registers(address=0, count=1)
        interface.write_registers(address=0, values=[1, 2])
        assert interface.operation_count == 6
