from fastapi import APIRouter, HTTPException, status from pydantic import BaseModel, Field from typing import List, Optional from pif_compiler.classes.models import Esposition from pif_compiler.functions.common_log import get_logger logger = get_logger() router = APIRouter() class EspositionRequest(BaseModel): preset_name: str = Field(..., description="Nome del preset") tipo_prodotto: str = Field(..., description="Tipo di prodotto cosmetico") luogo_applicazione: str = Field(..., description="Luogo di applicazione") esp_normali: List[str] = Field(..., description="Vie di esposizione normali") esp_secondarie: List[str] = Field(..., description="Vie di esposizione secondarie") esp_nano: List[str] = Field(..., description="Vie di esposizione nano") sup_esposta: int = Field(..., ge=1, le=17500, description="Area di applicazione in cm2") freq_applicazione: float = Field(default=1, description="Numero di applicazioni al giorno") qta_giornaliera: float = Field(..., description="Quantità di prodotto applicata (g/die)") ritenzione: float = Field(default=1.0, ge=0, le=1.0, description="Fattore di ritenzione") class Config: json_schema_extra = { "example": { "preset_name": "Crema viso leave-on", "tipo_prodotto": "Crema", "luogo_applicazione": "Viso", "esp_normali": ["Dermal"], "esp_secondarie": ["Oral", "Inhalation"], "esp_nano": ["Dermal"], "sup_esposta": 565, "freq_applicazione": 2, "qta_giornaliera": 1.54, "ritenzione": 1.0 } } class EspositionResponse(BaseModel): success: bool data: Optional[dict] = None error: Optional[str] = None class EspositionListResponse(BaseModel): success: bool total: int data: Optional[List[dict]] = None error: Optional[str] = None @router.post("/esposition/create", response_model=EspositionResponse, tags=["Esposition"]) async def create_esposition(request: EspositionRequest): """Crea un nuovo preset di esposizione e lo salva su PostgreSQL.""" logger.info(f"Creazione preset esposizione: {request.preset_name}") try: esposition = Esposition(**request.model_dump()) id_preset = esposition.save_to_postgres() if not id_preset: logger.warning(f"Salvataggio fallito per preset: {request.preset_name}") return EspositionResponse( success=False, error=f"Errore nel salvataggio del preset '{request.preset_name}'" ) logger.info(f"Preset '{request.preset_name}' creato con id_preset={id_preset}") return EspositionResponse( success=True, data={"id_preset": id_preset, **esposition.model_dump()} ) except Exception as e: logger.error(f"Errore creazione preset {request.preset_name}: {str(e)}", exc_info=True) raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Errore interno: {str(e)}" ) @router.delete("/esposition/delete/{preset_name}", response_model=EspositionResponse, tags=["Esposition"]) async def delete_esposition(preset_name: str): """Elimina un preset di esposizione tramite il nome.""" logger.info(f"Eliminazione preset esposizione: {preset_name}") try: deleted = Esposition.delete_by_name(preset_name) if not deleted: logger.warning(f"Preset '{preset_name}' non trovato") raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Preset '{preset_name}' non trovato" ) logger.info(f"Preset '{preset_name}' eliminato con successo") return EspositionResponse( success=True, data={"preset_name": preset_name, "deleted": True} ) except HTTPException: raise except Exception as e: logger.error(f"Errore eliminazione preset {preset_name}: {str(e)}", exc_info=True) raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Errore interno: {str(e)}" ) @router.get("/esposition/presets", response_model=EspositionListResponse, tags=["Esposition"]) async def get_all_presets(): """Recupera tutti i preset di esposizione da PostgreSQL.""" logger.info("Recupero tutti i preset di esposizione") try: presets = Esposition.get_presets() logger.info(f"Recuperati {len(presets)} preset") return EspositionListResponse( success=True, total=len(presets), data=[p.model_dump() for p in presets] ) except Exception as e: logger.error(f"Errore recupero preset: {str(e)}", exc_info=True) raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Errore interno: {str(e)}" )