from typing import List, Dict, Optional, Union, Any from datetime import datetime import re from sqlalchemy.orm import Session from sqlalchemy import or_ from models.user import User from schemas.user import UserCreate, UserUpdate from passlib.context import CryptContext pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") def validate_username(username: str) -> bool: """ Validate username format and length. Args: username: Username to validate Returns: bool: True if valid, False otherwise """ pattern = r'^[a-zA-Z0-9_]{3,32}$' return bool(re.match(pattern, username)) def hash_password(password: str) -> str: """ Hash a password using bcrypt. Args: password: Plain text password Returns: str: Hashed password """ return pwd_context.hash(password) def verify_password(plain_password: str, hashed_password: str) -> bool: """ Verify a password against its hash. Args: plain_password: Password to verify hashed_password: Stored hash to check against Returns: bool: True if password matches """ return pwd_context.verify(plain_password, hashed_password) def search_users( db: Session, search_term: str, skip: int = 0, limit: int = 10 ) -> List[User]: """ Search for users by username, first name, or last name. Args: db: Database session search_term: Term to search for skip: Number of records to skip limit: Max number of records to return Returns: List of matching users """ return db.query(User).filter( or_( User.username.ilike(f"%{search_term}%"), User.first_name.ilike(f"%{search_term}%"), User.last_name.ilike(f"%{search_term}%") ) ).offset(skip).limit(limit).all() def update_last_login(db: Session, user: User) -> User: """ Update user's last login timestamp. Args: db: Database session user: User to update Returns: Updated user object """ user.last_login = datetime.utcnow() db.commit() db.refresh(user) return user def format_user_profile(user: User) -> Dict[str, Any]: """ Format user data for profile display. Args: user: User object to format Returns: Dict containing formatted user profile data """ return { "username": user.username, "full_name": f"{user.first_name or ''} {user.last_name or ''}".strip(), "bio": user.bio or "No bio available", "profile_picture": user.profile_picture or "default.jpg", "relationship_status": user.relationship_status or "Not specified", "interests": user.interests.split(",") if user.interests else [], "last_active": user.last_login.isoformat() if user.last_login else None } def validate_user_update(user_data: UserUpdate) -> Dict[str, str]: """ Validate user update data. Args: user_data: Update data to validate Returns: Dict with error messages if validation fails """ errors = {} if user_data.username and not validate_username(user_data.username): errors["username"] = "Invalid username format" if user_data.email and not validate_email(user_data.email): errors["email"] = "Invalid email format" if user_data.profile_picture and not user_data.profile_picture.endswith(('.jpg','.png','.jpeg')): errors["profile_picture"] = "Invalid image format" if user_data.relationship_status and user_data.relationship_status not in [ "Single", "In a relationship", "Married", "It's complicated" ]: errors["relationship_status"] = "Invalid relationship status" return errors