"""Shared test fixtures for pyvisa-ar488."""

import pytest

from pyvisa_ar488.protocols import AR488Transport


class MockAR488Transport(AR488Transport):
    """In-process mock transport for testing pyvisa-ar488 without hardware.

    Simulates a minimal AR488 adapter with configurable instruments.
    """

    def __init__(self):
        self._connected = False
        self._current_address: int | None = None
        self._pending_command: str | None = None
        self._instruments: dict[int, dict] = {
            1: {
                "idn": "Keithley Instruments,2000,1234567,A01",
                "status_byte": 0,
                "responses": {
                    "MEAS:VOLT:DC?": "+1.23456789E+01",
                },
            },
            5: {
                "idn": "Hewlett-Packard,34401A,MY47000001,10-5-2",
                "status_byte": 0,
                "responses": {
                    "MEAS:VOLT:DC?": "+5.43210000E+00",
                },
            },
            22: {
                "idn": "Keithley Instruments,2400,9876543,C32",
                "status_byte": 0,
                "responses": {
                    ":SOUR:FUNC?": "VOLT",
                    ":SOUR:VOLT?": "+5.00000000E+00",
                    ":SOUR:CURR?": "+1.00000000E-01",
                    ":READ?": "+5.00000000E+00,+1.23000000E-01,+0.00000000E+00",
                },
            },
        }

    def connect(self) -> None:
        self._connected = True

    def disconnect(self) -> None:
        self._connected = False

    def is_connected(self) -> bool:
        return self._connected

    def send_command(self, command: str) -> None:
        self._pending_command = command

    def send_raw(self, command: str) -> None:
        pass

    def read_response(self, timeout_ms: int = 10000) -> str:
        inst = self._instruments.get(self._current_address or 0)
        if inst is None:
            raise TimeoutError("No instrument at address")

        cmd = self._pending_command
        self._pending_command = None

        if cmd is None:
            return ""

        # Check custom responses
        if cmd in inst["responses"]:
            return inst["responses"][cmd]

        # Standard SCPI
        upper = cmd.strip().upper()
        if upper == "*IDN?":
            return inst["idn"]
        if upper == "*STB?":
            return str(inst["status_byte"])
        if upper.endswith("?"):
            return "+1.00000000E+00"

        return ""

    def set_address(self, address: int) -> None:
        self._current_address = address

    def serial_poll(self, address: int) -> int:
        inst = self._instruments.get(address)
        return inst["status_byte"] if inst else 0

    def find_listeners(self) -> list[int]:
        return sorted(self._instruments.keys())

    def interface_clear(self) -> None:
        pass


@pytest.fixture
def mock_transport():
    """A mock AR488 transport for testing."""
    return MockAR488Transport()
