"""Tests for the AR488VisaLibrary pyvisa backend."""

from pyvisa.constants import StatusCode

from pyvisa_ar488.highlevel import AR488VisaLibrary


class TestBackendRegistration:
    """Verify the backend can be discovered and instantiated by pyvisa."""

    def test_wrapper_class_exposed(self):
        from pyvisa_ar488 import WRAPPER_CLASS

        assert WRAPPER_CLASS is AR488VisaLibrary

    def test_library_paths(self):
        paths = AR488VisaLibrary.get_library_paths()
        assert "ar488" in paths

    def test_debug_info(self):
        info = AR488VisaLibrary.get_debug_info()
        assert "Version" in info
        assert "AR488" in info["Backend"]


class TestResourceManager:
    """Test the resource manager session lifecycle."""

    def test_open_close_rm(self, mock_transport):
        lib = AR488VisaLibrary()
        lib._transport = mock_transport
        mock_transport.connect()

        session, status = lib.open_default_resource_manager()
        assert status == StatusCode.success
        assert session > 0

        close_status = lib.close(session)
        assert close_status == StatusCode.success

    def test_list_resources(self, mock_transport):
        lib = AR488VisaLibrary()
        lib._transport = mock_transport
        mock_transport.connect()

        session, _ = lib.open_default_resource_manager()
        resources = lib.list_resources(session)

        assert len(resources) == 3
        assert "GPIB0::1::INSTR" in resources
        assert "GPIB0::5::INSTR" in resources
        assert "GPIB0::22::INSTR" in resources


class TestInstrumentSession:
    """Test opening, reading, and writing to instrument sessions."""

    def test_open_instrument(self, mock_transport):
        lib = AR488VisaLibrary()
        lib._transport = mock_transport
        mock_transport.connect()

        rm_session, _ = lib.open_default_resource_manager()
        instr_session, status = lib.open(rm_session, "GPIB0::5::INSTR")

        assert status == StatusCode.success
        assert instr_session > 0
        assert instr_session != rm_session

    def test_write_and_read(self, mock_transport):
        lib = AR488VisaLibrary()
        lib._transport = mock_transport
        mock_transport.connect()

        rm_session, _ = lib.open_default_resource_manager()
        instr_session, _ = lib.open(rm_session, "GPIB0::5::INSTR")

        # Write a query
        count, status = lib.write(instr_session, b"*IDN?\n")
        assert status == StatusCode.success
        assert count > 0

        # Read the response
        data, status = lib.read(instr_session, 1024)
        assert status == StatusCode.success
        assert b"Hewlett-Packard" in data
        assert b"34401A" in data

    def test_read_measurement(self, mock_transport):
        lib = AR488VisaLibrary()
        lib._transport = mock_transport
        mock_transport.connect()

        rm_session, _ = lib.open_default_resource_manager()
        instr_session, _ = lib.open(rm_session, "GPIB0::5::INSTR")

        lib.write(instr_session, b"MEAS:VOLT:DC?\n")
        data, _ = lib.read(instr_session, 1024)
        assert b"5.43210" in data

    def test_close_instrument(self, mock_transport):
        lib = AR488VisaLibrary()
        lib._transport = mock_transport
        mock_transport.connect()

        rm_session, _ = lib.open_default_resource_manager()
        instr_session, _ = lib.open(rm_session, "GPIB0::1::INSTR")

        status = lib.close(instr_session)
        assert status == StatusCode.success

        # After close, read should fail
        _, status = lib.read(instr_session, 1024)
        assert status == StatusCode.error_invalid_object

    def test_read_stb(self, mock_transport):
        lib = AR488VisaLibrary()
        lib._transport = mock_transport
        mock_transport.connect()

        rm_session, _ = lib.open_default_resource_manager()
        instr_session, _ = lib.open(rm_session, "GPIB0::1::INSTR")

        stb, status = lib.read_stb(instr_session)
        assert status == StatusCode.success
        assert isinstance(stb, int)

    def test_gpib_send_ifc(self, mock_transport):
        lib = AR488VisaLibrary()
        lib._transport = mock_transport
        mock_transport.connect()

        rm_session, _ = lib.open_default_resource_manager()
        status = lib.gpib_send_ifc(rm_session)
        assert status == StatusCode.success

    def test_multiple_instruments(self, mock_transport):
        lib = AR488VisaLibrary()
        lib._transport = mock_transport
        mock_transport.connect()

        rm_session, _ = lib.open_default_resource_manager()

        sess1, _ = lib.open(rm_session, "GPIB0::1::INSTR")
        sess5, _ = lib.open(rm_session, "GPIB0::5::INSTR")

        # Query different instruments
        lib.write(sess1, b"*IDN?\n")
        data1, _ = lib.read(sess1, 1024)
        assert b"Keithley" in data1

        lib.write(sess5, b"*IDN?\n")
        data5, _ = lib.read(sess5, 1024)
        assert b"Hewlett-Packard" in data5

        lib.close(sess1)
        lib.close(sess5)
