"""Users router: admin-only user management (list, create, update, deactivate).""" import uuid from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from app.database import get_db from app.dependencies import get_pagination, require_role from app.models.user import User from app.schemas.user import ( UserCreate, UserListResponse, UserResponse, UserUpdate, ) from app.services.auth_service import ( create_user as svc_create_user, deactivate_user as svc_deactivate_user, list_users as svc_list_users, update_user as svc_update_user, ) router = APIRouter(prefix="/users", tags=["users"]) @router.get("/", response_model=UserListResponse, status_code=status.HTTP_200_OK) async def list_users( db: AsyncSession = Depends(get_db), pagination: dict = Depends(get_pagination), admin: User = Depends(require_role(["admin"])), ): """List all users with pagination. Admin only.""" users, total = await svc_list_users( db, page=pagination["page"], page_size=pagination["page_size"] ) return UserListResponse( items=[UserResponse.model_validate(u) for u in users], total=total, page=pagination["page"], page_size=pagination["page_size"], ) @router.post("/", response_model=UserResponse, status_code=status.HTTP_201_CREATED) async def create_user( body: UserCreate, db: AsyncSession = Depends(get_db), admin: User = Depends(require_role(["admin"])), ): """Create a new user. Admin only.""" try: user = await svc_create_user( db, email=body.email, password=body.password, full_name=body.full_name, role=body.role, language=body.language, ) except ValueError as exc: raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail={"error": {"code": "DUPLICATE_EMAIL", "message": str(exc)}}, ) return UserResponse.model_validate(user) @router.put("/{user_id}", response_model=UserResponse, status_code=status.HTTP_200_OK) async def update_user( user_id: uuid.UUID, body: UserUpdate, db: AsyncSession = Depends(get_db), admin: User = Depends(require_role(["admin"])), ): """Update a user's fields. Admin only.""" updates = body.model_dump(exclude_unset=True) if not updates: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail={"error": {"code": "NO_FIELDS", "message": "No fields to update"}}, ) user = await svc_update_user(db, user_id, **updates) if user is None: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail={"error": {"code": "USER_NOT_FOUND", "message": "User not found"}}, ) return UserResponse.model_validate(user) @router.delete( "/{user_id}", response_model=UserResponse, status_code=status.HTTP_200_OK ) async def delete_user( user_id: uuid.UUID, db: AsyncSession = Depends(get_db), admin: User = Depends(require_role(["admin"])), ): """Deactivate a user (soft delete). Admin only.""" user = await svc_deactivate_user(db, user_id) if user is None: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail={"error": {"code": "USER_NOT_FOUND", "message": "User not found"}}, ) return UserResponse.model_validate(user)