package com.fabledsword.minstrel.api.endpoints

import com.fabledsword.minstrel.models.wire.ListenBrainzStatusWire
import com.fabledsword.minstrel.models.wire.MyProfileWire
import com.fabledsword.minstrel.models.wire.SystemPlaylistsStatusWire
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.PUT

/**
 * Retrofit interface for the `/api/me` endpoints — caller-scoped account endpoints.
 * Mirrors the relevant slice of `flutter_client/lib/api/endpoints/settings.dart`.
 *
 * History + timezone + system-playlists-status live under /api/me too
 * but are handled by their respective feature repositories; this
 * interface only carries the profile + password slice.
 */
interface MeApi {
    @GET("api/me")
    suspend fun getProfile(): MyProfileWire

    /**
     * Pass only the fields you want to change; server merges. Returns
     * the canonical post-update row so the caller can refresh local
     * state without an extra GET.
     */
    @PUT("api/me/profile")
    suspend fun updateProfile(@Body body: UpdateProfileRequest): MyProfileWire

    /**
     * Change the caller's password. Server validates `current_password`
     * before accepting `new_password`. No body on success (204).
     */
    @PUT("api/me/password")
    suspend fun changePassword(@Body body: ChangePasswordRequest)

    /**
     * Caller's ListenBrainz state — never returns the token itself,
     * only whether one is stored, whether scrobbling is enabled, and
     * the last successful scrobble timestamp (RFC3339 string or null).
     */
    @GET("api/me/listenbrainz")
    suspend fun getListenBrainz(): ListenBrainzStatusWire

    /**
     * Caller's most recent system-playlist build state. Drives the
     * Home placeholder cards (building / failed / pending / seed-needed)
     * for system playlists that haven't generated yet.
     */
    @GET("api/me/system-playlists-status")
    suspend fun getSystemPlaylistsStatus(): SystemPlaylistsStatusWire

    /**
     * PUT against the same `/api/me/listenbrainz` endpoint with one
     * of two shapes — `{token: ...}` stashes a new token,
     * `{enabled: ...}` flips the scrobble switch. Server returns the
     * post-write status so callers refresh without a separate GET.
     */
    @PUT("api/me/listenbrainz")
    suspend fun setListenBrainz(@Body body: ListenBrainzPutBody): ListenBrainzStatusWire
}

/**
 * Body for `PUT /api/me/profile`. Pass only the fields you want to
 * change; the server merges — empty strings clear, nulls leave
 * existing values alone.
 */
@Serializable
data class UpdateProfileRequest(
    @SerialName("display_name") val displayName: String? = null,
    val email: String? = null,
)

/**
 * Body for `PUT /api/me/password`. Both fields required.
 */
@Serializable
data class ChangePasswordRequest(
    @SerialName("current_password") val currentPassword: String,
    @SerialName("new_password") val newPassword: String,
)

/**
 * Body for `PUT /api/me/listenbrainz`. Either `token` or `enabled`
 * is set; the server treats other fields as untouched. Mirrors
 * Flutter's `setListenBrainzToken` / `setListenBrainzEnabled` split
 * over a single endpoint shape.
 */
@Serializable
data class ListenBrainzPutBody(
    val token: String? = null,
    val enabled: Boolean? = null,
)
