"""
Integration test for new stimulation control methods in AllegoClient.

This test verifies that:
1. All new client methods exist and have correct signatures
2. Request/response models work correctly
3. Enum conversions work as expected
"""

from __future__ import annotations

import pytest
from pydantic import ValidationError

from radiens_core.allego_client import AllegoClient
from radiens_core.models.ports import Port
from radiens_core.models.stim import StimKeypressIndex, StimStep, StimStepRequest, StimStepState
from radiens_core.models.triggers import (
    ManualStimTriggerRequest,
    ManualStimTriggerToggleRequest,
    SetTriggerStateRequest,
    TriggerChannel,
    TriggerState,
)


def test_stimulation_control_methods_exist() -> None:
    """Test that all new stimulation control methods exist on AllegoClient."""
    from unittest.mock import patch

    with patch.object(
        AllegoClient,
        "_discover",
        return_value={
            "ALLEGO_CORE": "localhost:50051",
            "ALLEGO_LIFECYCLE": "localhost:50051",
            "ALLEGO_PCACHE": "localhost:50052",
        },
    ):
        client = AllegoClient()

    # Verify method existence
    assert hasattr(client, "set_trigger_state")
    assert hasattr(client, "get_trigger_state")
    assert hasattr(client, "manual_stim_trigger")
    assert hasattr(client, "manual_stim_trigger_toggle")
    assert hasattr(client, "set_stim_step")
    assert hasattr(client, "get_stim_step")


def test_trigger_state_models() -> None:
    """Test that trigger state models work correctly."""
    # Test SetTriggerStateRequest
    request = SetTriggerStateRequest(channel=TriggerChannel.T_DIN_0, enabled=True, port=Port.A)
    assert request.channel == TriggerChannel.T_DIN_0
    assert request.enabled is True
    assert request.port == Port.A

    # Test TriggerState response
    state = TriggerState(enabled_channels=[TriggerChannel.T_DIN_0, TriggerChannel.T_DIN_1], ports=[Port.A, Port.B])
    assert len(state.enabled_channels) == 2
    assert len(state.ports) == 2


def test_manual_stim_trigger_models() -> None:
    """Test manual stim trigger models."""
    # Test ManualStimTriggerRequest
    request = ManualStimTriggerRequest(trigger=StimKeypressIndex.KEYPRESS_1, trigger_on=True)
    assert request.trigger == StimKeypressIndex.KEYPRESS_1
    assert request.trigger_on is True

    # Test ManualStimTriggerToggleRequest
    toggle_request = ManualStimTriggerToggleRequest(trigger=StimKeypressIndex.KEYPRESS_1)
    assert toggle_request.trigger == StimKeypressIndex.KEYPRESS_1


def test_stim_step_models() -> None:
    """Test stimulation step models."""
    # Test StimStepRequest
    request = StimStepRequest(stim_step=StimStep.STIM_STEP_SIZE_100_NA)
    assert request.stim_step == StimStep.STIM_STEP_SIZE_100_NA

    # Test StimStepState
    state = StimStepState(stim_step=StimStep.STIM_STEP_SIZE_1_UA)
    assert state.stim_step == StimStep.STIM_STEP_SIZE_1_UA


def test_trigger_channel_enum_coverage() -> None:
    """Test that TriggerChannel enum has expected values."""
    # Test DIN channels
    assert hasattr(TriggerChannel, "T_DIN_0")
    assert hasattr(TriggerChannel, "T_DIN_15")

    # Test DOUT channels
    assert hasattr(TriggerChannel, "T_DOUT_0")
    assert hasattr(TriggerChannel, "T_DOUT_15")

    # Test special values
    assert hasattr(TriggerChannel, "T_NONE")

    # Ensure we have the right number of values (32 DIN/DOUT + 1 NONE)
    trigger_channels = list(TriggerChannel)
    assert len(trigger_channels) == 33


def test_stim_step_enum_coverage() -> None:
    """Test that StimStep enum has expected values."""
    # Test key step sizes
    assert hasattr(StimStep, "STIM_STEP_SIZE_MIN")
    assert hasattr(StimStep, "STIM_STEP_SIZE_10_NA")
    assert hasattr(StimStep, "STIM_STEP_SIZE_20_NA")
    assert hasattr(StimStep, "STIM_STEP_SIZE_50_NA")
    assert hasattr(StimStep, "STIM_STEP_SIZE_100_NA")
    assert hasattr(StimStep, "STIM_STEP_SIZE_200_NA")
    assert hasattr(StimStep, "STIM_STEP_SIZE_500_NA")
    assert hasattr(StimStep, "STIM_STEP_SIZE_1_UA")
    assert hasattr(StimStep, "STIM_STEP_SIZE_2_UA")
    assert hasattr(StimStep, "STIM_STEP_SIZE_5_UA")
    assert hasattr(StimStep, "STIM_STEP_SIZE_10_UA")
    assert hasattr(StimStep, "STIM_STEP_SIZE_MAX")

    # Ensure we have all expected step sizes
    step_sizes = list(StimStep)
    assert len(step_sizes) == 12


def test_model_immutability() -> None:
    """Test that all stimulation control models are immutable (frozen)."""
    # Test that models cannot be modified after creation
    request = SetTriggerStateRequest(channel=TriggerChannel.T_DIN_0, enabled=True, port=Port.A)

    with pytest.raises(ValidationError):
        request.channel = TriggerChannel.T_DIN_1  # type: ignore[misc]  # Should fail - model is frozen

    state = StimStepState(stim_step=StimStep.STIM_STEP_SIZE_1_UA)
    with pytest.raises(ValidationError):
        state.stim_step = StimStep.STIM_STEP_SIZE_10_UA  # type: ignore[misc]  # Should fail - model is frozen


if __name__ == "__main__":
    # Run tests directly
    pytest.main([__file__, "-v"])
