"""
Unit tests for recipe models and validation.
"""

import pytest
from datetime import datetime

from src.tempering_machine.shared.models.recipe import Recipe, RecipePhase


class TestRecipe:
    """Test cases for Recipe model."""
    
    def test_recipe_creation(self):
        """Test basic recipe creation."""
        recipe = Recipe(
            name="Test Recipe",
            heating_goal=46.0,
            cooling_goal=27.0,
            tank_temp=45.0,
            fountain_temp=32.0
        )
        
        assert recipe.name == "Test Recipe"
        assert recipe.heating_goal == 46.0
        assert recipe.cooling_goal == 27.0
        assert recipe.is_active is True
        assert recipe.version == 1
    
    def test_recipe_temperature_validation_valid(self):
        """Test valid temperature parameters."""
        recipe = Recipe(
            name="Valid Recipe",
            heating_goal=50.0,
            cooling_goal=25.0,
            pouring_goal=30.0,
            tank_temp=45.0,
            fountain_temp=32.0
        )
        
        assert recipe.validate_temperatures() is True
    
    def test_recipe_temperature_validation_invalid_cooling_too_high(self):
        """Test invalid temperature parameters - cooling goal too high."""
        recipe = Recipe(
            name="Invalid Recipe",
            heating_goal=45.0,
            cooling_goal=50.0,  # Higher than heating goal
            tank_temp=45.0,
            fountain_temp=32.0
        )
        
        assert recipe.validate_temperatures() is False
    
    def test_recipe_temperature_validation_invalid_ranges(self):
        """Test invalid temperature ranges."""
        # Heating goal too low
        recipe1 = Recipe(
            name="Invalid Recipe 1",
            heating_goal=35.0,  # Below minimum of 40°C
            cooling_goal=25.0,
            tank_temp=45.0,
            fountain_temp=32.0
        )
        assert recipe1.validate_temperatures() is False
        
        # Cooling goal too high
        recipe2 = Recipe(
            name="Invalid Recipe 2", 
            heating_goal=50.0,
            cooling_goal=45.0,  # Above maximum of 40°C
            tank_temp=45.0,
            fountain_temp=32.0
        )
        assert recipe2.validate_temperatures() is False
    
    def test_recipe_pouring_goal_validation(self):
        """Test pouring goal validation."""
        # Valid pouring goal within range
        recipe1 = Recipe(
            name="Valid Pouring",
            heating_goal=50.0,
            cooling_goal=25.0,
            pouring_goal=30.0,  # Between cooling and heating
            tank_temp=45.0,
            fountain_temp=32.0
        )
        assert recipe1.validate_temperatures() is True
        
        # Invalid pouring goal - too low
        recipe2 = Recipe(
            name="Invalid Pouring Low",
            heating_goal=50.0,
            cooling_goal=25.0,
            pouring_goal=20.0,  # Below cooling goal
            tank_temp=45.0,
            fountain_temp=32.0
        )
        assert recipe2.validate_temperatures() is False
        
        # Invalid pouring goal - too high
        recipe3 = Recipe(
            name="Invalid Pouring High",
            heating_goal=50.0,
            cooling_goal=25.0,
            pouring_goal=55.0,  # Above heating goal
            tank_temp=45.0,
            fountain_temp=32.0
        )
        assert recipe3.validate_temperatures() is False
    
    def test_get_phase_sequence(self):
        """Test phase sequence generation."""
        recipe = Recipe(
            name="Phase Test",
            heating_goal=46.0,
            cooling_goal=27.0,
            tank_temp=45.0,
            fountain_temp=32.0
        )
        
        phases = recipe.get_phase_sequence()
        expected_phases = [
            RecipePhase.PREHEATING,
            RecipePhase.HEATING,
            RecipePhase.HEATING_DELAY,
            RecipePhase.COOLING,
            RecipePhase.COOLING_DELAY,
            RecipePhase.POURING
        ]
        
        assert phases == expected_phases
    
    def test_recipe_to_dict(self):
        """Test recipe serialization to dictionary."""
        recipe = Recipe(
            name="Serialization Test",
            description="Test description",
            heating_goal=46.0,
            cooling_goal=27.0,
            pouring_goal=30.0,
            tank_temp=45.0,
            fountain_temp=32.0,
            mixer_enabled=True,
            fountain_enabled=True,
            pedal_on_time=2.5,
            pedal_off_time=3.5
        )
        
        recipe_dict = recipe.to_dict()
        
        assert recipe_dict["name"] == "Serialization Test"
        assert recipe_dict["description"] == "Test description"
        assert recipe_dict["heating_goal"] == 46.0
        assert recipe_dict["cooling_goal"] == 27.0
        assert recipe_dict["pouring_goal"] == 30.0
        assert recipe_dict["mixer_enabled"] is True
        assert recipe_dict["pedal_on_time"] == 2.5
        assert recipe_dict["pedal_off_time"] == 3.5
        assert recipe_dict["version"] == 1
        assert recipe_dict["is_active"] is True
    
    def test_from_csv_row(self):
        """Test creating recipe from CSV data."""
        csv_row = {
            "ID": "1",
            "Name": "CSV Recipe",
            "HeatingGoal": "46.0",
            "CoolingGoal": "27.0",
            "PouringGoal": "30.0",
            "TankTemp": "45.0",
            "FountainTemp": "32.0",
            "Mixer": "1",
            "Fountain": "1",
            "MoldHeater": "0",
            "Vibration": "0",
            "VibHeater": "0",
            "Pedal": "1",
            "PedalOnTime": "2.0",
            "PedalOffTime": "3.0"
        }
        
        recipe = Recipe.from_csv_row(csv_row)
        
        assert recipe.id == 1
        assert recipe.name == "CSV Recipe"
        assert recipe.heating_goal == 46.0
        assert recipe.cooling_goal == 27.0
        assert recipe.pouring_goal == 30.0
        assert recipe.mixer_enabled is True
        assert recipe.mold_heater_enabled is False
        assert recipe.pedal_on_time == 2.0


class TestRecipePhase:
    """Test cases for RecipePhase enum."""
    
    def test_recipe_phase_values(self):
        """Test recipe phase enum values."""
        assert RecipePhase.PREHEATING.value == "preheating"
        assert RecipePhase.HEATING.value == "heating"
        assert RecipePhase.HEATING_DELAY.value == "heating_delay"
        assert RecipePhase.COOLING.value == "cooling"
        assert RecipePhase.COOLING_DELAY.value == "cooling_delay"
        assert RecipePhase.POURING.value == "pouring"
        assert RecipePhase.COMPLETED.value == "completed"
        assert RecipePhase.STOPPED.value == "stopped"
        assert RecipePhase.ERROR.value == "error"
    
    def test_recipe_phase_membership(self):
        """Test recipe phase enum membership."""
        assert RecipePhase.PREHEATING in RecipePhase
        assert RecipePhase.HEATING in RecipePhase
        assert RecipePhase.COMPLETED in RecipePhase
        
        # Test string conversion
        assert str(RecipePhase.HEATING) == "RecipePhase.HEATING"