"""Unit tests for health monitor."""

import pytest
from datetime import datetime, timedelta

from src.data.health_monitor import HealthMonitor, HealthMetrics, HealthStatus


class TestHealthMetrics:
    """Tests for HealthMetrics."""
    
    def test_record_success(self):
        """Test recording successful operation."""
        metrics = HealthMetrics()
        metrics.record_success(0.5)
        
        assert metrics.status == HealthStatus.HEALTHY
        assert metrics.success_count == 1
        assert metrics.consecutive_failures == 0
        assert len(metrics.response_times) == 1
    
    def test_record_failure(self):
        """Test recording failed operation."""
        metrics = HealthMetrics()
        metrics.record_failure()
        
        assert metrics.failure_count == 1
        assert metrics.consecutive_failures == 1
    
    def test_circuit_breaker(self):
        """Test circuit breaker opening."""
        metrics = HealthMetrics()
        
        # Record 5 failures
        for _ in range(5):
            metrics.record_failure()
        
        assert metrics.circuit_breaker_open is True
        assert metrics.consecutive_failures == 5
    
    def test_should_attempt(self):
        """Test should_attempt logic."""
        metrics = HealthMetrics()
        
        # Should attempt if circuit breaker not open
        assert metrics.should_attempt() is True
        
        # Open circuit breaker
        for _ in range(5):
            metrics.record_failure()
        
        # Should not attempt immediately
        assert metrics.should_attempt(circuit_breaker_timeout=60) is False
    
    def test_get_avg_response_time(self):
        """Test average response time calculation."""
        metrics = HealthMetrics()
        metrics.response_times.extend([0.1, 0.2, 0.3])
        
        avg = metrics.get_avg_response_time()
        assert avg == 0.2


class TestHealthMonitor:
    """Tests for HealthMonitor."""
    
    @pytest.fixture
    def monitor(self):
        """Create a health monitor instance."""
        return HealthMonitor()
    
    def test_record_success(self, monitor):
        """Test recording success."""
        monitor.record_success("provider1", 0.5)
        
        metrics = monitor.get_metrics("provider1")
        assert metrics is not None
        assert metrics.status == HealthStatus.HEALTHY
        assert metrics.success_count == 1
    
    def test_record_failure(self, monitor):
        """Test recording failure."""
        monitor.record_failure("provider1")
        
        metrics = monitor.get_metrics("provider1")
        assert metrics is not None
        assert metrics.failure_count == 1
        assert metrics.consecutive_failures == 1
    
    def test_is_healthy(self, monitor):
        """Test health checking."""
        # No metrics yet - assume healthy
        assert monitor.is_healthy("provider1") is True
        
        # Record success
        monitor.record_success("provider1", 0.5)
        assert monitor.is_healthy("provider1") is True
        
        # Record many failures
        for _ in range(10):
            monitor.record_failure("provider1")
        
        assert monitor.is_healthy("provider1") is False
    
    def test_get_health_status(self, monitor):
        """Test getting health status."""
        monitor.record_success("provider1", 0.5)
        status = monitor.get_health_status("provider1")
        assert status == HealthStatus.HEALTHY
    
    def test_select_healthiest(self, monitor):
        """Test selecting healthiest provider."""
        # Make provider1 healthy
        monitor.record_success("provider1", 0.1)
        monitor.record_success("provider1", 0.2)
        
        # Make provider2 unhealthy
        monitor.record_failure("provider2")
        monitor.record_failure("provider2")
        monitor.record_failure("provider2")
        
        healthiest = monitor.select_healthiest(["provider1", "provider2"])
        assert healthiest == "provider1"
    
    def test_reset_circuit_breaker(self, monitor):
        """Test resetting circuit breaker."""
        # Open circuit breaker
        for _ in range(5):
            monitor.record_failure("provider1")
        
        assert monitor.get_metrics("provider1").circuit_breaker_open is True
        
        monitor.reset_circuit_breaker("provider1")
        
        metrics = monitor.get_metrics("provider1")
        assert metrics.circuit_breaker_open is False
        assert metrics.consecutive_failures == 0
    
    def test_reset_metrics(self, monitor):
        """Test resetting metrics."""
        monitor.record_success("provider1", 0.5)
        assert monitor.get_metrics("provider1") is not None
        
        monitor.reset_metrics("provider1")
        assert monitor.get_metrics("provider1") is None
