package com.fabledsword.minstrel.models.wire

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

/**
 * Wire shape of one playlist as returned by `/api/playlists` and
 * `/api/playlists/{id}`. Mirrors `internal/api/playlists.go Playlist`.
 *
 * All string fields default to empty so missing keys don't throw.
 * `systemVariant` is nullable — non-null means a system-generated mix.
 */
@Serializable
data class PlaylistWire(
    val id: String,
    @SerialName("user_id") val userId: String = "",
    val name: String = "",
    val description: String = "",
    @SerialName("is_public") val isPublic: Boolean = false,
    @SerialName("system_variant") val systemVariant: String? = null,
    @SerialName("track_count") val trackCount: Int = 0,
    @SerialName("cover_url") val coverUrl: String = "",
    @SerialName("owner_username") val ownerUsername: String = "",
    @SerialName("created_at") val createdAt: String = "",
    @SerialName("updated_at") val updatedAt: String = "",
)

/**
 * `GET /api/playlists?kind=user|system|all` envelope. Server splits
 * the caller's own playlists from public ones owned by others; both
 * are surfaced to the UI as separate sections.
 */
@Serializable
data class PlaylistsListWire(
    val owned: List<PlaylistWire> = emptyList(),
    val public: List<PlaylistWire> = emptyList(),
)

/**
 * One row inside a `PlaylistDetailWire.tracks`. `trackId` / `albumId`
 * / `artistId` / `streamUrl` are nullable because the upstream track
 * may have been removed from the library while the row stays in the
 * playlist with its display fields preserved.
 */
@Serializable
data class PlaylistTrackWire(
    val position: Int = 0,
    @SerialName("track_id") val trackId: String? = null,
    val title: String = "",
    @SerialName("album_id") val albumId: String? = null,
    @SerialName("album_title") val albumTitle: String = "",
    @SerialName("artist_id") val artistId: String? = null,
    @SerialName("artist_name") val artistName: String = "",
    @SerialName("duration_sec") val durationSec: Int = 0,
    @SerialName("stream_url") val streamUrl: String? = null,
)

/**
 * `GET /api/playlists/{id}` envelope. Server flattens the playlist
 * fields at the root level and adds a `tracks` array — matches the
 * Flutter fromJson which calls `Playlist.fromJson(j)` on the same map
 * that owns `tracks`.
 */
@Serializable
data class PlaylistDetailWire(
    val id: String,
    @SerialName("user_id") val userId: String = "",
    val name: String = "",
    val description: String = "",
    @SerialName("is_public") val isPublic: Boolean = false,
    @SerialName("system_variant") val systemVariant: String? = null,
    @SerialName("track_count") val trackCount: Int = 0,
    @SerialName("cover_url") val coverUrl: String = "",
    @SerialName("owner_username") val ownerUsername: String = "",
    val tracks: List<PlaylistTrackWire> = emptyList(),
)
