# services/production/app/schemas/quality_templates.py
"""
Quality Check Template Pydantic schemas for validation and serialization
"""

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

from ..models.production import ProcessStage


class QualityCheckType(str, Enum):
    """Quality check types"""
    VISUAL = "visual"
    MEASUREMENT = "measurement"
    TEMPERATURE = "temperature"
    WEIGHT = "weight"
    BOOLEAN = "boolean"
    TIMING = "timing"
    CHECKLIST = "checklist"


class QualityCheckTemplateBase(BaseModel):
    """Base schema for quality check templates"""
    name: str = Field(..., min_length=1, max_length=255, description="Template name")
    template_code: Optional[str] = Field(None, max_length=100, description="Template code for reference")
    check_type: QualityCheckType = Field(..., description="Type of quality check")
    category: Optional[str] = Field(None, max_length=100, description="Check category (e.g., appearance, structure)")
    description: Optional[str] = Field(None, description="Template description")
    instructions: Optional[str] = Field(None, description="Check instructions for staff")

    # Configuration
    parameters: Optional[Dict[str, Any]] = Field(None, description="Dynamic check parameters")
    thresholds: Optional[Dict[str, Any]] = Field(None, description="Pass/fail criteria")
    scoring_criteria: Optional[Dict[str, Any]] = Field(None, description="Scoring methodology")

    # Settings
    is_active: bool = Field(True, description="Whether template is active")
    is_required: bool = Field(False, description="Whether check is required")
    is_critical: bool = Field(False, description="Whether failure blocks production")
    weight: float = Field(1.0, ge=0.0, le=10.0, description="Weight in overall quality score")

    # Measurement specifications
    min_value: Optional[float] = Field(None, description="Minimum acceptable value")
    max_value: Optional[float] = Field(None, description="Maximum acceptable value")
    target_value: Optional[float] = Field(None, description="Target value")
    unit: Optional[str] = Field(None, max_length=20, description="Unit of measurement")
    tolerance_percentage: Optional[float] = Field(None, ge=0.0, le=100.0, description="Tolerance percentage")

    # Process stage applicability
    applicable_stages: Optional[List[ProcessStage]] = Field(None, description="Applicable process stages")

    @validator('applicable_stages')
    def validate_stages(cls, v):
        if v is not None:
            # Ensure all values are valid ProcessStage enums
            for stage in v:
                if stage not in ProcessStage:
                    raise ValueError(f"Invalid process stage: {stage}")
        return v

    @validator('min_value', 'max_value', 'target_value')
    def validate_measurement_values(cls, v, values):
        if v is not None and values.get('check_type') not in [QualityCheckType.MEASUREMENT, QualityCheckType.TEMPERATURE, QualityCheckType.WEIGHT]:
            return None  # Clear values for non-measurement types
        return v


class QualityCheckTemplateCreate(QualityCheckTemplateBase):
    """Schema for creating quality check templates"""
    created_by: UUID = Field(..., description="User ID who created the template")


class QualityCheckTemplateUpdate(BaseModel):
    """Schema for updating quality check templates"""
    name: Optional[str] = Field(None, min_length=1, max_length=255)
    template_code: Optional[str] = Field(None, max_length=100)
    check_type: Optional[QualityCheckType] = None
    category: Optional[str] = Field(None, max_length=100)
    description: Optional[str] = None
    instructions: Optional[str] = None
    parameters: Optional[Dict[str, Any]] = None
    thresholds: Optional[Dict[str, Any]] = None
    scoring_criteria: Optional[Dict[str, Any]] = None
    is_active: Optional[bool] = None
    is_required: Optional[bool] = None
    is_critical: Optional[bool] = None
    weight: Optional[float] = Field(None, ge=0.0, le=10.0)
    min_value: Optional[float] = None
    max_value: Optional[float] = None
    target_value: Optional[float] = None
    unit: Optional[str] = Field(None, max_length=20)
    tolerance_percentage: Optional[float] = Field(None, ge=0.0, le=100.0)
    applicable_stages: Optional[List[ProcessStage]] = None


class QualityCheckTemplateResponse(QualityCheckTemplateBase):
    """Schema for quality check template responses"""
    id: UUID
    tenant_id: UUID
    created_by: UUID
    created_at: datetime
    updated_at: datetime

    class Config:
        from_attributes = True


class QualityCheckTemplateList(BaseModel):
    """Schema for paginated quality check template lists"""
    templates: List[QualityCheckTemplateResponse]
    total: int
    skip: int
    limit: int


class QualityCheckCriterion(BaseModel):
    """Individual quality check criterion within a template"""
    id: str = Field(..., description="Unique criterion identifier")
    name: str = Field(..., description="Criterion name")
    description: str = Field(..., description="Criterion description")
    check_type: QualityCheckType = Field(..., description="Type of check")
    required: bool = Field(True, description="Whether criterion is required")
    weight: float = Field(1.0, ge=0.0, le=10.0, description="Weight in template score")
    acceptable_criteria: str = Field(..., description="Description of acceptable criteria")
    min_value: Optional[float] = None
    max_value: Optional[float] = None
    unit: Optional[str] = None
    is_critical: bool = Field(False, description="Whether failure is critical")


class QualityCheckResult(BaseModel):
    """Result of a quality check criterion"""
    criterion_id: str = Field(..., description="Criterion identifier")
    value: Union[float, str, bool] = Field(..., description="Check result value")
    score: float = Field(..., ge=0.0, le=10.0, description="Score for this criterion")
    notes: Optional[str] = Field(None, description="Additional notes")
    photos: Optional[List[str]] = Field(None, description="Photo URLs")
    pass_check: bool = Field(..., description="Whether criterion passed")
    timestamp: datetime = Field(..., description="When check was performed")


class QualityCheckExecutionRequest(BaseModel):
    """Schema for executing a quality check using a template"""
    template_id: UUID = Field(..., description="Quality check template ID")
    batch_id: UUID = Field(..., description="Production batch ID")
    process_stage: ProcessStage = Field(..., description="Current process stage")
    checker_id: Optional[str] = Field(None, description="Staff member performing check")
    results: List[QualityCheckResult] = Field(..., description="Check results")
    final_notes: Optional[str] = Field(None, description="Final notes")
    photos: Optional[List[str]] = Field(None, description="Additional photo URLs")


class QualityCheckExecutionResponse(BaseModel):
    """Schema for quality check execution results"""
    check_id: UUID = Field(..., description="Created quality check ID")
    overall_score: float = Field(..., ge=0.0, le=10.0, description="Overall quality score")
    overall_pass: bool = Field(..., description="Whether check passed overall")
    critical_failures: List[str] = Field(..., description="List of critical failures")
    corrective_actions: List[str] = Field(..., description="Recommended corrective actions")
    timestamp: datetime = Field(..., description="When check was completed")


class ProcessStageQualityConfig(BaseModel):
    """Configuration for quality checks at a specific process stage"""
    stage: ProcessStage = Field(..., description="Process stage")
    template_ids: List[UUID] = Field(..., description="Required template IDs")
    custom_parameters: Optional[Dict[str, Any]] = Field(None, description="Stage-specific parameters")
    is_required: bool = Field(True, description="Whether stage requires quality checks")
    blocking: bool = Field(True, description="Whether stage blocks on failed checks")


class RecipeQualityConfiguration(BaseModel):
    """Quality check configuration for a recipe"""
    stages: Dict[str, ProcessStageQualityConfig] = Field(..., description="Stage configurations")
    global_parameters: Optional[Dict[str, Any]] = Field(None, description="Global quality parameters")
    default_templates: Optional[List[UUID]] = Field(None, description="Default template IDs")