"""
Unit tests for Prediction Pydantic schemas.
"""

import pytest
from datetime import datetime, timezone
from pydantic import ValidationError

from app.schemas.prediction import (
    PredictionBase,
    PredictionCreate,
    PredictionUpdate,
    PredictionResponse,
    PredictionListResponse,
    PredictionStatsResponse
)


class TestPredictionBase:
    """Test PredictionBase schema."""
    
    def test_prediction_base_valid(self):
        """Test creating a valid PredictionBase."""
        prediction_data = {
            "match_id": 1,
            "energy_score": "high",
            "confidence": "85%",
            "predicted_winner": "PSG",
            "created_at": datetime.now(timezone.utc)
        }
        
        prediction = PredictionBase(**prediction_data)
        
        assert prediction.match_id == 1
        assert prediction.energy_score == "high"
        assert prediction.confidence == "85%"
        assert prediction.predicted_winner == "PSG"
    
    def test_prediction_base_energy_score_too_long(self):
        """Test that energy_score exceeds max length."""
        with pytest.raises(ValidationError) as exc_info:
            PredictionBase(
                match_id=1,
                energy_score="A" * 51,  # Too long
                confidence="85%",
                predicted_winner="PSG",
                created_at=datetime.now(timezone.utc)
            )
        
        assert "at most 50 characters" in str(exc_info.value).lower()
    
    def test_prediction_base_confidence_too_long(self):
        """Test that confidence exceeds max length."""
        with pytest.raises(ValidationError) as exc_info:
            PredictionBase(
                match_id=1,
                energy_score="high",
                confidence="A" * 51,  # Too long
                predicted_winner="PSG",
                created_at=datetime.now(timezone.utc)
            )
        
        assert "at most 50 characters" in str(exc_info.value).lower()
    
    def test_prediction_base_predicted_winner_too_long(self):
        """Test that predicted_winner exceeds max length."""
        with pytest.raises(ValidationError) as exc_info:
            PredictionBase(
                match_id=1,
                energy_score="high",
                confidence="85%",
                predicted_winner="A" * 256,  # Too long
                created_at=datetime.now(timezone.utc)
            )
        
        assert "at most 255 characters" in str(exc_info.value).lower()


class TestPredictionCreate:
    """Test PredictionCreate schema."""
    
    def test_prediction_create_valid(self):
        """Test creating a valid PredictionCreate."""
        prediction_data = {
            "match_id": 1,
            "energy_score": "medium",
            "confidence": "70%",
            "predicted_winner": "Barcelona",
            "created_at": datetime.now(timezone.utc)
        }
        
        prediction = PredictionCreate(**prediction_data)
        
        assert prediction.match_id == 1
        assert prediction.energy_score == "medium"
        assert prediction.confidence == "70%"
        assert prediction.predicted_winner == "Barcelona"


class TestPredictionUpdate:
    """Test PredictionUpdate schema."""
    
    def test_prediction_update_partial(self):
        """Test updating only some fields."""
        update_data = {
            "confidence": "90%"
        }
        
        prediction_update = PredictionUpdate(**update_data)
        
        assert prediction_update.confidence == "90%"
        assert prediction_update.energy_score is None
        assert prediction_update.predicted_winner is None
    
    def test_prediction_update_all_fields(self):
        """Test updating all fields."""
        update_data = {
            "energy_score": "very_high",
            "confidence": "95%",
            "predicted_winner": "Real Madrid"
        }
        
        prediction_update = PredictionUpdate(**update_data)
        
        assert prediction_update.energy_score == "very_high"
        assert prediction_update.confidence == "95%"
        assert prediction_update.predicted_winner == "Real Madrid"
    
    def test_prediction_update_empty(self):
        """Test that PredictionUpdate can be empty."""
        prediction_update = PredictionUpdate()
        
        assert prediction_update.energy_score is None
        assert prediction_update.confidence is None
        assert prediction_update.predicted_winner is None


class TestPredictionResponse:
    """Test PredictionResponse schema."""
    
    def test_prediction_response_from_dict(self):
        """Test creating PredictionResponse from dictionary."""
        prediction_dict = {
            "id": 1,
            "match_id": 1,
            "energy_score": "high",
            "confidence": "85%",
            "predicted_winner": "Manchester City",
            "created_at": datetime.now(timezone.utc)
        }
        
        prediction = PredictionResponse(**prediction_dict)
        
        assert prediction.id == 1
        assert prediction.match_id == 1
        assert prediction.energy_score == "high"
        assert prediction.confidence == "85%"
        assert prediction.predicted_winner == "Manchester City"


class TestPredictionListResponse:
    """Test PredictionListResponse schema."""
    
    def test_prediction_list_response(self):
        """Test creating a PredictionListResponse."""
        predictions_data = [
            {
                "id": 1,
                "match_id": 1,
                "energy_score": "high",
                "confidence": "85%",
                "predicted_winner": "PSG",
                "created_at": datetime.now(timezone.utc)
            },
            {
                "id": 2,
                "match_id": 2,
                "energy_score": "medium",
                "confidence": "70%",
                "predicted_winner": "Barcelona",
                "created_at": datetime.now(timezone.utc)
            }
        ]
        
        response = PredictionListResponse(data=predictions_data, count=2, meta={"page": 1})
        
        assert response.count == 2
        assert len(response.data) == 2
        assert response.meta["page"] == 1


class TestPredictionStatsResponse:
    """Test PredictionStatsResponse schema."""
    
    def test_prediction_stats_response(self):
        """Test creating a PredictionStatsResponse."""
        stats = {
            "total_predictions": 20,
            "predictions_by_confidence": {"high": 10, "medium": 5, "low": 5},
            "predictions_by_energy_score": {"high": 8, "medium": 7, "low": 5},
            "avg_confidence": 75.5,
            "unique_matches_predicted": 15
        }
        
        prediction_stats = PredictionStatsResponse(**stats)
        
        assert prediction_stats.total_predictions == 20
        assert prediction_stats.predictions_by_confidence["high"] == 10
        assert prediction_stats.predictions_by_energy_score["medium"] == 7
        assert prediction_stats.avg_confidence == 75.5
        assert prediction_stats.unique_matches_predicted == 15
