from fastapi import APIRouter, Depends from sqlalchemy.orm import Session from sqlalchemy import func from datetime import datetime, timedelta from config.database import get_db from models.user import User from models.event import Event, EventParticipation, ParticipationStatus from models.album import Album, Media from models.post import Post from models.vlog import Vlog from utils.security import get_current_active_user router = APIRouter() @router.get("/overview") async def get_overview_stats( db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user) ): """Get general overview statistics.""" total_users = db.query(User).filter(User.is_active == True).count() total_events = db.query(Event).count() total_albums = db.query(Album).count() total_posts = db.query(Post).count() total_vlogs = db.query(Vlog).count() total_media = db.query(Media).count() # Recent activity (last 30 days) thirty_days_ago = datetime.utcnow() - timedelta(days=30) recent_events = db.query(Event).filter(Event.created_at >= thirty_days_ago).count() recent_posts = db.query(Post).filter(Post.created_at >= thirty_days_ago).count() recent_vlogs = db.query(Vlog).filter(Vlog.created_at >= thirty_days_ago).count() return { "total_users": total_users, "total_events": total_events, "total_albums": total_albums, "total_posts": total_posts, "total_vlogs": total_vlogs, "total_media": total_media, "recent_events": recent_events, "recent_posts": recent_posts, "recent_vlogs": recent_vlogs } @router.get("/attendance") async def get_attendance_stats( db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user) ): """Get attendance statistics for all users.""" users = db.query(User).filter(User.is_active == True).all() attendance_stats = [] for user in users: # Get past events participation past_participations = db.query(EventParticipation).join(Event).filter( EventParticipation.user_id == user.id, Event.date < datetime.utcnow() ).all() total_past_events = len(past_participations) present_count = sum(1 for p in past_participations if p.status == ParticipationStatus.PRESENT) absent_count = sum(1 for p in past_participations if p.status == ParticipationStatus.ABSENT) # Get upcoming events participation upcoming_participations = db.query(EventParticipation).join(Event).filter( EventParticipation.user_id == user.id, Event.date >= datetime.utcnow() ).all() upcoming_present = sum(1 for p in upcoming_participations if p.status == ParticipationStatus.PRESENT) upcoming_maybe = sum(1 for p in upcoming_participations if p.status == ParticipationStatus.MAYBE) upcoming_pending = sum(1 for p in upcoming_participations if p.status == ParticipationStatus.PENDING) attendance_stats.append({ "user_id": user.id, "username": user.username, "full_name": user.full_name, "avatar_url": user.avatar_url, "attendance_rate": user.attendance_rate, "total_past_events": total_past_events, "present_count": present_count, "absent_count": absent_count, "upcoming_present": upcoming_present, "upcoming_maybe": upcoming_maybe, "upcoming_pending": upcoming_pending }) # Sort by attendance rate attendance_stats.sort(key=lambda x: x["attendance_rate"], reverse=True) return { "attendance_stats": attendance_stats, "best_attendee": attendance_stats[0] if attendance_stats else None, "worst_attendee": attendance_stats[-1] if attendance_stats else None } @router.get("/fun") async def get_fun_stats( db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user) ): """Get fun statistics about the group.""" # Most active poster post_counts = db.query( User.id, User.username, User.full_name, func.count(Post.id).label("post_count") ).join(Post).group_by(User.id).order_by(func.count(Post.id).desc()).first() # Most mentioned user mention_counts = db.query( User.id, User.username, User.full_name, func.count().label("mention_count") ).join(Post.mentions).group_by(User.id).order_by(func.count().desc()).first() # Biggest vlogger vlog_counts = db.query( User.id, User.username, User.full_name, func.count(Vlog.id).label("vlog_count") ).join(Vlog).group_by(User.id).order_by(func.count(Vlog.id).desc()).first() # Photo addict (most albums created) album_counts = db.query( User.id, User.username, User.full_name, func.count(Album.id).label("album_count") ).join(Album).group_by(User.id).order_by(func.count(Album.id).desc()).first() # Event organizer (most events created) event_counts = db.query( User.id, User.username, User.full_name, func.count(Event.id).label("event_count") ).join(Event, Event.creator_id == User.id).group_by(User.id).order_by(func.count(Event.id).desc()).first() # Most viewed vlog most_viewed_vlog = db.query(Vlog).order_by(Vlog.views_count.desc()).first() # Longest event streak (consecutive events attended) # This would require more complex logic to calculate return { "most_active_poster": { "user_id": post_counts[0] if post_counts else None, "username": post_counts[1] if post_counts else None, "full_name": post_counts[2] if post_counts else None, "post_count": post_counts[3] if post_counts else 0 } if post_counts else None, "most_mentioned": { "user_id": mention_counts[0] if mention_counts else None, "username": mention_counts[1] if mention_counts else None, "full_name": mention_counts[2] if mention_counts else None, "mention_count": mention_counts[3] if mention_counts else 0 } if mention_counts else None, "biggest_vlogger": { "user_id": vlog_counts[0] if vlog_counts else None, "username": vlog_counts[1] if vlog_counts else None, "full_name": vlog_counts[2] if vlog_counts else None, "vlog_count": vlog_counts[3] if vlog_counts else 0 } if vlog_counts else None, "photo_addict": { "user_id": album_counts[0] if album_counts else None, "username": album_counts[1] if album_counts else None, "full_name": album_counts[2] if album_counts else None, "album_count": album_counts[3] if album_counts else 0 } if album_counts else None, "event_organizer": { "user_id": event_counts[0] if event_counts else None, "username": event_counts[1] if event_counts else None, "full_name": event_counts[2] if event_counts else None, "event_count": event_counts[3] if event_counts else 0 } if event_counts else None, "most_viewed_vlog": { "id": most_viewed_vlog.id, "title": most_viewed_vlog.title, "author_name": most_viewed_vlog.author.full_name, "views_count": most_viewed_vlog.views_count } if most_viewed_vlog else None } @router.get("/user/{user_id}") async def get_user_stats( user_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user) ): """Get statistics for a specific user.""" user = db.query(User).filter(User.id == user_id).first() if not user: return {"error": "User not found"} posts_count = db.query(Post).filter(Post.author_id == user_id).count() vlogs_count = db.query(Vlog).filter(Vlog.author_id == user_id).count() albums_count = db.query(Album).filter(Album.creator_id == user_id).count() events_created = db.query(Event).filter(Event.creator_id == user_id).count() # Get participation stats participations = db.query(EventParticipation).filter(EventParticipation.user_id == user_id).all() present_count = sum(1 for p in participations if p.status == ParticipationStatus.PRESENT) absent_count = sum(1 for p in participations if p.status == ParticipationStatus.ABSENT) maybe_count = sum(1 for p in participations if p.status == ParticipationStatus.MAYBE) # Total views on vlogs total_vlog_views = db.query(func.sum(Vlog.views_count)).filter(Vlog.author_id == user_id).scalar() or 0 return { "user": { "id": user.id, "username": user.username, "full_name": user.full_name, "avatar_url": user.avatar_url, "attendance_rate": user.attendance_rate, "member_since": user.created_at }, "content_stats": { "posts_count": posts_count, "vlogs_count": vlogs_count, "albums_count": albums_count, "events_created": events_created, "total_vlog_views": total_vlog_views }, "participation_stats": { "total_events": len(participations), "present_count": present_count, "absent_count": absent_count, "maybe_count": maybe_count } } @router.get("/activity/user/{user_id}") async def get_user_activity( user_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user) ): """Get recent activity for a specific user.""" user = db.query(User).filter(User.id == user_id).first() if not user: return {"error": "User not found"} # Get recent posts recent_posts = db.query(Post).filter( Post.author_id == user_id ).order_by(Post.created_at.desc()).limit(5).all() # Get recent vlogs recent_vlogs = db.query(Vlog).filter( Vlog.author_id == user_id ).order_by(Vlog.created_at.desc()).limit(5).all() # Get recent albums recent_albums = db.query(Album).filter( Album.creator_id == user_id ).order_by(Album.created_at.desc()).limit(5).all() # Get recent events created recent_events = db.query(Event).filter( Event.creator_id == user_id ).order_by(Event.created_at.desc()).limit(5).all() # Combine and sort by date activities = [] for post in recent_posts: activities.append({ "id": post.id, "type": "post", "description": f"A publié : {post.content[:50]}...", "created_at": post.created_at, "link": f"/posts/{post.id}" }) for vlog in recent_vlogs: activities.append({ "id": vlog.id, "type": "vlog", "description": f"A publié un vlog : {vlog.title}", "created_at": vlog.created_at, "link": f"/vlogs/{vlog.id}" }) for album in recent_albums: activities.append({ "id": album.id, "type": "album", "description": f"A créé un album : {album.title}", "created_at": album.created_at, "link": f"/albums/{album.id}" }) for event in recent_events: activities.append({ "id": event.id, "type": "event", "description": f"A créé un événement : {event.title}", "created_at": event.created_at, "link": f"/events/{event.id}" }) # Sort by creation date (most recent first) activities.sort(key=lambda x: x["created_at"], reverse=True) return { "activity": activities[:10] # Return top 10 most recent activities }