from typing import Any, List, Optional from fastapi import APIRouter, Depends, HTTPException, status, Query from sqlalchemy.orm import Session from app.api.deps import get_db, get_current_active_user from app.models.user import User from app.schemas.playlist import ( Playlist, PlaylistCreate, PlaylistUpdate, PlaylistWithSongs, PlaylistSongAdd, PlaylistSongRemove ) from app.services.playlist import ( create_playlist, delete_playlist, get_playlist, get_playlists_by_user, get_public_playlists, update_playlist, add_song_to_playlist, remove_song_from_playlist ) from app.services.song import get_song router = APIRouter() @router.get("/", response_model=List[Playlist]) def read_playlists( db: Session = Depends(get_db), skip: int = 0, limit: int = 100, search: Optional[str] = Query(None, description="Search by playlist name"), current_user: User = Depends(get_current_active_user), ) -> Any: """ Retrieve user's playlists. """ playlists = get_playlists_by_user( db, user_id=current_user.id, skip=skip, limit=limit, search=search ) return playlists @router.get("/public", response_model=List[Playlist]) def read_public_playlists( db: Session = Depends(get_db), skip: int = 0, limit: int = 100, search: Optional[str] = Query(None, description="Search by playlist name"), ) -> Any: """ Retrieve public playlists. """ playlists = get_public_playlists(db, skip=skip, limit=limit, search=search) return playlists @router.post("/", response_model=Playlist) def create_new_playlist( *, db: Session = Depends(get_db), playlist_in: PlaylistCreate, current_user: User = Depends(get_current_active_user), ) -> Any: """ Create new playlist. """ playlist = create_playlist(db, obj_in=playlist_in, user_id=current_user.id) return playlist @router.get("/{playlist_id}", response_model=PlaylistWithSongs) def read_playlist( *, db: Session = Depends(get_db), playlist_id: int, current_user: Optional[User] = Depends(get_current_active_user), ) -> Any: """ Get playlist by ID with songs. """ playlist = get_playlist(db, playlist_id=playlist_id) if not playlist: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Playlist not found", ) # Check if user has access to the playlist if not playlist.is_public and playlist.user_id != current_user.id: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Not enough permissions to access this playlist", ) return playlist @router.put("/{playlist_id}", response_model=Playlist) def update_playlist_endpoint( *, db: Session = Depends(get_db), playlist_id: int, playlist_in: PlaylistUpdate, current_user: User = Depends(get_current_active_user), ) -> Any: """ Update a playlist. """ playlist = get_playlist(db, playlist_id=playlist_id) if not playlist: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Playlist not found", ) # Check if user owns the playlist if playlist.user_id != current_user.id: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Not enough permissions to modify this playlist", ) playlist = update_playlist(db, db_obj=playlist, obj_in=playlist_in) return playlist @router.delete("/{playlist_id}", status_code=status.HTTP_204_NO_CONTENT, response_model=None) def delete_playlist_endpoint( *, db: Session = Depends(get_db), playlist_id: int, current_user: User = Depends(get_current_active_user), ) -> Any: """ Delete a playlist. """ playlist = get_playlist(db, playlist_id=playlist_id) if not playlist: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Playlist not found", ) # Check if user owns the playlist if playlist.user_id != current_user.id: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Not enough permissions to delete this playlist", ) delete_playlist(db, id=playlist_id) return None @router.post("/{playlist_id}/songs", response_model=PlaylistWithSongs) def add_song_to_playlist_endpoint( *, db: Session = Depends(get_db), playlist_id: int, song_data: PlaylistSongAdd, current_user: User = Depends(get_current_active_user), ) -> Any: """ Add a song to a playlist. """ playlist = get_playlist(db, playlist_id=playlist_id) if not playlist: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Playlist not found", ) # Check if user owns the playlist if playlist.user_id != current_user.id: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Not enough permissions to modify this playlist", ) # Check if song exists song = get_song(db, song_id=song_data.song_id) if not song: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Song not found", ) playlist = add_song_to_playlist(db, playlist_id=playlist_id, song_id=song_data.song_id) return playlist @router.delete("/{playlist_id}/songs", response_model=PlaylistWithSongs) def remove_song_from_playlist_endpoint( *, db: Session = Depends(get_db), playlist_id: int, song_data: PlaylistSongRemove, current_user: User = Depends(get_current_active_user), ) -> Any: """ Remove a song from a playlist. """ playlist = get_playlist(db, playlist_id=playlist_id) if not playlist: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Playlist not found", ) # Check if user owns the playlist if playlist.user_id != current_user.id: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Not enough permissions to modify this playlist", ) playlist = remove_song_from_playlist(db, playlist_id=playlist_id, song_id=song_data.song_id) return playlist