from __future__ import annotations from typing import Any, List from fastapi import APIRouter, Depends, HTTPException, Path, Query, status from sqlalchemy.orm import Session from app import models, schemas from app.api import deps from app.db.session import get_db from app.models.achievement import AchievementType from app.services.achievement import achievement, user_achievement router = APIRouter() @router.get("/", response_model=List[schemas.Achievement]) def read_achievements( db: Session = Depends(get_db), skip: int = 0, limit: int = 100, achievement_type: AchievementType = Query(None, description="Filter by achievement type"), active_only: bool = Query(True, description="Filter only active achievements"), ) -> Any: """ Retrieve achievements. """ if achievement_type: achievements = achievement.get_by_type( db, achievement_type=achievement_type, skip=skip, limit=limit ) elif active_only: achievements = achievement.get_active(db, skip=skip, limit=limit) else: achievements = achievement.get_multi(db, skip=skip, limit=limit) return achievements @router.post("/", response_model=schemas.Achievement) def create_achievement( *, db: Session = Depends(get_db), achievement_in: schemas.AchievementCreate, current_user: models.User = Depends(deps.get_current_active_superuser), ) -> Any: """ Create new achievement. Only for superusers. """ achievement_obj = achievement.create(db, obj_in=achievement_in) return achievement_obj @router.get("/{achievement_id}", response_model=schemas.Achievement) def read_achievement( *, db: Session = Depends(get_db), achievement_id: int = Path(..., gt=0), ) -> Any: """ Get achievement by ID. """ achievement_obj = achievement.get(db, id=achievement_id) if not achievement_obj: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Achievement not found", ) return achievement_obj @router.put("/{achievement_id}", response_model=schemas.Achievement) def update_achievement( *, db: Session = Depends(get_db), achievement_id: int = Path(..., gt=0), achievement_in: schemas.AchievementUpdate, current_user: models.User = Depends(deps.get_current_active_superuser), ) -> Any: """ Update achievement. Only for superusers. """ achievement_obj = achievement.get(db, id=achievement_id) if not achievement_obj: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Achievement not found", ) achievement_obj = achievement.update(db, db_obj=achievement_obj, obj_in=achievement_in) return achievement_obj @router.delete("/{achievement_id}", status_code=status.HTTP_204_NO_CONTENT, response_model=None) def delete_achievement( *, db: Session = Depends(get_db), achievement_id: int = Path(..., gt=0), current_user: models.User = Depends(deps.get_current_active_superuser), ) -> None: """ Delete achievement. Only for superusers. """ achievement_obj = achievement.get(db, id=achievement_id) if not achievement_obj: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Achievement not found", ) achievement.remove(db, id=achievement_id) @router.get("/user/{user_id}", response_model=List[schemas.UserAchievement]) def read_user_achievements( *, db: Session = Depends(get_db), user_id: int = Path(..., gt=0), skip: int = 0, limit: int = 100, current_user: models.User = Depends(deps.get_current_active_user), ) -> Any: """ Get a user's achievements. """ # Regular users can only get their own achievements if user_id != current_user.id and not current_user.is_superuser: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Not enough permissions", ) user_achievements = user_achievement.get_by_user(db, user_id=user_id, skip=skip, limit=limit) return user_achievements @router.post("/user/{user_id}/award/{achievement_id}", response_model=schemas.UserAchievement) def award_achievement_to_user( *, db: Session = Depends(get_db), user_id: int = Path(..., gt=0), achievement_id: int = Path(..., gt=0), current_user: models.User = Depends(deps.get_current_active_superuser), ) -> Any: """ Award an achievement to a user. Only for superusers. """ # Check if achievement exists achievement_obj = achievement.get(db, id=achievement_id) if not achievement_obj: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Achievement not found", ) # Check if user exists user = db.query(models.User).filter(models.User.id == user_id).first() if not user: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="User not found", ) user_achievement_obj = user_achievement.award_achievement( db, user_id=user_id, achievement_id=achievement_id ) return user_achievement_obj @router.post("/user/{user_id}/check", response_model=List[schemas.UserAchievement]) def check_user_achievements( *, db: Session = Depends(get_db), user_id: int = Path(..., gt=0), current_user: models.User = Depends(deps.get_current_active_user), ) -> Any: """ Check and award achievements based on user's progress. """ # Regular users can only check their own achievements if user_id != current_user.id and not current_user.is_superuser: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Not enough permissions", ) # Check if user exists user = db.query(models.User).filter(models.User.id == user_id).first() if not user: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="User not found", ) new_achievements = user_achievement.check_achievements(db, user_id=user_id) return new_achievements