from sqlalchemy.orm import Session
from sqlalchemy import and_
from typing import Optional, List
from app.models.user import User
from app.schemas.user import UserCreate, UserUpdate
from app.core.security import get_password_hash, verify_password


class UserCRUD:
    def get_by_id(self, db: Session, user_id: int) -> Optional[User]:
        """Obtenir un utilisateur par ID"""
        return db.query(User).filter(User.id == user_id).first()
    
    def get_by_email(self, db: Session, email: str) -> Optional[User]:
        """Obtenir un utilisateur par email"""
        return db.query(User).filter(User.email == email).first()
    
    def get_by_username(self, db: Session, username: str) -> Optional[User]:
        """Obtenir un utilisateur par nom d'utilisateur"""
        return db.query(User).filter(User.username == username).first()
    
    def get_all(self, db: Session, skip: int = 0, limit: int = 100) -> List[User]:
        """Obtenir tous les utilisateurs"""
        return db.query(User).offset(skip).limit(limit).all()
    
    def create(self, db: Session, user_create: UserCreate) -> User:
        """Créer un nouvel utilisateur"""
        hashed_password = get_password_hash(user_create.password)
        db_user = User(
            email=user_create.email,
            username=user_create.username,
            full_name=user_create.full_name,
            hashed_password=hashed_password,
            phone=user_create.phone,
            address=user_create.address,
            city=user_create.city,
            postal_code=user_create.postal_code,
            country=user_create.country
        )
        db.add(db_user)
        db.commit()
        db.refresh(db_user)
        return db_user
    
    def update(self, db: Session, user_id: int, user_update: UserUpdate) -> Optional[User]:
        """Mettre à jour un utilisateur"""
        db_user = self.get_by_id(db, user_id)
        if not db_user:
            return None
        
        update_data = user_update.dict(exclude_unset=True)
        
        # Hasher le mot de passe si fourni
        if "password" in update_data:
            update_data["hashed_password"] = get_password_hash(update_data.pop("password"))
        
        for field, value in update_data.items():
            setattr(db_user, field, value)
        
        db.commit()
        db.refresh(db_user)
        return db_user
    
    def delete(self, db: Session, user_id: int) -> bool:
        """Supprimer un utilisateur"""
        db_user = self.get_by_id(db, user_id)
        if not db_user:
            return False
        
        db.delete(db_user)
        db.commit()
        return True
    
    def authenticate(self, db: Session, email: str, password: str) -> Optional[User]:
        """Authentifier un utilisateur"""
        user = self.get_by_email(db, email)
        if not user:
            return None
        if not verify_password(password, user.hashed_password):
            return None
        return user
    
    def verify_email(self, db: Session, user_id: int) -> Optional[User]:
        """Vérifier l'email d'un utilisateur"""
        from datetime import datetime
        db_user = self.get_by_id(db, user_id)
        if not db_user:
            return None
        
        db_user.is_verified = True
        db_user.email_verified_at = datetime.utcnow()
        db.commit()
        db.refresh(db_user)
        return db_user


user_crud = UserCRUD()
