"""Schémas Pydantic pour la validation des données utilisateur."""

from typing import Optional
from pydantic import BaseModel, EmailStr, field_validator, Field
from utils.validators import validate_username_format, validate_password_strength


class UserRegisterSchema(BaseModel):
    """Schéma pour l'inscription d'un nouvel utilisateur.
    
    Attributes:
        email: Adresse email (unique).
        username: Nom d'utilisateur (unique, 3-50 caractères).
        password: Mot de passe (minimum 8 caractères avec majuscule, minuscule et chiffre).
        password_confirm: Confirmation du mot de passe.
    """
    
    email: EmailStr
    username: str = Field(..., min_length=3, max_length=50)
    password: str = Field(..., min_length=8)
    password_confirm: str
    
    @field_validator('username')
    @classmethod
    def validate_username(cls, v: str) -> str:
        """Valide le format du username.
        
        Args:
            v: Username à valider.
        
        Returns:
            Username validé.
        
        Raises:
            ValueError: Si le username est invalide.
        """
        if not validate_username_format(v):
            raise ValueError(
                "Le nom d'utilisateur doit commencer par une lettre et ne contenir "
                "que des lettres, chiffres, underscores et tirets"
            )
        return v
    
    @field_validator('password')
    @classmethod
    def validate_password(cls, v: str) -> str:
        """Valide la force du mot de passe.
        
        Args:
            v: Mot de passe à valider.
        
        Returns:
            Mot de passe validé.
        
        Raises:
            ValueError: Si le mot de passe est trop faible.
        """
        is_valid, error_message = validate_password_strength(v)
        if not is_valid:
            raise ValueError(error_message)
        return v
    
    def validate_passwords_match(self) -> None:
        """Vérifie que les mots de passe correspondent.
        
        Raises:
            ValueError: Si les mots de passe ne correspondent pas.
        """
        if self.password != self.password_confirm:
            raise ValueError("Les mots de passe ne correspondent pas")


class UserLoginSchema(BaseModel):
    """Schéma pour la connexion d'un utilisateur.
    
    Attributes:
        email: Adresse email.
        password: Mot de passe.
    """
    
    email: EmailStr
    password: str


class UserUpdateSchema(BaseModel):
    """Schéma pour la mise à jour du profil utilisateur.
    
    Attributes:
        username: Nouveau nom d'utilisateur (optionnel).
        email: Nouvelle adresse email (optionnel).
    """
    
    username: Optional[str] = Field(None, min_length=3, max_length=50)
    email: Optional[EmailStr] = None
    
    @field_validator('username')
    @classmethod
    def validate_username(cls, v: Optional[str]) -> Optional[str]:
        """Valide le format du username si fourni.
        
        Args:
            v: Username à valider.
        
        Returns:
            Username validé ou None.
        
        Raises:
            ValueError: Si le username est invalide.
        """
        if v is not None and not validate_username_format(v):
            raise ValueError(
                "Le nom d'utilisateur doit commencer par une lettre et ne contenir "
                "que des lettres, chiffres, underscores et tirets"
            )
        return v


class UserResponseSchema(BaseModel):
    """Schéma pour la réponse contenant les données utilisateur.
    
    Attributes:
        id: ID de l'utilisateur.
        email: Adresse email.
        username: Nom d'utilisateur.
        is_active: Compte actif ou non.
        is_verified: Email vérifié ou non.
        created_at: Date de création.
        updated_at: Date de dernière mise à jour.
    """
    
    id: str
    email: str
    username: str
    is_active: bool
    is_verified: bool
    created_at: str
    updated_at: str
    
    model_config = {
        "from_attributes": True
    }

