from datetime import datetime

import pytest

from autotrainer.training import TrainingProgress


@pytest.fixture
def sample_progress_data():
    """Sample progress data dictionary"""
    return {
        "timestamp": "2024-01-15T10:30:00",
        "time_in_training": 3600.5,
        "session_count": 5,
        "pellets_consumed": 12,
        "magnet_baseline": 10,
        "pellet_start_location": [1.0, 2.0, 3.0],
        "pellet_current_location": [1.1, 2.1, 3.1],
        "successful_reaches": 8,
        "phase_attempts": 3,
        "user_context": {
            "notes": "Good progress",
            "difficulty": "easy"
        }
    }


class TestTrainingProgress:
    """Test TrainingProgress serialization and deserialization"""

    def test_training_progress_serialization(self, sample_progress_data):
        """Test TrainingProgress to_dict() includes all fields"""
        progress = TrainingProgress()
        progress.timestamp = datetime.fromisoformat(sample_progress_data["timestamp"])
        progress.time_in_training = sample_progress_data["time_in_training"]
        progress.session_count = sample_progress_data["session_count"]
        progress.pellets_consumed = sample_progress_data["pellets_consumed"]
        progress.magnet_baseline = sample_progress_data["magnet_baseline"]
        progress.pellet_start_location = tuple(sample_progress_data["pellet_start_location"])
        progress.pellet_current_location = tuple(sample_progress_data["pellet_current_location"])
        progress.successful_reaches = sample_progress_data["successful_reaches"]
        progress.phase_attempts = sample_progress_data["phase_attempts"]
        progress.user_context = sample_progress_data["user_context"]

        result = progress.to_dict()

        assert result["timestamp"] == sample_progress_data["timestamp"]

        assert result["timeInTraining"] == sample_progress_data["time_in_training"]
        assert result["sessionCount"] == sample_progress_data["session_count"]
        assert result["pelletsConsumed"] == sample_progress_data["pellets_consumed"]
        assert result["pelletStartLocation"] == sample_progress_data["pellet_start_location"]
        assert result["pelletCurrentLocation"] == sample_progress_data["pellet_current_location"]
        assert result["successfulReaches"] == sample_progress_data["successful_reaches"]
        assert result["phaseAttempts"] == sample_progress_data["phase_attempts"]
        assert result["userContext"] == sample_progress_data["user_context"]

    def test_training_progress_deserialization(self, sample_progress_data):
        """Test TrainingProgress from_dict() restores all fields"""
        progress = TrainingProgress.from_dict(sample_progress_data)

        assert progress.timestamp == datetime.fromisoformat(sample_progress_data["timestamp"])
        assert progress.time_in_training == sample_progress_data["time_in_training"]
        assert progress.session_count == sample_progress_data["session_count"]
        assert progress.pellets_consumed == sample_progress_data["pellets_consumed"]
        assert progress.pellet_start_location == tuple(sample_progress_data["pellet_start_location"])
        assert progress.pellet_current_location == tuple(sample_progress_data["pellet_current_location"])
        assert progress.successful_reaches == sample_progress_data["successful_reaches"]
        assert progress.phase_attempts == sample_progress_data["phase_attempts"]
        assert progress.user_context == sample_progress_data["user_context"]

    def test_training_progress_backward_compatibility(self):
        """Test TrainingProgress handles missing optional fields with defaults"""
        minimal_data = {
            "timestamp": "2024-01-15T10:30:00",
            "time_in_training": 1800.0,
            "session_count": 2,
            "pellets_consumed": 5,
            "magnet_baseline": 10,
            "pellet_start_location": [0.0, 0.0, 0.0],
            "pellet_current_location": [0.0, 0.0, 0.0]
        }

        progress = TrainingProgress.from_dict(minimal_data)

        assert progress.successful_reaches == 0
        assert progress.phase_attempts == 0
        assert progress.user_context == {}