from fastapi import APIRouter, Depends, Query from sqlmodel import Session, select, func, desc from typing import List, Optional from database import get_session from models import Review, Show, Venue, User, Profile router = APIRouter( prefix="/leaderboards", tags=["leaderboards"] ) @router.get("/shows/top") def get_top_shows(limit: int = 10, session: Session = Depends(get_session)): """Get top rated shows based on average review score""" # Group by show_id, calc avg score, count reviews # Filter for shows with at least 1 review (or maybe 2 to be significant?) # SQLModel doesn't support complex group_by/having easily in pure pythonic way sometimes, # but we can use session.exec with a direct select. query = ( select( Show, func.avg(Review.score).label("avg_score"), func.count(Review.id).label("review_count") ) .join(Review, Review.show_id == Show.id) .group_by(Show.id) .having(func.count(Review.id) >= 1) .order_by(desc("avg_score"), desc("review_count")) .limit(limit) ) results = session.exec(query).all() return [ { "show": show, "avg_score": round(score, 2), "review_count": count } for show, score, count in results ] @router.get("/venues/top") def get_top_venues(limit: int = 10, session: Session = Depends(get_session)): """Get top rated venues""" query = ( select( Venue, func.avg(Review.score).label("avg_score"), func.count(Review.id).label("review_count") ) .join(Review, Review.venue_id == Venue.id) .group_by(Venue.id) .order_by(desc("avg_score")) .limit(limit) ) results = session.exec(query).all() return [ { "venue": venue, "avg_score": round(score, 2), "review_count": count } for venue, score, count in results ] @router.get("/users/active") def get_active_users(limit: int = 10, session: Session = Depends(get_session)): """Get users with most reviews""" query = ( select( Profile, func.count(Review.id).label("review_count") ) .join(User, User.id == Profile.user_id) .join(Review, Review.user_id == User.id) .group_by(Profile.id) .order_by(desc("review_count")) .limit(limit) ) results = session.exec(query).all() return [ { "profile": profile, "review_count": count } for profile, count in results ]