"""Player API endpoints.""" from typing import Annotated, Any from fastapi import APIRouter, Depends, HTTPException, status from pydantic import BaseModel, Field from app.core.dependencies import get_current_active_user_flexible from app.core.logging import get_logger from app.models.user import User from app.services.player import PlayerMode, get_player_service logger = get_logger(__name__) router = APIRouter(prefix="/player", tags=["player"]) class SeekRequest(BaseModel): """Request model for seek operation.""" position_ms: int = Field(ge=0, description="Position in milliseconds") class VolumeRequest(BaseModel): """Request model for volume control.""" volume: int = Field(ge=0, le=100, description="Volume level (0-100)") class ModeRequest(BaseModel): """Request model for mode change.""" mode: PlayerMode = Field(description="Playback mode") @router.post("/play") async def play( current_user: Annotated[User, Depends(get_current_active_user_flexible)], # noqa: ARG001 ) -> dict[str, str]: """Play current sound.""" try: player = get_player_service() await player.play() return {"message": "Playback started"} except Exception as e: logger.exception("Error starting playback") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to start playback", ) from e @router.post("/play/{index}") async def play_at_index( index: int, current_user: Annotated[User, Depends(get_current_active_user_flexible)], # noqa: ARG001 ) -> dict[str, str]: """Play sound at specific index.""" try: player = get_player_service() await player.play(index) return {"message": f"Playing sound at index {index}"} except ValueError as e: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=str(e), ) from e except Exception as e: logger.exception("Error playing sound at index %s", index) raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to play sound", ) from e @router.post("/pause") async def pause( current_user: Annotated[User, Depends(get_current_active_user_flexible)], # noqa: ARG001 ) -> dict[str, str]: """Pause playback.""" try: player = get_player_service() await player.pause() return {"message": "Playback paused"} except Exception as e: logger.exception("Error pausing playback") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to pause playback", ) from e @router.post("/stop") async def stop( current_user: Annotated[User, Depends(get_current_active_user_flexible)], # noqa: ARG001 ) -> dict[str, str]: """Stop playback.""" try: player = get_player_service() await player.stop_playback() return {"message": "Playback stopped"} except Exception as e: logger.exception("Error stopping playback") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to stop playback", ) from e @router.post("/next") async def next_track( current_user: Annotated[User, Depends(get_current_active_user_flexible)], # noqa: ARG001 ) -> dict[str, str]: """Skip to next track.""" try: player = get_player_service() await player.next() return {"message": "Skipped to next track"} except Exception as e: logger.exception("Error skipping to next track") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to skip to next track", ) from e @router.post("/previous") async def previous_track( current_user: Annotated[User, Depends(get_current_active_user_flexible)], # noqa: ARG001 ) -> dict[str, str]: """Go to previous track.""" try: player = get_player_service() await player.previous() return {"message": "Went to previous track"} except Exception as e: logger.exception("Error going to previous track") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to go to previous track", ) from e @router.post("/seek") async def seek( request: SeekRequest, current_user: Annotated[User, Depends(get_current_active_user_flexible)], # noqa: ARG001 ) -> dict[str, str]: """Seek to specific position in current track.""" try: player = get_player_service() await player.seek(request.position_ms) return {"message": f"Seeked to position {request.position_ms}ms"} except Exception as e: logger.exception("Error seeking to position %s", request.position_ms) raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to seek", ) from e @router.post("/volume") async def set_volume( request: VolumeRequest, current_user: Annotated[User, Depends(get_current_active_user_flexible)], # noqa: ARG001 ) -> dict[str, str]: """Set playback volume.""" try: player = get_player_service() await player.set_volume(request.volume) return {"message": f"Volume set to {request.volume}"} except Exception as e: logger.exception("Error setting volume to %s", request.volume) raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to set volume", ) from e @router.post("/mode") async def set_mode( request: ModeRequest, current_user: Annotated[User, Depends(get_current_active_user_flexible)], # noqa: ARG001 ) -> dict[str, str]: """Set playback mode.""" try: player = get_player_service() await player.set_mode(request.mode) return {"message": f"Mode set to {request.mode.value}"} except Exception as e: logger.exception("Error setting mode to %s", request.mode) raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to set mode", ) from e @router.post("/reload-playlist") async def reload_playlist( current_user: Annotated[User, Depends(get_current_active_user_flexible)], # noqa: ARG001 ) -> dict[str, str]: """Reload current playlist.""" try: player = get_player_service() await player.reload_playlist() return {"message": "Playlist reloaded"} except Exception as e: logger.exception("Error reloading playlist") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to reload playlist", ) from e @router.get("/state") async def get_state( current_user: Annotated[User, Depends(get_current_active_user_flexible)], # noqa: ARG001 ) -> dict[str, Any]: """Get current player state.""" try: player = get_player_service() return player.get_state() except Exception as e: logger.exception("Error getting player state") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to get player state", ) from e