"""Playlist management routes.""" from flask import Blueprint, jsonify, request from app.models.playlist import Playlist from app.models.sound import Sound from app.services.decorators import require_auth from app.services.music_player_service import music_player_service from app.services.logging_service import LoggingService logger = LoggingService.get_logger(__name__) bp = Blueprint("playlist", __name__) @bp.route("/", methods=["GET"]) @require_auth def get_playlists(): """Get all playlists.""" try: # Get system playlists and user playlists system_playlists = Playlist.find_system_playlists() user_playlists = [] # TODO: Add user-specific playlists when user auth is implemented playlists = system_playlists + user_playlists return jsonify({ "playlists": [playlist.to_dict() for playlist in playlists] }) except Exception as e: logger.error(f"Error getting playlists: {e}") return jsonify({"error": "Failed to get playlists"}), 500 @bp.route("/", methods=["GET"]) @require_auth def get_playlist(playlist_id): """Get a specific playlist with sounds.""" try: playlist = Playlist.query.get_or_404(playlist_id) return jsonify({"playlist": playlist.to_detailed_dict()}) except Exception as e: logger.error(f"Error getting playlist {playlist_id}: {e}") return jsonify({"error": "Failed to get playlist"}), 500 @bp.route("/", methods=["POST"]) @require_auth def create_playlist(): """Create a new playlist.""" try: data = request.get_json() name = data.get("name") description = data.get("description") genre = data.get("genre") if not name: return jsonify({"error": "Playlist name is required"}), 400 # Check if playlist with same name already exists existing = Playlist.find_by_name(name) if existing: return jsonify({"error": "Playlist with this name already exists"}), 400 playlist = Playlist.create_playlist( name=name, description=description, genre=genre, user_id=None, # System playlist for now is_deletable=True ) return jsonify({"playlist": playlist.to_dict()}), 201 except Exception as e: logger.error(f"Error creating playlist: {e}") return jsonify({"error": "Failed to create playlist"}), 500 @bp.route("/", methods=["PUT"]) @require_auth def update_playlist(playlist_id): """Update a playlist.""" try: playlist = Playlist.query.get_or_404(playlist_id) data = request.get_json() if "name" in data: playlist.name = data["name"] if "description" in data: playlist.description = data["description"] if "genre" in data: playlist.genre = data["genre"] playlist.save() return jsonify({"playlist": playlist.to_dict()}) except Exception as e: logger.error(f"Error updating playlist {playlist_id}: {e}") return jsonify({"error": "Failed to update playlist"}), 500 @bp.route("/", methods=["DELETE"]) @require_auth def delete_playlist(playlist_id): """Delete a playlist.""" try: playlist = Playlist.query.get_or_404(playlist_id) if not playlist.is_deletable: return jsonify({"error": "This playlist cannot be deleted"}), 400 # If this is the current playlist, clear it from the player current_playlist = Playlist.find_current_playlist() if current_playlist and current_playlist.id == playlist_id: # Set main playlist as current if it exists main_playlist = Playlist.find_main_playlist() if main_playlist: main_playlist.set_as_current() music_player_service.reload_current_playlist_if_modified(main_playlist.id) playlist.delete() return jsonify({"message": "Playlist deleted successfully"}) except Exception as e: logger.error(f"Error deleting playlist {playlist_id}: {e}") return jsonify({"error": "Failed to delete playlist"}), 500 @bp.route("//set-current", methods=["POST"]) @require_auth def set_current_playlist(playlist_id): """Set a playlist as the current one.""" try: playlist = Playlist.query.get_or_404(playlist_id) playlist.set_as_current() # Reload the playlist in the music player music_player_service.reload_current_playlist_if_modified(playlist_id) return jsonify({"message": "Playlist set as current"}) except Exception as e: logger.error(f"Error setting current playlist {playlist_id}: {e}") return jsonify({"error": "Failed to set current playlist"}), 500 @bp.route("//sounds", methods=["POST"]) @require_auth def add_sound_to_playlist(playlist_id): """Add a sound to a playlist.""" try: playlist = Playlist.query.get_or_404(playlist_id) data = request.get_json() sound_id = data.get("sound_id") order = data.get("order") if not sound_id: return jsonify({"error": "Sound ID is required"}), 400 # Verify sound exists sound = Sound.query.get_or_404(sound_id) # Add sound to playlist playlist_sound = playlist.add_sound(sound_id, order) # Reload playlist in music player if it's the current one music_player_service.reload_current_playlist_if_modified(playlist_id) return jsonify({ "message": "Sound added to playlist", "playlist_sound": { "sound_id": playlist_sound.sound_id, "order": playlist_sound.order } }), 201 except Exception as e: logger.error(f"Error adding sound to playlist {playlist_id}: {e}") return jsonify({"error": "Failed to add sound to playlist"}), 500 @bp.route("//sounds/", methods=["DELETE"]) @require_auth def remove_sound_from_playlist(playlist_id, sound_id): """Remove a sound from a playlist.""" try: playlist = Playlist.query.get_or_404(playlist_id) success = playlist.remove_sound(sound_id) if not success: return jsonify({"error": "Sound not found in playlist"}), 404 # Reload playlist in music player if it's the current one music_player_service.reload_current_playlist_if_modified(playlist_id) return jsonify({"message": "Sound removed from playlist"}) except Exception as e: logger.error(f"Error removing sound from playlist {playlist_id}: {e}") return jsonify({"error": "Failed to remove sound from playlist"}), 500 @bp.route("//sounds/reorder", methods=["PUT"]) @require_auth def reorder_playlist_sounds(playlist_id): """Reorder sounds in a playlist.""" try: playlist = Playlist.query.get_or_404(playlist_id) data = request.get_json() sound_orders = data.get("sound_orders", []) if not sound_orders: return jsonify({"error": "Sound orders are required"}), 400 # Validate sound_orders format for item in sound_orders: if not isinstance(item, dict) or "sound_id" not in item or "order" not in item: return jsonify({"error": "Invalid sound_orders format"}), 400 # Reorder sounds playlist.reorder_sounds(sound_orders) # Reload playlist in music player if it's the current one music_player_service.reload_current_playlist_if_modified(playlist_id) return jsonify({"message": "Playlist sounds reordered"}) except Exception as e: logger.error(f"Error reordering playlist sounds {playlist_id}: {e}") return jsonify({"error": "Failed to reorder playlist sounds"}), 500 @bp.route("//duplicate", methods=["POST"]) @require_auth def duplicate_playlist(playlist_id): """Duplicate a playlist.""" try: playlist = Playlist.query.get_or_404(playlist_id) data = request.get_json() new_name = data.get("name") if not new_name: return jsonify({"error": "New playlist name is required"}), 400 # Check if playlist with same name already exists existing = Playlist.find_by_name(new_name) if existing: return jsonify({"error": "Playlist with this name already exists"}), 400 new_playlist = playlist.duplicate(new_name) return jsonify({"playlist": new_playlist.to_dict()}), 201 except Exception as e: logger.error(f"Error duplicating playlist {playlist_id}: {e}") return jsonify({"error": "Failed to duplicate playlist"}), 500