from fastapi import APIRouter, Depends from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select, func from app.database import get_db from app.models.user import User from app.models.scan import Scan from app.models.achievement import Achievement, UserAchievement from app.utils.security import get_current_user router = APIRouter(prefix="/api", tags=["achievements"]) @router.get("/achievements") async def get_achievements(user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db)): # Get all achievements res = await db.execute(select(Achievement).order_by(Achievement.id)) all_achievements = res.scalars().all() # Get user unlocked unlocked_res = await db.execute( select(UserAchievement).where(UserAchievement.user_id == user.id) ) unlocked = {ua.achievement_id: ua.unlocked_at for ua in unlocked_res.scalars().all()} # Get progress counts total_scans_res = await db.execute(select(func.count(Scan.id)).where(Scan.user_id == user.id)) total_scans = total_scans_res.scalar() or 0 photo_scans_res = await db.execute( select(func.count(Scan.id)).where(Scan.user_id == user.id, Scan.barcode == "PHOTO") ) photo_scans = photo_scans_res.scalar() or 0 progress_map = { "first_scan": min(total_scans, 1), "detective": min(total_scans, 10), "expert": min(total_scans, 50), "master": min(total_scans, 100), "photographer": min(photo_scans, 5), "comparator": 0, # tracked separately } result = [] for a in all_achievements: is_unlocked = a.id in unlocked result.append({ "id": a.id, "code": a.code, "name": a.name, "description": a.description, "emoji": a.emoji, "target": a.target, "progress": progress_map.get(a.code, 0), "unlocked": is_unlocked, "unlocked_at": unlocked[a.id].isoformat() if is_unlocked else None, }) return {"achievements": result, "total_scans": total_scans}