# services/recipes/app/schemas/recipes.py
"""
Pydantic schemas for recipe-related API requests and responses
"""

from pydantic import BaseModel, Field
from typing import List, Optional, Dict, Any
from uuid import UUID
from datetime import datetime
from enum import Enum

from ..models.recipes import RecipeStatus, MeasurementUnit


# Quality Template Association Schemas
class QualityStageConfiguration(BaseModel):
    """Schema for quality checks configuration per production stage"""
    template_ids: List[UUID] = Field(default_factory=list, description="Quality template IDs for this stage")
    required_checks: List[str] = Field(default_factory=list, description="Required quality check types")
    optional_checks: List[str] = Field(default_factory=list, description="Optional quality check types")
    blocking_on_failure: bool = Field(default=True, description="Block stage progression on critical failures")
    min_quality_score: Optional[float] = Field(None, ge=0, le=10, description="Minimum quality score to pass stage")


class RecipeQualityConfiguration(BaseModel):
    """Schema for recipe quality configuration across all stages"""
    stages: Dict[str, QualityStageConfiguration] = Field(default_factory=dict, description="Quality configuration per stage")
    overall_quality_threshold: float = Field(default=7.0, ge=0, le=10, description="Overall quality threshold for batch")
    critical_stage_blocking: bool = Field(default=True, description="Block progression if critical checks fail")
    auto_create_quality_checks: bool = Field(default=True, description="Automatically create quality checks for batches")
    quality_manager_approval_required: bool = Field(default=False, description="Require quality manager approval")


class RecipeQualityConfigurationUpdate(BaseModel):
    """Schema for updating recipe quality configuration"""
    stages: Optional[Dict[str, QualityStageConfiguration]] = None
    overall_quality_threshold: Optional[float] = Field(None, ge=0, le=10)
    critical_stage_blocking: Optional[bool] = None
    auto_create_quality_checks: Optional[bool] = None
    quality_manager_approval_required: Optional[bool] = None


class RecipeIngredientCreate(BaseModel):
    """Schema for creating recipe ingredients"""
    ingredient_id: UUID
    quantity: float = Field(..., gt=0)
    unit: MeasurementUnit
    alternative_quantity: Optional[float] = None
    alternative_unit: Optional[MeasurementUnit] = None
    preparation_method: Optional[str] = None
    ingredient_notes: Optional[str] = None
    is_optional: bool = False
    ingredient_order: int = Field(..., ge=1)
    ingredient_group: Optional[str] = None
    substitution_options: Optional[Dict[str, Any]] = None
    substitution_ratio: Optional[float] = None


class RecipeIngredientUpdate(BaseModel):
    """Schema for updating recipe ingredients"""
    ingredient_id: Optional[UUID] = None
    quantity: Optional[float] = Field(None, gt=0)
    unit: Optional[MeasurementUnit] = None
    alternative_quantity: Optional[float] = None
    alternative_unit: Optional[MeasurementUnit] = None
    preparation_method: Optional[str] = None
    ingredient_notes: Optional[str] = None
    is_optional: Optional[bool] = None
    ingredient_order: Optional[int] = Field(None, ge=1)
    ingredient_group: Optional[str] = None
    substitution_options: Optional[Dict[str, Any]] = None
    substitution_ratio: Optional[float] = None


class RecipeIngredientResponse(BaseModel):
    """Schema for recipe ingredient responses"""
    id: UUID
    tenant_id: UUID
    recipe_id: UUID
    ingredient_id: UUID
    quantity: float
    unit: str
    quantity_in_base_unit: Optional[float] = None
    alternative_quantity: Optional[float] = None
    alternative_unit: Optional[str] = None
    preparation_method: Optional[str] = None
    ingredient_notes: Optional[str] = None
    is_optional: bool
    ingredient_order: int
    ingredient_group: Optional[str] = None
    substitution_options: Optional[Dict[str, Any]] = None
    substitution_ratio: Optional[float] = None
    unit_cost: Optional[float] = None
    total_cost: Optional[float] = None
    cost_updated_at: Optional[datetime] = None

    class Config:
        from_attributes = True


class RecipeCreate(BaseModel):
    """Schema for creating recipes"""
    name: str = Field(..., min_length=1, max_length=255)
    recipe_code: Optional[str] = Field(None, max_length=100)
    version: str = Field(default="1.0", max_length=20)
    finished_product_id: UUID
    description: Optional[str] = None
    category: Optional[str] = Field(None, max_length=100)
    cuisine_type: Optional[str] = Field(None, max_length=100)
    difficulty_level: int = Field(default=1, ge=1, le=5)
    yield_quantity: float = Field(..., gt=0)
    yield_unit: MeasurementUnit
    prep_time_minutes: Optional[int] = Field(None, ge=0)
    cook_time_minutes: Optional[int] = Field(None, ge=0)
    total_time_minutes: Optional[int] = Field(None, ge=0)
    rest_time_minutes: Optional[int] = Field(None, ge=0)
    instructions: Optional[Dict[str, Any]] = None
    preparation_notes: Optional[str] = None
    storage_instructions: Optional[str] = None
    quality_check_configuration: Optional[RecipeQualityConfiguration] = None
    serves_count: Optional[int] = Field(None, ge=1)
    nutritional_info: Optional[Dict[str, Any]] = None
    allergen_info: Optional[Dict[str, Any]] = None
    dietary_tags: Optional[Dict[str, Any]] = None
    batch_size_multiplier: float = Field(default=1.0, gt=0)
    minimum_batch_size: Optional[float] = Field(None, gt=0)
    maximum_batch_size: Optional[float] = Field(None, gt=0)
    optimal_production_temperature: Optional[float] = None
    optimal_humidity: Optional[float] = Field(None, ge=0, le=100)
    is_seasonal: bool = False
    season_start_month: Optional[int] = Field(None, ge=1, le=12)
    season_end_month: Optional[int] = Field(None, ge=1, le=12)
    is_signature_item: bool = False
    target_margin_percentage: Optional[float] = Field(None, ge=0)
    ingredients: List[RecipeIngredientCreate] = Field(..., min_items=1)


class RecipeUpdate(BaseModel):
    """Schema for updating recipes"""
    name: Optional[str] = Field(None, min_length=1, max_length=255)
    recipe_code: Optional[str] = Field(None, max_length=100)
    version: Optional[str] = Field(None, max_length=20)
    description: Optional[str] = None
    category: Optional[str] = Field(None, max_length=100)
    cuisine_type: Optional[str] = Field(None, max_length=100)
    difficulty_level: Optional[int] = Field(None, ge=1, le=5)
    yield_quantity: Optional[float] = Field(None, gt=0)
    yield_unit: Optional[MeasurementUnit] = None
    prep_time_minutes: Optional[int] = Field(None, ge=0)
    cook_time_minutes: Optional[int] = Field(None, ge=0)
    total_time_minutes: Optional[int] = Field(None, ge=0)
    rest_time_minutes: Optional[int] = Field(None, ge=0)
    instructions: Optional[Dict[str, Any]] = None
    preparation_notes: Optional[str] = None
    storage_instructions: Optional[str] = None
    quality_check_configuration: Optional[RecipeQualityConfigurationUpdate] = None
    serves_count: Optional[int] = Field(None, ge=1)
    nutritional_info: Optional[Dict[str, Any]] = None
    allergen_info: Optional[Dict[str, Any]] = None
    dietary_tags: Optional[Dict[str, Any]] = None
    batch_size_multiplier: Optional[float] = Field(None, gt=0)
    minimum_batch_size: Optional[float] = Field(None, gt=0)
    maximum_batch_size: Optional[float] = Field(None, gt=0)
    optimal_production_temperature: Optional[float] = None
    optimal_humidity: Optional[float] = Field(None, ge=0, le=100)
    status: Optional[RecipeStatus] = None
    is_seasonal: Optional[bool] = None
    season_start_month: Optional[int] = Field(None, ge=1, le=12)
    season_end_month: Optional[int] = Field(None, ge=1, le=12)
    is_signature_item: Optional[bool] = None
    target_margin_percentage: Optional[float] = Field(None, ge=0)
    ingredients: Optional[List[RecipeIngredientCreate]] = None


class RecipeResponse(BaseModel):
    """Schema for recipe responses"""
    id: UUID
    tenant_id: UUID
    name: str
    recipe_code: Optional[str] = None
    version: str
    finished_product_id: UUID
    description: Optional[str] = None
    category: Optional[str] = None
    cuisine_type: Optional[str] = None
    difficulty_level: int
    yield_quantity: float
    yield_unit: str
    prep_time_minutes: Optional[int] = None
    cook_time_minutes: Optional[int] = None
    total_time_minutes: Optional[int] = None
    rest_time_minutes: Optional[int] = None
    estimated_cost_per_unit: Optional[float] = None
    last_calculated_cost: Optional[float] = None
    cost_calculation_date: Optional[datetime] = None
    target_margin_percentage: Optional[float] = None
    suggested_selling_price: Optional[float] = None
    instructions: Optional[Dict[str, Any]] = None
    preparation_notes: Optional[str] = None
    storage_instructions: Optional[str] = None
    quality_check_configuration: Optional[RecipeQualityConfiguration] = None
    serves_count: Optional[int] = None
    nutritional_info: Optional[Dict[str, Any]] = None
    allergen_info: Optional[Dict[str, Any]] = None
    dietary_tags: Optional[Dict[str, Any]] = None
    batch_size_multiplier: float
    minimum_batch_size: Optional[float] = None
    maximum_batch_size: Optional[float] = None
    optimal_production_temperature: Optional[float] = None
    optimal_humidity: Optional[float] = None
    status: str
    is_seasonal: bool
    season_start_month: Optional[int] = None
    season_end_month: Optional[int] = None
    is_signature_item: bool
    created_at: datetime
    updated_at: datetime
    created_by: Optional[UUID] = None
    updated_by: Optional[UUID] = None
    ingredients: Optional[List[RecipeIngredientResponse]] = None

    class Config:
        from_attributes = True


class RecipeDeletionSummary(BaseModel):
    """Summary of what will be deleted when hard-deleting a recipe"""
    recipe_id: UUID
    recipe_name: str
    recipe_code: str
    production_batches_count: int
    recipe_ingredients_count: int
    dependent_recipes_count: int  # Recipes that use this as ingredient/sub-recipe
    affected_orders_count: int  # Orders that include this recipe
    last_used_date: Optional[datetime] = None
    can_delete: bool
    warnings: List[str] = []


class RecipeSearchRequest(BaseModel):
    """Schema for recipe search requests"""
    search_term: Optional[str] = None
    status: Optional[RecipeStatus] = None
    category: Optional[str] = None
    is_seasonal: Optional[bool] = None
    is_signature: Optional[bool] = None
    difficulty_level: Optional[int] = Field(None, ge=1, le=5)
    limit: int = Field(default=100, ge=1, le=1000)
    offset: int = Field(default=0, ge=0)


class RecipeDuplicateRequest(BaseModel):
    """Schema for recipe duplication requests"""
    new_name: str = Field(..., min_length=1, max_length=255)


class RecipeFeasibilityResponse(BaseModel):
    """Schema for recipe feasibility check responses"""
    recipe_id: UUID
    recipe_name: str
    batch_multiplier: float
    feasible: bool
    missing_ingredients: List[Dict[str, Any]] = []
    insufficient_ingredients: List[Dict[str, Any]] = []


class RecipeStatisticsResponse(BaseModel):
    """Schema for recipe statistics responses"""
    total_recipes: int
    active_recipes: int
    signature_recipes: int
    seasonal_recipes: int
    category_breakdown: List[Dict[str, Any]]