"""User management endpoints""" from fastapi import APIRouter, HTTPException, Header from typing import Optional import logging from services.user_service import user_service from models.user import ( UserRegisterRequest, UserResponse, UserUpdateNameRequest, UserGetRequest, ) router = APIRouter() logger = logging.getLogger(__name__) @router.post("/register", response_model=UserResponse, tags=["Users"]) async def register_user(request: UserRegisterRequest): """ Register a new user or get existing user by unique_id - **unique_id**: Browser-generated unique identifier (from localStorage) - **name**: Optional display name (will generate random if not provided) Returns user data including the user_id to store in localStorage """ try: user = user_service.register_or_get_user( unique_id=request.unique_id, name=request.name ) logger.info(f"User registered/retrieved: {user.get('id')}") return UserResponse(**user) except ValueError as e: logger.error(f"Validation error: {str(e)}") raise HTTPException(status_code=400, detail=str(e)) except Exception as e: logger.error(f"Registration error: {str(e)}") raise HTTPException(status_code=500, detail=f"Registration failed: {str(e)}") @router.get("/me", response_model=UserResponse, tags=["Users"]) async def get_current_user(x_user_id: Optional[str] = Header(None, alias="X-User-ID")): """ Get current user by user_id from header - **X-User-ID**: User UUID (sent in request header) Returns user data """ if not x_user_id: raise HTTPException(status_code=400, detail="X-User-ID header is required") try: user = user_service.get_user_by_id(x_user_id) if not user: raise HTTPException(status_code=404, detail="User not found") return UserResponse(**user) except HTTPException: raise except Exception as e: logger.error(f"Error getting user: {str(e)}") raise HTTPException(status_code=500, detail=f"Failed to get user: {str(e)}") @router.get("/by-unique-id", response_model=UserResponse, tags=["Users"]) async def get_user_by_unique_id(unique_id: str): """ Get user by unique_id (query parameter) - **unique_id**: Browser-generated unique identifier Returns user data """ try: user = user_service.get_user_by_unique_id(unique_id) if not user: raise HTTPException(status_code=404, detail="User not found") return UserResponse(**user) except HTTPException: raise except Exception as e: logger.error(f"Error getting user: {str(e)}") raise HTTPException(status_code=500, detail=f"Failed to get user: {str(e)}") @router.patch("/me/name", response_model=UserResponse, tags=["Users"]) async def update_user_name( request: UserUpdateNameRequest, x_user_id: Optional[str] = Header(None, alias="X-User-ID") ): """ Update user's display name - **X-User-ID**: User UUID (sent in request header) - **name**: New display name Returns updated user data """ if not x_user_id: raise HTTPException(status_code=400, detail="X-User-ID header is required") try: user = user_service.update_user_name( user_id=x_user_id, name=request.name ) logger.info(f"Updated user name: {x_user_id}") return UserResponse(**user) except ValueError as e: logger.error(f"Validation error: {str(e)}") raise HTTPException(status_code=400, detail=str(e)) except Exception as e: logger.error(f"Update error: {str(e)}") raise HTTPException(status_code=500, detail=f"Update failed: {str(e)}")