from pydantic import BaseModel, Field, field_validator from typing import Optional, List, Dict, Any from datetime import datetime from enum import Enum class GatewayHealthStatus(str, Enum): HEALTHY = "healthy" UNHEALTHY = "unhealthy" UNKNOWN = "unknown" # === CREATE === class SageGatewayCreate(BaseModel): name: str = Field( ..., min_length=2, max_length=100, description="Nom de la gateway" ) description: Optional[str] = Field(None, max_length=500) gateway_url: str = Field( ..., description="URL de la gateway Sage (ex: http://192.168.1.50:8100)" ) gateway_token: str = Field( ..., min_length=10, description="Token d'authentification" ) sage_company: Optional[str] = Field(None, max_length=255) is_active: bool = Field(False, description="Activer immédiatement cette gateway") is_default: bool = Field(False, description="Définir comme gateway par défaut") priority: int = Field(0, ge=0, le=100) extra_config: Optional[Dict[str, Any]] = Field( None, description="Configuration JSON additionnelle" ) allowed_ips: Optional[List[str]] = Field( None, description="Liste des IPs autorisées" ) @field_validator("gateway_url") @classmethod def validate_url(cls, v): if not v.startswith(("http://", "https://")): raise ValueError("L'URL doit commencer par http:// ou https://") return v.rstrip("/") class SageGatewayUpdate(BaseModel): name: Optional[str] = Field(None, min_length=2, max_length=100) description: Optional[str] = Field(None, max_length=500) gateway_url: Optional[str] = None gateway_token: Optional[str] = Field(None, min_length=10) is_default: Optional[bool] = None priority: Optional[int] = Field(None, ge=0, le=100) extra_config: Optional[Dict[str, Any]] = None allowed_ips: Optional[List[str]] = None @field_validator("gateway_url") @classmethod def validate_url(cls, v): if v and not v.startswith(("http://", "https://")): raise ValueError("L'URL doit commencer par http:// ou https://") return v.rstrip("/") if v else v # === RESPONSE === class SageGatewayResponse(BaseModel): id: str user_id: str name: str description: Optional[str] = None gateway_url: str token_preview: str is_active: bool is_default: bool priority: int health_status: GatewayHealthStatus last_health_check: Optional[datetime] = None last_error: Optional[str] = None total_requests: int successful_requests: int failed_requests: int success_rate: float last_used_at: Optional[datetime] = None extra_config: Optional[Dict[str, Any]] = None allowed_ips: Optional[List[str]] = None created_at: datetime updated_at: Optional[datetime] = None class Config: from_attributes = True class SageGatewayListResponse(BaseModel): items: List[SageGatewayResponse] total: int active_gateway: Optional[SageGatewayResponse] = None using_fallback: bool = False class SageGatewayHealthCheck(BaseModel): gateway_id: str gateway_name: str status: GatewayHealthStatus response_time_ms: Optional[float] = None sage_version: Optional[str] = None error: Optional[str] = None checked_at: datetime class SageGatewayActivateRequest(BaseModel): gateway_id: str class SageGatewayTestRequest(BaseModel): gateway_url: str gateway_token: str @field_validator("gateway_url") @classmethod def validate_url(cls, v): if not v.startswith(("http://", "https://")): raise ValueError("L'URL doit commencer par http:// ou https://") return v.rstrip("/") class SageGatewayStatsResponse(BaseModel): total_gateways: int active_gateways: int total_requests: int successful_requests: int failed_requests: int average_success_rate: float most_used_gateway: Optional[str] = None last_activity: Optional[datetime] = None class CurrentGatewayInfo(BaseModel): source: str gateway_id: Optional[str] = None gateway_name: Optional[str] = None gateway_url: str is_healthy: Optional[bool] = None user_id: Optional[str] = None