from typing import List, Optional from fastapi import APIRouter, Depends, HTTPException, Query from sqlmodel import Session, select, col from sqlalchemy.orm import selectinload from database import get_session from models import Show, Song, Venue, Tour, User, Group, Performance, PerformanceNickname, Comment, Review from schemas import ShowRead, SongRead, VenueRead, TourRead, UserRead, GroupRead router = APIRouter(prefix="/search", tags=["search"]) @router.get("/") def global_search( q: str, session: Session = Depends(get_session), limit: int = 5 ): if len(q) < 2: return {} q_str = f"%{q}%" # Search Songs songs = session.exec( select(Song) .where(col(Song.title).ilike(q_str)) .limit(limit) ).all() # Search Venues venues = session.exec( select(Venue) .where(col(Venue.name).ilike(q_str)) .limit(limit) ).all() # Search Tours tours = session.exec( select(Tour) .where(col(Tour.name).ilike(q_str)) .limit(limit) ).all() # Search Groups groups = session.exec( select(Group) .where(col(Group.name).ilike(q_str)) .limit(limit) ).all() # Search Users (by email or profile username) users = session.exec( select(User) .where(col(User.email).ilike(q_str)) .limit(limit) ).all() # Also search Profiles for username matches from models import Profile profile_matches = session.exec( select(Profile) .where(col(Profile.username).ilike(q_str)) .limit(limit) ).all() # Add unique users from profile matches existing_user_ids = {u.id for u in users} for p in profile_matches: if p.user_id not in existing_user_ids: user = session.get(User, p.user_id) if user: users.append(user) existing_user_ids.add(user.id) # Search Nicknames nicknames = session.exec( select(PerformanceNickname) .options(selectinload(PerformanceNickname.performance).selectinload(Performance.song)) .where(col(PerformanceNickname.nickname).ilike(q_str)) .where(PerformanceNickname.status == "approved") .limit(limit) ).all() # Search Performances performances = session.exec( select(Performance) .options(selectinload(Performance.song), selectinload(Performance.show)) .where(col(Performance.notes).ilike(q_str)) .limit(limit) ).all() # Search Reviews reviews = session.exec( select(Review) .where( (col(Review.blurb).ilike(q_str)) | (col(Review.content).ilike(q_str)) ) .limit(limit) ).all() # Search Comments comments = session.exec( select(Comment) .where(col(Comment.content).ilike(q_str)) .limit(limit) ).all() return { "songs": songs, "venues": venues, "tours": tours, "groups": groups, "users": users, "nicknames": nicknames, "performances": performances, "reviews": reviews, "comments": comments }