import pytest

from matterlab_valves import SwitchingValve


class MockSwitchingValve(SwitchingValve):
    def __init__(self, num_port, ports=None):
        super().__init__(num_port=num_port, ports=ports)
        self._port = 1

    @property
    def port(self):
        return self._port

    @port.setter
    def port(self, port_id):
        self._port = port_id


def test_switching_valve_requires_concrete_subclass():
    with pytest.raises(TypeError):
        SwitchingValve(num_port=2, ports={"A": 1, "B": 2})


def test_switching_valve_stores_num_port_and_ports():
    ports = {"A": 1, "B": 2, "C": 3}
    valve = MockSwitchingValve(num_port=3, ports=ports)

    assert isinstance(valve, SwitchingValve)
    assert valve.num_port == 3
    assert valve.ports == ports


def test_switch_port_accepts_named_port():
    valve = MockSwitchingValve(num_port=2, ports={"A": 1, "B": 2})

    result = valve.switch_port("B")

    assert result == 2
    assert valve.port == 2


def test_switch_port_accepts_numeric_port():
    valve = MockSwitchingValve(num_port=3, ports={"A": 1, "B": 2, "C": 3})

    result = valve.switch_port(3)

    assert result == 3
    assert valve.port == 3


def test_switch_port_raises_for_unknown_port():
    valve = MockSwitchingValve(num_port=2, ports={"A": 1, "B": 2})

    with pytest.raises(ValueError, match="Wrong ports"):
        valve.switch_port("C")


def test_get_port_id_returns_matching_label():
    valve = MockSwitchingValve(num_port=2, ports={"A": 1, "B": 2})

    assert valve._get_port_id(1) == "A"
    assert valve._get_port_id(2) == "B"


def test_get_port_id_raises_for_unknown_port_number():
    valve = MockSwitchingValve(num_port=2, ports={"A": 1, "B": 2})

    with pytest.raises(KeyError, match="Port number 3 not found in ports."):
        valve._get_port_id(3)


def test_port_property_uses_concrete_implementation():
    valve = MockSwitchingValve(num_port=2, ports={"A": 1, "B": 2})

    assert valve.port == 1

    valve.port = 2

    assert valve.port == 2
