from typing import List from fastapi import APIRouter, Depends, HTTPException, Query from sqlmodel import Session, select from database import get_session from models import Show, Tag, EntityTag from schemas import ShowCreate, ShowRead, ShowUpdate, TagRead from auth import get_current_user router = APIRouter(prefix="/shows", tags=["shows"]) @router.post("/", response_model=ShowRead) def create_show(show: ShowCreate, session: Session = Depends(get_session), current_user = Depends(get_current_user)): db_show = Show.model_validate(show) session.add(db_show) session.commit() session.refresh(db_show) return db_show @router.get("/", response_model=List[ShowRead]) def read_shows( offset: int = 0, limit: int = Query(default=2000, le=5000), venue_id: int = None, tour_id: int = None, year: int = None, session: Session = Depends(get_session) ): query = select(Show) if venue_id: query = query.where(Show.venue_id == venue_id) if tour_id: query = query.where(Show.tour_id == tour_id) if year: from sqlalchemy import extract query = query.where(extract('year', Show.date) == year) shows = session.exec(query.offset(offset).limit(limit)).all() return shows @router.get("/recent", response_model=List[ShowRead]) def read_recent_shows( limit: int = Query(default=10, le=50), session: Session = Depends(get_session) ): """Get the most recent shows ordered by date descending""" from datetime import datetime query = select(Show).where(Show.date <= datetime.now()).order_by(Show.date.desc()).limit(limit) shows = session.exec(query).all() return shows @router.get("/{show_id}", response_model=ShowRead) def read_show(show_id: int, session: Session = Depends(get_session)): show = session.get(Show, show_id) if not show: raise HTTPException(status_code=404, detail="Show not found") tags = session.exec( select(Tag) .join(EntityTag, Tag.id == EntityTag.tag_id) .where(EntityTag.entity_type == "show") .where(EntityTag.entity_id == show_id) ).all() # Manually populate performances to ensure nicknames are filtered if needed # (Though for now we just return all, or filter approved in schema if we had a custom getter) # The relationship `show.performances` is already loaded if we access it, but we might want to sort. # Re-fetch show with relationships if needed, or just rely on lazy loading + validation # But for nicknames, we only want "approved" ones usually. # Let's let the frontend filter or do it here. # Doing it here is safer. show_data = ShowRead.model_validate(show) show_data.tags = tags # Sort performances by position sorted_perfs = sorted(show.performances, key=lambda p: p.position) # Filter nicknames for each performance for perf in sorted_perfs: perf.nicknames = [n for n in perf.nicknames if n.status == "approved"] show_data.performances = sorted_perfs return show_data @router.patch("/{show_id}", response_model=ShowRead) def update_show(show_id: int, show: ShowUpdate, session: Session = Depends(get_session), current_user = Depends(get_current_user)): db_show = session.get(Show, show_id) if not db_show: raise HTTPException(status_code=404, detail="Show not found") show_data = show.model_dump(exclude_unset=True) db_show.sqlmodel_update(show_data) session.add(db_show) session.commit() session.refresh(db_show) return db_show