//! Spotify API response parsers.

use serde_json::Value;

use crate::{Album, Artist, Playlist, PlaybackState, Track};

pub fn parse_track(v: &Value) -> Option<Track> {
    let id = v["id"].as_str()?.to_string();
    if id.is_empty() {
        return None;
    }
    let name = v["name"].as_str().unwrap_or("Unknown").to_string();
    let artists = v["artists"]
        .as_array()
        .map(|a| {
            a.iter()
                .filter_map(|x| x["name"].as_str())
                .collect::<Vec<_>>()
                .join(", ")
        })
        .unwrap_or_default();
    let artist_ids = v["artists"]
        .as_array()
        .map(|a| {
            a.iter()
                .filter_map(|x| x["id"].as_str().map(|s| s.to_string()))
                .collect()
        })
        .unwrap_or_default();
    let album = v["album"]["name"].as_str().unwrap_or("").to_string();
    let album_id = v["album"]["id"].as_str().unwrap_or("").to_string();
    let duration_ms = v["duration_ms"].as_u64().unwrap_or(0);
    let uri = v["uri"].as_str().unwrap_or("").to_string();
    let album_art = v["album"]["images"]
        .as_array()
        .and_then(|images| images.first())
        .and_then(|image| image["url"].as_str())
        .unwrap_or("")
        .to_string();
    Some(Track { id, name, artists, artist_ids, album, album_id, duration_ms, uri, album_art, added_at: None })
}

pub fn parse_playlist(v: &Value) -> Option<Playlist> {
    let id = v["id"].as_str()?.to_string();
    if id.is_empty() { return None; }
    let name = v["name"].as_str().unwrap_or("Untitled").to_string();
    // Spotify currently returns `items: { href, total }` from /me/playlists
    // for this account, while older docs/examples use `tracks.total`.
    // Support both shapes so the library sidebar does not show false 0 counts.
    let tracks = v["tracks"]["total"]
        .as_u64()
        .or_else(|| v["items"]["total"].as_u64())
        .or_else(|| v["tracks"]["items"].as_array().map(|a| a.len() as u64))
        .or_else(|| v["items"].as_array().map(|a| a.len() as u64))
        .unwrap_or(0) as u32;
    let owner = v["owner"]["display_name"]
        .as_str()
        .or_else(|| v["owner"]["id"].as_str())
        .unwrap_or("")
        .to_string();
    let uri = v["uri"].as_str().unwrap_or("").to_string();
    Some(Playlist { id, name, tracks, owner, uri })
}

pub fn parse_artist(v: &Value) -> Option<Artist> {
    let id = v["id"].as_str()?.to_string();
    if id.is_empty() { return None; }
    let name = v["name"].as_str().unwrap_or("Unknown").to_string();
    let followers = v["followers"]["total"].as_u64().unwrap_or(0) as u32;
    let uri = v["uri"].as_str().unwrap_or("").to_string();
    let image = String::new();
    Some(Artist { id, name, followers, uri, image })
}

pub fn parse_album(v: &Value) -> Option<Album> {
    let id = v["id"].as_str()?.to_string();
    if id.is_empty() { return None; }
    let name = v["name"].as_str().unwrap_or("Untitled").to_string();
    let artists = v["artists"]
        .as_array()
        .map(|a| {
            a.iter()
                .filter_map(|x| x["name"].as_str())
                .collect::<Vec<_>>()
                .join(", ")
        })
        .unwrap_or_default();
    let tracks = v["total_tracks"].as_u64().unwrap_or(0) as u32;
    let uri = v["uri"].as_str().unwrap_or("").to_string();
    let image = v["images"]
        .as_array()
        .and_then(|images| images.first())
        .and_then(|image| image["url"].as_str())
        .unwrap_or("")
        .to_string();
    Some(Album { id, name, artists, tracks, uri, image })
}

pub fn parse_playback(v: &Value) -> PlaybackState {
    let track = parse_track(&v["item"]);
    PlaybackState {
        is_playing: v["is_playing"].as_bool().unwrap_or(false),
        progress_ms: v["progress_ms"].as_u64().unwrap_or(0),
        duration_ms: track
            .as_ref()
            .map(|t| t.duration_ms)
            .unwrap_or_else(|| v["item"]["duration_ms"].as_u64().unwrap_or(0)),
        shuffle_state: v["shuffle_state"].as_bool().unwrap_or(false),
        repeat_state: v["repeat_state"].as_str().unwrap_or("off").to_string(),
        volume_percent: v["device"]["volume_percent"].as_u64().unwrap_or(100) as u32,
        device_name: v["device"]["name"].as_str().unwrap_or("").to_string(),
        device_id: v["device"]["id"].as_str().unwrap_or("").to_string(),
        track,
    }
}