"""Unit tests for protocol definitions."""

from typing import Any, Optional

import pytest

from augint_library.protocols import (
    AdvancedProcessor,
    CacheProvider,
    ConfigurableClient,
    DataProcessor,
    EventHandler,
    ProcessingResult,
)


@pytest.mark.unit
def test_processing_result_protocol_structure() -> None:
    """Test that ProcessingResult protocol has expected attributes."""
    # Test protocol has expected methods/properties
    assert hasattr(ProcessingResult, "success")
    assert hasattr(ProcessingResult, "data")
    assert hasattr(ProcessingResult, "error")
    assert hasattr(ProcessingResult, "metadata")


@pytest.mark.unit
def test_data_processor_protocol_structure() -> None:
    """Test that DataProcessor protocol has expected methods."""
    assert hasattr(DataProcessor, "process")
    assert hasattr(DataProcessor, "batch_process")


@pytest.mark.unit
def test_configurable_client_protocol_structure() -> None:
    """Test that ConfigurableClient protocol has expected methods."""
    assert hasattr(ConfigurableClient, "get")
    assert hasattr(ConfigurableClient, "post")


@pytest.mark.unit
def test_event_handler_protocol_structure() -> None:
    """Test that EventHandler protocol has expected methods."""
    assert hasattr(EventHandler, "handle_event")
    assert hasattr(EventHandler, "can_handle")


@pytest.mark.unit
def test_cache_provider_protocol_structure() -> None:
    """Test that CacheProvider protocol has expected methods."""
    assert hasattr(CacheProvider, "get")
    assert hasattr(CacheProvider, "set")
    assert hasattr(CacheProvider, "delete")
    assert hasattr(CacheProvider, "clear")


@pytest.mark.unit
def test_advanced_processor_protocol_structure() -> None:
    """Test that AdvancedProcessor protocol has expected methods."""
    # Should have DataProcessor methods
    assert hasattr(AdvancedProcessor, "process")
    assert hasattr(AdvancedProcessor, "batch_process")
    # Should have EventHandler methods
    assert hasattr(AdvancedProcessor, "handle_event")
    assert hasattr(AdvancedProcessor, "can_handle")
    # Should have its own method
    assert hasattr(AdvancedProcessor, "process_with_events")


# Test simple protocol implementations to verify runtime checking works


class MockProcessingResult:
    """Mock implementation of ProcessingResult for testing."""

    def __init__(self, success: bool = True, data: Any = None, error: Optional[str] = None):
        self._success = success
        self._data = data
        self._error = error
        self._metadata: dict[str, Any] = {}

    @property
    def success(self) -> bool:
        return self._success

    @property
    def data(self) -> Any:
        return self._data

    @property
    def error(self) -> Optional[str]:
        return self._error

    @property
    def metadata(self) -> dict[str, Any]:
        return self._metadata


class MockDataProcessor:
    """Mock implementation of DataProcessor for testing."""

    def process(
        self, data: Any, *, timeout: int = 30, retries: int = 3, validate: bool = True
    ) -> Any:
        return MockProcessingResult(success=True, data=f"processed_{data}")

    def batch_process(
        self, data_list: list[Any], *, parallel: bool = True, chunk_size: int = 100
    ) -> list[Any]:
        return [self.process(item) for item in data_list]


class MockEventHandler:
    """Mock implementation of EventHandler for testing."""

    def handle_event(
        self, event_type: str, event_data: dict[str, Any], *, priority: str = "normal"
    ) -> bool:
        return True

    def can_handle(self, event_type: str) -> bool:
        return event_type.startswith("test_")


@pytest.mark.unit
def test_processing_result_isinstance_check() -> None:
    """Test that mock implementation satisfies ProcessingResult protocol."""
    result = MockProcessingResult(success=True, data="test")
    assert isinstance(result, ProcessingResult)


@pytest.mark.unit
def test_data_processor_isinstance_check() -> None:
    """Test that mock implementation satisfies DataProcessor protocol."""
    processor = MockDataProcessor()
    assert isinstance(processor, DataProcessor)


@pytest.mark.unit
def test_event_handler_isinstance_check() -> None:
    """Test that mock implementation satisfies EventHandler protocol."""
    handler = MockEventHandler()
    assert isinstance(handler, EventHandler)


@pytest.mark.unit
def test_mock_processor_functionality() -> None:
    """Test that mock processor actually works."""
    processor = MockDataProcessor()
    result = processor.process("test_data")

    assert isinstance(result, ProcessingResult)
    assert result.success is True
    assert result.data == "processed_test_data"

    # Test batch processing
    batch_result = processor.batch_process(["item1", "item2"])
    assert len(batch_result) == 2
    assert all(isinstance(r, ProcessingResult) for r in batch_result)


@pytest.mark.unit
def test_mock_handler_functionality() -> None:
    """Test that mock event handler actually works."""
    handler = MockEventHandler()

    assert handler.can_handle("test_event") is True
    assert handler.can_handle("other_event") is False

    success = handler.handle_event("test_event", {"key": "value"})
    assert success is True


@pytest.mark.unit
def test_protocol_runtime_checkable() -> None:
    """Test that protocols are marked as runtime_checkable."""

    # These protocols should be runtime checkable
    protocols = [
        ProcessingResult,
        DataProcessor,
        ConfigurableClient,
        EventHandler,
        CacheProvider,
        AdvancedProcessor,
    ]

    for protocol in protocols:
        # Runtime checkable protocols have the _is_runtime_protocol attribute
        assert hasattr(protocol, "_is_runtime_protocol")
        assert protocol._is_runtime_protocol is True


@pytest.mark.unit
def test_protocol_imports_from_main_module() -> None:
    """Test that protocols can be imported from main augint_library module."""
    import augint_library

    # All protocols should be available from main module
    assert hasattr(augint_library, "DataProcessor")
    assert hasattr(augint_library, "ProcessingResult")
    assert hasattr(augint_library, "ConfigurableClient")
    assert hasattr(augint_library, "EventHandler")
    assert hasattr(augint_library, "CacheProvider")
    assert hasattr(augint_library, "AdvancedProcessor")
