"""Wire schemas for the discovery API: requests and streamed events."""

from typing import Literal

from pydantic import BaseModel, Field

NDJSON_CONTENT_TYPE = "application/x-ndjson"


class HistoryTurn(BaseModel):
    """One prior chat turn; conversation state lives client-side."""

    role: Literal["user", "assistant"]
    content: str = Field(min_length=1, max_length=2000)


class PriorRecommendation(BaseModel):
    """A track from an earlier response that follow-up turns can refer to."""

    rank: int = Field(ge=1, le=50)
    track_id: str
    title: str
    artists: list[str] = Field(max_length=10)


class RecommendationRequest(BaseModel):
    """A discovery query with bounded client-side conversation state."""

    schema_version: Literal[1] = 1
    query: str = Field(min_length=1, max_length=1000)
    history: list[HistoryTurn] = Field(default_factory=list, max_length=12)
    prior_recommendations: list[PriorRecommendation] = Field(default_factory=list, max_length=50)


class TrackCard(BaseModel):
    """The wire shape of one recommended track."""

    id: str
    uri: str
    title: str
    artists: list[str]
    album_name: str
    album_art_url: str | None
    external_url: str | None


class MetadataEvent(BaseModel):
    """First stream event: how the query was understood."""

    type: Literal["metadata"] = "metadata"
    request_id: str
    intent_summary: str
    candidate_count: int


class TrackEvent(BaseModel):
    """One recommended track, streamed as soon as it validates."""

    type: Literal["track"] = "track"
    rank: int
    track: TrackCard
    justification: str


class WarningEvent(BaseModel):
    """A non-fatal degradation, surfaced honestly instead of hidden."""

    type: Literal["warning"] = "warning"
    code: str
    message: str


class ErrorEvent(BaseModel):
    """A terminal failure; no further events follow it."""

    type: Literal["error"] = "error"
    code: str
    message: str


class DoneEvent(BaseModel):
    """Final stream event with response-level counters."""

    type: Literal["done"] = "done"
    track_count: int
    total_ms: int


StreamEvent = MetadataEvent | TrackEvent | WarningEvent | ErrorEvent | DoneEvent


class PlaylistCreateRequest(BaseModel):
    """A request to save recommended tracks as a real Spotify playlist."""

    schema_version: Literal[1] = 1
    name: str = Field(min_length=1, max_length=100)
    track_uris: list[str] = Field(min_length=1, max_length=50)


class PlaylistCreateResponse(BaseModel):
    """The created playlist's public location."""

    url: str
