"""Track request/response schemas.""" import datetime as dt import uuid from pydantic import BaseModel, Field from app.api.schemas.download import DownloadJobOut class TrackOut(BaseModel): id: uuid.UUID title: str artist_id: uuid.UUID artist_name: str album_id: uuid.UUID | None album_title: str | None duration_seconds: int | None file_format: str | None file_size: int | None genre: str | None year: int | None track_number: int | None metadata_status: str metadata_error: str | None enriched_at: dt.datetime | None availability: str source: str has_cover: bool created_at: dt.datetime class TrackUpdate(BaseModel): title: str | None = None genre: str | None = None year: int | None = None class MetadataMatch(BaseModel): """One AcoustID candidate for the metadata editor's match picker (§A7).""" acoustid: str score: float recording_mbid: str | None release_group_mbid: str | None title: str | None artist: str | None album: str | None year: int | None class MetadataMatchesOut(BaseModel): items: list[MetadataMatch] class MetadataApply(BaseModel): """Manual edits / accepted match applied via ``PUT /tracks/{id}/metadata``. Sets ``metadata_status = manual`` (never overwritten by auto-enrichment).""" title: str | None = None artist_name: str | None = None album_title: str | None = None year: int | None = None genre: str | None = None track_number: int | None = None class RemoteTrackSave(BaseModel): """Save a remote browse hit (§A4 discover) as a library placeholder — ``availability="remote"``, no audio until first play (plan: Model C).""" source: str source_id: str = Field(min_length=1) title: str artist: str | None = None class MaterializeResponse(BaseModel): """Result of requesting that a placeholder track's audio be fetched. ``job`` is ``None`` when the track is already ``local`` — nothing to wait for, the caller can stream immediately. Otherwise it's the (new or already in-flight) job; poll ``GET /downloads/{job.id}`` until ``done``.""" track: TrackOut job: DownloadJobOut | None