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)}"
        )
