"""Service layer for user profile management. All user database operations go through this service. Routes should never query the users table directly. """ from typing import Optional import structlog from sqlmodel import Session, select from app.models.user import User logger = structlog.get_logger(__name__) class UserService: """Handles CRUD operations for User records. Args: session: An active SQLModel Session. """ def __init__(self, session: Session) -> None: self._session = session def create_user( self, username: str, display_name: str, height: Optional[str] = None, weight: Optional[str] = None, goals: Optional[str] = None, ) -> User: """Create a new user profile. Args: username: Unique identifier. display_name: Human-readable name. height: User height as string. weight: User weight as string. goals: Free-text goals. Returns: The newly created User record. """ user = User( username=username, display_name=display_name, height=height, weight=weight, goals=goals, ) self._session.add(user) self._session.commit() self._session.refresh(user) logger.info("user_created", username=username) return user def get_user_by_id(self, user_id: int) -> Optional[User]: """Retrieve a user by primary key.""" return self._session.get(User, user_id) def get_user_by_username(self, username: str) -> Optional[User]: """Retrieve a user by username.""" statement = select(User).where(User.username == username) return self._session.exec(statement).first() def list_users(self) -> list[User]: """List all user profiles.""" statement = select(User) return list(self._session.exec(statement).all()) def update_user(self, user_id: int, **kwargs) -> User: """Update fields on an existing user. Args: user_id: The user's ID. **kwargs: Field names and new values to update. Returns: The updated User record. Raises: ValueError: If the user is not found. """ user = self.get_user_by_id(user_id) if user is None: raise ValueError(f"User with id {user_id} not found") for key, value in kwargs.items(): if hasattr(user, key): setattr(user, key, value) self._session.add(user) self._session.commit() self._session.refresh(user) logger.info("user_updated", user_id=user_id, fields=list(kwargs.keys())) return user