"""
Tests for data models.
"""

import pytest

from airctl.models.device import BLEDeviceInfo, ConnectedDevice
from airctl.models.events import (
    EventType,
    DeviceFoundEvent,
    DeviceConnectedEvent,
    NotificationEvent,
)
from airctl.models.gatt import CharacteristicInfo, CharacteristicProperty, ServiceInfo
from airctl.models.protocol import JSONRPCRequest, JSONRPCResponse, JSONRPCError


class TestBLEDeviceInfo:
    """Tests for BLEDeviceInfo model."""

    def test_creation(self):
        """Test device info creation."""
        device = BLEDeviceInfo(
            address="AA:BB:CC:DD:EE:FF",
            name="Test Device",
            rssi=-45,
            service_uuids=["180D"],
        )

        assert device.address == "AA:BB:CC:DD:EE:FF"
        assert device.name == "Test Device"
        assert device.rssi == -45
        assert device.service_uuids == ["180D"]

    def test_optional_fields(self):
        """Test optional fields."""
        device = BLEDeviceInfo(address="AA:BB:CC:DD:EE:FF", rssi=-50)

        assert device.name is None
        assert device.service_uuids == []


class TestConnectedDevice:
    """Tests for ConnectedDevice model."""

    def test_creation(self):
        """Test connected device creation."""
        device = ConnectedDevice(
            address="AA:BB:CC:DD:EE:FF",
            name="Test Device",
            alias="my-device",
            mtu_size=64,
            connected_at=1234567890.0,
        )

        assert device.address == "AA:BB:CC:DD:EE:FF"
        assert device.alias == "my-device"
        assert device.mtu_size == 64


class TestEvents:
    """Tests for event models."""

    def test_device_found_event(self):
        """Test device found event."""
        event = DeviceFoundEvent(
            timestamp=1234567890.0,
            device_address="AA:BB:CC:DD:EE:FF",
            device_name="Test",
            rssi=-45,
        )

        assert event.type == EventType.DEVICE_FOUND
        assert event.device_address == "AA:BB:CC:DD:EE:FF"

    def test_notification_event(self):
        """Test notification event."""
        event = NotificationEvent(
            timestamp=1234567890.0,
            device_address="AA:BB:CC:DD:EE:FF",
            characteristic_uuid="180D",
            data="AQID",
        )

        assert event.type == EventType.NOTIFICATION
        assert event.characteristic_uuid == "180D"


class TestGATTModels:
    """Tests for GATT models."""

    def test_service_info(self):
        """Test service info model."""
        service = ServiceInfo(
            uuid="180D",
            handle=1,
            description="Heart Rate",
        )

        assert service.uuid == "180D"
        assert service.handle == 1

    def test_characteristic_info(self):
        """Test characteristic info model."""
        char = CharacteristicInfo(
            uuid="2A37",
            handle=2,
            service_uuid="180D",
            properties=[CharacteristicProperty.READ, CharacteristicProperty.NOTIFY],
        )

        assert char.uuid == "2A37"
        assert CharacteristicProperty.READ in char.properties
        assert CharacteristicProperty.NOTIFY in char.properties


class TestProtocolModels:
    """Tests for JSON-RPC protocol models."""

    def test_request_creation(self):
        """Test request creation."""
        request = JSONRPCRequest(
            id=1,
            method="ble.scan",
            params={"timeout": 10.0},
        )

        assert request.jsonrpc == "2.0"
        assert request.method == "ble.scan"

    def test_response_success(self):
        """Test success response."""
        response = JSONRPCResponse(
            id=1,
            result={"devices": []},
        )

        assert response.is_success()
        assert response.error is None

    def test_response_error(self):
        """Test error response."""
        response = JSONRPCResponse(
            id=1,
            error=JSONRPCError(code=-32000, message="Test error"),
        )

        assert not response.is_success()
        assert response.error.code == -32000
