"""Storage analysis and cleanup endpoints.""" from typing import Any from fastapi import APIRouter from app.api.deps import ( AlbumRepoDep, ArtistRepoDep, CurrentUser, FileStorageDep, TrackRepoDep, ) from app.api.schemas.storage import ( DiskUsageOut, FormatBreakdownOut, GenreCountOut, StorageStatsOut, ) router = APIRouter(prefix="/storage", tags=["storage"]) # How many of the most common genres the dashboard surfaces. _TOP_GENRES = 8 @router.get("") async def get_storage_stats( track_repo: TrackRepoDep, artist_repo: ArtistRepoDep, album_repo: AlbumRepoDep, storage: FileStorageDep, _: CurrentUser, ) -> StorageStatsOut: """Library + disk statistics for the Storage dashboard (§A6). Aggregates come from the catalogue (cheap GROUP BYs); ``disk`` reflects the real backing volume and is ``None`` for backends without a fixed-capacity disk (e.g. object stores).""" stats = await track_repo.library_stats() total_artists = await artist_repo.count(q=None) total_albums = await album_repo.count(artist_id=None, q=None) genres = await track_repo.genres() disk = await storage.disk_usage() return StorageStatsOut( total_tracks=stats.total_tracks, total_artists=total_artists, total_albums=total_albums, total_size=stats.total_size, total_duration_seconds=stats.total_duration_seconds, largest_track_size=stats.largest_track_size, earliest_added=stats.earliest_added, latest_added=stats.latest_added, by_format=[ FormatBreakdownOut( file_format=f.file_format, track_count=f.track_count, total_size=f.total_size, ) for f in stats.by_format ], by_metadata_status=stats.by_metadata_status, by_source=stats.by_source, top_genres=[ GenreCountOut(genre=genre, track_count=count) for genre, count in genres[:_TOP_GENRES] ], disk=DiskUsageOut(total=disk.total, used=disk.used, free=disk.free) if disk else None, ) @router.get("/duplicates") async def get_duplicates() -> Any: ... @router.get("/broken") async def get_broken_files() -> Any: ... @router.get("/missing-metadata") async def get_missing_metadata() -> Any: ... @router.post("/cleanup") async def run_cleanup() -> Any: ...