"""Unit tests for PoolMetrics schema (Story 2.6)."""

import pytest
from pydantic import ValidationError

from rabbitmq_mcp_connection.schemas.pool import PoolMetrics


class TestPoolMetrics:
    """Test PoolMetrics Pydantic model validation and field constraints."""

    def test_pool_metrics_valid(self):
        """Test creating PoolMetrics with valid values."""
        metrics = PoolMetrics(
            active_connections=3,
            pool_size=5,
            wait_time=12.5,
            total_requests=100,
            successful_requests=95,
            failed_requests=5,
            evictions_last_hour=2,
            pool_exhaustion_count=1,
            health_score=0.95,
        )

        assert metrics.active_connections == 3
        assert metrics.pool_size == 5
        assert metrics.wait_time == 12.5
        assert metrics.total_requests == 100
        assert metrics.successful_requests == 95
        assert metrics.failed_requests == 5
        assert metrics.evictions_last_hour == 2
        assert metrics.pool_exhaustion_count == 1
        assert metrics.health_score == 0.95

    def test_pool_metrics_defaults(self):
        """Test PoolMetrics default values."""
        metrics = PoolMetrics(
            active_connections=2,
            pool_size=5,
        )

        assert metrics.active_connections == 2
        assert metrics.pool_size == 5
        assert metrics.wait_time is None
        assert metrics.total_requests == 0
        assert metrics.successful_requests == 0
        assert metrics.failed_requests == 0
        assert metrics.evictions_last_hour == 0
        assert metrics.pool_exhaustion_count == 0
        assert metrics.health_score == 1.0

    @pytest.mark.parametrize(
        "health_score",
        [0.0, 0.5, 0.75, 0.90, 1.0],
    )
    def test_health_score_valid_range(self, health_score: float):
        """Test health score accepts valid range 0.0-1.0."""
        metrics = PoolMetrics(
            active_connections=1,
            pool_size=5,
            health_score=health_score,
        )
        assert metrics.health_score == health_score

    @pytest.mark.parametrize(
        "invalid_score",
        [-0.1, -1.0, 1.1, 2.0, 10.0],
    )
    def test_health_score_invalid_range(self, invalid_score: float):
        """Test health score rejects values outside 0.0-1.0."""
        with pytest.raises(ValidationError) as exc_info:
            PoolMetrics(
                active_connections=1,
                pool_size=5,
                health_score=invalid_score,
            )
        assert "Health score must be between 0.0 and 1.0" in str(exc_info.value)

    @pytest.mark.parametrize(
        "field,value",
        [
            ("active_connections", -1),
            ("pool_size", -5),
            ("total_requests", -10),
            ("successful_requests", -20),
            ("failed_requests", -3),
            ("evictions_last_hour", -2),
            ("pool_exhaustion_count", -1),
        ],
    )
    def test_negative_values_rejected(self, field: str, value: int):
        """Test integer metrics reject negative values."""
        kwargs = {
            "active_connections": 1,
            "pool_size": 5,
            field: value,
        }
        with pytest.raises(ValidationError) as exc_info:
            PoolMetrics(**kwargs)
        assert "Value must be non-negative" in str(exc_info.value)

    def test_pool_metrics_serialization(self):
        """Test PoolMetrics can be serialized to JSON."""
        metrics = PoolMetrics(
            active_connections=3,
            pool_size=5,
            total_requests=50,
            successful_requests=48,
            failed_requests=2,
            health_score=0.96,
        )

        json_data = metrics.model_dump_json()
        assert '"active_connections":3' in json_data
        assert '"pool_size":5' in json_data
        assert '"health_score":0.96' in json_data

    def test_pool_metrics_from_dict(self):
        """Test creating PoolMetrics from dictionary."""
        data = {
            "active_connections": 4,
            "pool_size": 10,
            "total_requests": 200,
            "successful_requests": 190,
            "failed_requests": 10,
            "health_score": 0.95,
        }

        metrics = PoolMetrics(**data)
        assert metrics.active_connections == 4
        assert metrics.pool_size == 10
        assert metrics.health_score == 0.95

    def test_pool_metrics_wait_time_optional(self):
        """Test wait_time field is optional."""
        metrics_without_wait = PoolMetrics(
            active_connections=2,
            pool_size=5,
        )
        assert metrics_without_wait.wait_time is None

        metrics_with_wait = PoolMetrics(
            active_connections=2,
            pool_size=5,
            wait_time=25.5,
        )
        assert metrics_with_wait.wait_time == 25.5
