"""
Unit tests for Prediction Calculator module.
"""

import pytest
from app.ml.prediction_calculator import (
    calculate_prediction,
    calculate_confidence_meter,
    determine_winner,
    validate_prediction_result
)


class TestConfidenceMeterCalculation:
    """Test Confidence Meter calculation logic."""
    
    def test_confidence_meter_equal_energy(self):
        """Test confidence meter when both teams have equal energy."""
        result = calculate_confidence_meter(home_energy=50.0, away_energy=50.0)
        assert result == 0.0  # No confidence when teams are equal
    
    def test_confidence_meter_small_difference(self):
        """Test confidence meter with small energy difference."""
        result = calculate_confidence_meter(home_energy=52.0, away_energy=50.0)
        assert 0 < result < 100
        assert result == 4.0  # 2 * 2.0 = 4.0%
    
    def test_confidence_meter_medium_difference(self):
        """Test confidence meter with medium energy difference."""
        result = calculate_confidence_meter(home_energy=60.0, away_energy=50.0)
        assert 0 < result < 100
        assert result == 20.0  # 2 * 10.0 = 20.0%
    
    def test_confidence_meter_large_difference(self):
        """Test confidence meter with large energy difference."""
        result = calculate_confidence_meter(home_energy=80.0, away_energy=50.0)
        assert 0 < result <= 100
        assert result == 60.0  # 2 * 30.0 = 60.0%
    
    def test_confidence_meter_very_large_difference(self):
        """Test confidence meter caps at 100% for very large differences."""
        result = calculate_confidence_meter(home_energy=100.0, away_energy=50.0)
        assert result == 100.0  # Capped at 100%
    
    def test_confidence_meter_zero_energy(self):
        """Test confidence meter when one team has zero energy."""
        result = calculate_confidence_meter(home_energy=0.0, away_energy=50.0)
        assert result == 100.0  # Max confidence
    
    def test_confidence_meter_negative_energy(self):
        """Test confidence meter with negative energy values."""
        result = calculate_confidence_meter(home_energy=-10.0, away_energy=50.0)
        assert result == 100.0  # Capped at 100%


class TestWinnerDetermination:
    """Test winner determination logic."""
    
    def test_home_team_wins(self):
        """Test home team wins when home energy is higher."""
        result = determine_winner(home_energy=60.0, away_energy=40.0)
        assert result == "home"
    
    def test_away_team_wins(self):
        """Test away team wins when away energy is higher."""
        result = determine_winner(home_energy=40.0, away_energy=60.0)
        assert result == "away"
    
    def test_draw_equal_energy(self):
        """Test draw when both teams have equal energy."""
        result = determine_winner(home_energy=50.0, away_energy=50.0)
        assert result == "draw"
    
    def test_draw_almost_equal(self):
        """Test draw when energy difference is very small."""
        result = determine_winner(home_energy=50.01, away_energy=50.0)
        assert result == "home"  # Should prefer home on tie


class TestPredictionCalculation:
    """Test complete prediction calculation."""
    
    def test_prediction_home_win(self):
        """Test prediction calculation for home team win."""
        result = calculate_prediction(home_energy=65.0, away_energy=45.0)
        
        assert 'confidence' in result
        assert 'predicted_winner' in result
        assert 'home_energy' in result
        assert 'away_energy' in result
        
        assert result['confidence'] > 0
        assert result['predicted_winner'] == 'home'
        assert result['home_energy'] == 65.0
        assert result['away_energy'] == 45.0
    
    def test_prediction_away_win(self):
        """Test prediction calculation for away team win."""
        result = calculate_prediction(home_energy=35.0, away_energy=70.0)
        
        assert result['confidence'] > 0
        assert result['predicted_winner'] == 'away'
        assert result['home_energy'] == 35.0
        assert result['away_energy'] == 70.0
    
    def test_prediction_draw(self):
        """Test prediction calculation for draw."""
        result = calculate_prediction(home_energy=50.0, away_energy=50.0)
        
        assert result['confidence'] == 0.0
        assert result['predicted_winner'] == 'draw'
    
    def test_prediction_high_confidence(self):
        """Test prediction with high confidence."""
        result = calculate_prediction(home_energy=90.0, away_energy=30.0)
        
        assert result['confidence'] >= 80.0  # High confidence
        assert result['predicted_winner'] == 'home'


class TestPredictionValidation:
    """Test prediction result validation."""
    
    def test_valid_prediction_result(self):
        """Test validation of valid prediction result."""
        result = {
            'confidence': 75.0,
            'predicted_winner': 'home',
            'home_energy': 65.0,
            'away_energy': 45.0
        }
        
        assert validate_prediction_result(result) is True
    
    def test_invalid_confidence_negative(self):
        """Test validation fails with negative confidence."""
        result = {
            'confidence': -10.0,
            'predicted_winner': 'home',
            'home_energy': 65.0,
            'away_energy': 45.0
        }
        
        assert validate_prediction_result(result) is False
    
    def test_invalid_confidence_over_100(self):
        """Test validation fails with confidence over 100%."""
        result = {
            'confidence': 150.0,
            'predicted_winner': 'home',
            'home_energy': 65.0,
            'away_energy': 45.0
        }
        
        assert validate_prediction_result(result) is False
    
    def test_invalid_winner_value(self):
        """Test validation fails with invalid winner value."""
        result = {
            'confidence': 75.0,
            'predicted_winner': 'invalid',
            'home_energy': 65.0,
            'away_energy': 45.0
        }
        
        assert validate_prediction_result(result) is False
    
    def test_invalid_missing_fields(self):
        """Test validation fails when required fields are missing."""
        result = {
            'confidence': 75.0,
            'predicted_winner': 'home'
            # Missing home_energy and away_energy
        }
        
        assert validate_prediction_result(result) is False
    
    def test_invalid_energy_negative(self):
        """Test validation fails with negative energy values."""
        result = {
            'confidence': 75.0,
            'predicted_winner': 'home',
            'home_energy': -10.0,
            'away_energy': 45.0
        }
        
        assert validate_prediction_result(result) is False


class TestPredictionEdgeCases:
    """Test prediction calculation edge cases."""
    
    def test_both_teams_zero_energy(self):
        """Test prediction when both teams have zero energy."""
        result = calculate_prediction(home_energy=0.0, away_energy=0.0)
        
        assert result['confidence'] == 0.0
        assert result['predicted_winner'] == 'draw'
    
    def test_very_high_energy_values(self):
        """Test prediction with very high energy values."""
        result = calculate_prediction(home_energy=1000.0, away_energy=500.0)
        
        assert result['confidence'] == 100.0  # Should be capped
        assert result['predicted_winner'] == 'home'
    
    def test_decimal_energy_values(self):
        """Test prediction with decimal energy values."""
        result = calculate_prediction(home_energy=55.5, away_energy=54.5)
        
        assert 0 < result['confidence'] < 100
        assert result['predicted_winner'] == 'home'
