"""Album endpoints.""" import uuid from typing import Any from fastapi import APIRouter, Query from app.api.deps import AlbumRepoDep, ArtistRepoDep, CurrentUser, TrackRepoDep from app.api.schemas.album import AlbumOut from app.api.schemas.pagination import PagedResponse from app.api.schemas.track import TrackOut from app.api.v1.tracks import _build_track_out from app.domain.entities.album import Album from app.domain.entities.track import Artist from app.domain.errors import NotFoundError router = APIRouter(prefix="/albums", tags=["albums"]) async def _build_album_out( albums: list[Album], artists: dict[uuid.UUID, Artist], track_counts: dict[uuid.UUID, int], ) -> list[AlbumOut]: return [ AlbumOut( id=a.id, title=a.title, artist_id=a.artist_id, artist_name=artists[a.artist_id].name if a.artist_id in artists else "Unknown Artist", year=a.year, track_count=track_counts.get(a.id, 0), created_at=a.created_at, ) for a in albums ] @router.get("") async def list_albums( album_repo: AlbumRepoDep, artist_repo: ArtistRepoDep, _: CurrentUser, artist_id: uuid.UUID | None = None, q: str | None = None, limit: int = Query(50, ge=1, le=200), offset: int = Query(0, ge=0), ) -> PagedResponse[AlbumOut]: albums = await album_repo.list(artist_id=artist_id, q=q, limit=limit, offset=offset) total = await album_repo.count(artist_id=artist_id, q=q) artist_ids = list({a.artist_id for a in albums}) artists = {a.id: a for a in await artist_repo.get_many(artist_ids)} track_counts = await album_repo.track_count_many([a.id for a in albums]) items = await _build_album_out(albums, artists, track_counts) return PagedResponse(items=items, total=total, limit=limit, offset=offset) @router.get("/{album_id}") async def get_album( album_id: uuid.UUID, album_repo: AlbumRepoDep, artist_repo: ArtistRepoDep, _: CurrentUser, ) -> AlbumOut: album = await album_repo.get_by_id(album_id) if album is None: raise NotFoundError(f"Album {album_id} not found.") artists = {a.id: a for a in await artist_repo.get_many([album.artist_id])} track_counts = await album_repo.track_count_many([album.id]) items = await _build_album_out([album], artists, track_counts) return items[0] @router.get("/{album_id}/tracks") async def get_album_tracks( album_id: uuid.UUID, track_repo: TrackRepoDep, artist_repo: ArtistRepoDep, album_repo: AlbumRepoDep, _: CurrentUser, limit: int = Query(50, ge=1, le=200), offset: int = Query(0, ge=0), ) -> PagedResponse[TrackOut]: album = await album_repo.get_by_id(album_id) if album is None: raise NotFoundError(f"Album {album_id} not found.") tracks = await track_repo.list( artist_id=None, album_id=album_id, q=None, sort_by="title", order="asc", limit=limit, offset=offset, ) total = await track_repo.count(artist_id=None, album_id=album_id, q=None) artist_ids = list({t.artist_id for t in tracks}) artists = {a.id: a for a in await artist_repo.get_many(artist_ids)} albums = {album.id: album} items = await _build_track_out(tracks, artists, albums) return PagedResponse(items=items, total=total, limit=limit, offset=offset) @router.get("/{album_id}/cover") async def get_album_cover(album_id: uuid.UUID, _: CurrentUser) -> Any: ...