"""
Pydantic schemas for API request/response validation.
"""
from typing import Optional, List, Dict, Any
from pydantic import BaseModel, Field
from enum import Enum


class ExperimentType(str, Enum):
    """Available brace generation experiments."""
    STANDARD = "standard"           # Original pipeline
    EXPERIMENT_3 = "experiment_3"   # Research-based adaptive


class BraceConfigRequest(BaseModel):
    """Brace configuration parameters."""
    brace_height_mm: float = Field(default=400.0, ge=200, le=600)
    torso_width_mm: float = Field(default=280.0, ge=150, le=400)
    torso_depth_mm: float = Field(default=200.0, ge=100, le=350)
    wall_thickness_mm: float = Field(default=4.0, ge=2, le=10)
    pressure_strength_mm: float = Field(default=15.0, ge=0, le=30)


class AnalyzeRequest(BaseModel):
    """Request to analyze X-ray and generate brace."""
    s3_key: Optional[str] = Field(None, description="S3 key of uploaded X-ray image")
    case_id: Optional[str] = Field(None, description="Case ID for organizing outputs")
    experiment: ExperimentType = Field(default=ExperimentType.EXPERIMENT_3)
    config: Optional[BraceConfigRequest] = None
    
    # Output options
    save_visualization: bool = Field(default=True)
    save_landmarks: bool = Field(default=True)
    output_format: str = Field(default="stl", description="stl, ply, or both")


class AnalyzeFromUrlRequest(BaseModel):
    """Request with direct image URL."""
    image_url: str = Field(..., description="URL to download X-ray image from")
    case_id: Optional[str] = Field(None)
    experiment: ExperimentType = Field(default=ExperimentType.EXPERIMENT_3)
    config: Optional[BraceConfigRequest] = None
    save_visualization: bool = True
    save_landmarks: bool = True
    output_format: str = "stl"


class Vertebra(BaseModel):
    """Single vertebra data."""
    level: str
    centroid_px: List[float]
    orientation_deg: Optional[float] = None
    confidence: Optional[float] = None
    corners_px: Optional[List[List[float]]] = None


class CobbAngles(BaseModel):
    """Cobb angle measurements."""
    PT: float = Field(..., description="Proximal Thoracic angle")
    MT: float = Field(..., description="Main Thoracic angle")
    TL: float = Field(..., description="Thoracolumbar angle")


class RigoClassification(BaseModel):
    """Rigo-Chêneau classification result."""
    type: str
    description: str
    curve_pattern: Optional[str] = None


class DeformationReport(BaseModel):
    """Patch-based deformation report (Experiment 3)."""
    patch_grid: str
    deformations: Optional[List[List[float]]] = None
    zones: Optional[List[Dict[str, Any]]] = None


class AnalysisResult(BaseModel):
    """Complete analysis result."""
    case_id: Optional[str] = None
    experiment: str
    
    # Input
    input_image: str
    
    # Detection results
    model_used: str
    vertebrae_detected: int
    vertebrae: Optional[List[Vertebra]] = None
    
    # Measurements
    cobb_angles: CobbAngles
    curve_type: str
    
    # Classification
    rigo_classification: RigoClassification
    
    # Brace mesh info
    mesh_vertices: int
    mesh_faces: int
    
    # Deformation (Experiment 3)
    deformation_report: Optional[DeformationReport] = None
    
    # Output URLs/paths
    outputs: Dict[str, str] = Field(default_factory=dict)
    
    # Timing
    processing_time_ms: float


class HealthResponse(BaseModel):
    """Health check response."""
    status: str
    device: str
    cuda_available: bool
    model_loaded: bool
    gpu_name: Optional[str] = None
    gpu_memory_mb: Optional[int] = None


class ErrorResponse(BaseModel):
    """Error response."""
    error: str
    detail: Optional[str] = None
