mod util;

use rspotify::{
    model::{AlbumId, AlbumType, ArtistId, Country, Market, PlaylistId, TrackId},
    prelude::*,
    ClientCredsSpotify,
};

use maybe_async::maybe_async;

use rspotify_model::SearchType;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::*;

/// Generating a new basic client for the requests.
#[maybe_async]
pub async fn creds_client() -> ClientCredsSpotify {
    let _ = env_logger::builder().is_test(true).try_init();
    let creds = util::get_credentials();
    let spotify = ClientCredsSpotify::new(creds);
    spotify.request_token().await.unwrap();
    spotify
}

#[maybe_async::test(
    feature = "__sync",
    async(all(feature = "__async", not(target_arch = "wasm32")), tokio::test),
    async(all(feature = "__async", target_arch = "wasm32"), wasm_bindgen_test)
)]
#[ignore = "Active premium subscription required for the owner of the app. See https://github.com/ramsayleung/rspotify/issues/550 for more information."]
async fn test_album() {
    let birdy_uri = AlbumId::from_uri("spotify:album:0sNOF9WDwhWunNAHPD3Baj").unwrap();
    creds_client().await.album(birdy_uri, None).await.unwrap();
}

#[maybe_async::test(
    feature = "__sync",
    async(all(feature = "__async", not(target_arch = "wasm32")), tokio::test),
    async(all(feature = "__async", target_arch = "wasm32"), wasm_bindgen_test)
)]
#[ignore = "Active premium subscription required for the owner of the app. See https://github.com/ramsayleung/rspotify/issues/550 for more information."]
async fn test_album_tracks() {
    let birdy_uri = AlbumId::from_uri("spotify:album:6akEvsycLGftJxYudPjmqK").unwrap();
    creds_client()
        .await
        .album_track_manual(birdy_uri, None, Some(2), None)
        .await
        .unwrap();
}

#[maybe_async::test(
    feature = "__sync",
    async(all(feature = "__async", not(target_arch = "wasm32")), tokio::test),
    async(all(feature = "__async", target_arch = "wasm32"), wasm_bindgen_test)
)]
#[ignore = "Active premium subscription required for the owner of the app. See https://github.com/ramsayleung/rspotify/issues/550 for more information."]
async fn test_artist() {
    let birdy_uri = ArtistId::from_uri("spotify:artist:2WX2uTcsvV5OnS0inACecP").unwrap();
    creds_client().await.artist(birdy_uri).await.unwrap();
}

#[maybe_async::test(
    feature = "__sync",
    async(all(feature = "__async", not(target_arch = "wasm32")), tokio::test),
    async(all(feature = "__async", target_arch = "wasm32"), wasm_bindgen_test)
)]
#[ignore = "Active premium subscription required for the owner of the app. See https://github.com/ramsayleung/rspotify/issues/550 for more information."]
async fn test_artists_albums() {
    let birdy_uri = ArtistId::from_uri("spotify:artist:2WX2uTcsvV5OnS0inACecP").unwrap();
    creds_client()
        .await
        .artist_albums_manual(
            birdy_uri,
            Some(AlbumType::Album),
            Some(Market::Country(Country::UnitedStates)),
            Some(10),
            None,
        )
        .await
        .unwrap();
}

#[maybe_async::test(
    feature = "__sync",
    async(all(feature = "__async", not(target_arch = "wasm32")), tokio::test),
    async(all(feature = "__async", target_arch = "wasm32"), wasm_bindgen_test)
)]
#[ignore = "Active premium subscription required for the owner of the app. See https://github.com/ramsayleung/rspotify/issues/550 for more information."]
async fn test_artists_albums_with_multiple_album_types() {
    let birdy_uri = ArtistId::from_uri("spotify:artist:0TnOYISbd1XYRBk9myaseg").unwrap();
    let include_groups = [
        AlbumType::Album,
        AlbumType::Single,
        AlbumType::Compilation,
        AlbumType::AppearsOn,
    ];
    creds_client()
        .await
        .artist_albums_manual(
            birdy_uri,
            include_groups,
            Some(Market::Country(Country::Spain)),
            Some(10),
            None,
        )
        .await
        .unwrap();
}

#[maybe_async::test(
    feature = "__sync",
    async(all(feature = "__async", not(target_arch = "wasm32")), tokio::test),
    async(all(feature = "__async", target_arch = "wasm32"), wasm_bindgen_test)
)]
#[ignore = "Active premium subscription required for the owner of the app. See https://github.com/ramsayleung/rspotify/issues/550 for more information."]
async fn test_artists_albums_with_zero_album_type() {
    let birdy_uri = ArtistId::from_uri("spotify:artist:2WX2uTcsvV5OnS0inACecP").unwrap();
    creds_client()
        .await
        .artist_albums_manual(
            birdy_uri,
            [],
            Some(Market::Country(Country::UnitedStates)),
            Some(10),
            None,
        )
        .await
        .unwrap();
}

#[maybe_async::test(
    feature = "__sync",
    async(all(feature = "__async", not(target_arch = "wasm32")), tokio::test),
    async(all(feature = "__async", target_arch = "wasm32"), wasm_bindgen_test)
)]
#[ignore = "Active premium subscription required for the owner of the app. See https://github.com/ramsayleung/rspotify/issues/550 for more information."]
async fn test_track() {
    let birdy_uri = TrackId::from_uri("spotify:track:6rqhFgbbKwnb9MLmUQDhG6").unwrap();
    creds_client().await.track(birdy_uri, None).await.unwrap();
}

#[maybe_async::test(
    feature = "__sync",
    async(all(feature = "__async", not(target_arch = "wasm32")), tokio::test),
    async(all(feature = "__async", target_arch = "wasm32"), wasm_bindgen_test)
)]
#[ignore = "Active premium subscription required for the owner of the app. See https://github.com/ramsayleung/rspotify/issues/550 for more information."]
async fn test_existing_playlist() {
    let playlist_id = PlaylistId::from_id("0fwsN3jhWKTbJ1J7cR7fgu").unwrap();
    creds_client()
        .await
        .playlist(playlist_id, None, None)
        .await
        .unwrap();
}

#[maybe_async::test(
    feature = "__sync",
    async(all(feature = "__async", not(target_arch = "wasm32")), tokio::test),
    async(all(feature = "__async", target_arch = "wasm32"), wasm_bindgen_test)
)]
#[ignore = "Active premium subscription required for the owner of the app. See https://github.com/ramsayleung/rspotify/issues/550 for more information."]
async fn test_fake_playlist() {
    let playlist_id = PlaylistId::from_id("fakeid").unwrap();
    let playlist = creds_client().await.playlist(playlist_id, None, None).await;
    assert!(playlist.is_err());
}

#[maybe_async::test(
    feature = "__sync",
    async(all(feature = "__async", not(target_arch = "wasm32")), tokio::test),
    async(all(feature = "__async", target_arch = "wasm32"), wasm_bindgen_test)
)]
#[ignore = "Active premium subscription required for the owner of the app. See https://github.com/ramsayleung/rspotify/issues/550 for more information."]
async fn test_search_album() {
    let query = "album:arrival artist:abba";
    creds_client()
        .await
        .search(query, SearchType::Album, None, None, Some(10), Some(0))
        .await
        .unwrap();
}

#[maybe_async::test(
    feature = "__sync",
    async(all(feature = "__async", not(target_arch = "wasm32")), tokio::test),
    async(all(feature = "__async", target_arch = "wasm32"), wasm_bindgen_test)
)]
#[ignore = "Active premium subscription required for the owner of the app. See https://github.com/ramsayleung/rspotify/issues/550 for more information."]
async fn test_search_multiple_types() {
    let query = "album:arrival artist:abba";
    creds_client()
        .await
        .search_multiple(
            query,
            vec![SearchType::Artist, SearchType::Album],
            None,
            None,
            Some(10),
            Some(0),
        )
        .await
        .unwrap();
}

pub mod test_pagination {
    use super::*;

    static ALBUM: &str = "spotify:album:2T7DdrOvsqOqU9bGTkjBYu";
    static SONG_NAMES: &[&str; 10] = &[
        "Human After All",
        "The Prime Time of Your Life",
        "Robot Rock",
        "Steam Machine",
        "Make Love",
        "The Brainwasher",
        "On / Off",
        "Television Rules the Nation",
        "Technologic",
        "Emotion",
    ];

    /// This test iterates a request of 10 items, with 5 requests of 2 items.
    #[cfg(feature = "__sync")]
    #[test]
    #[ignore = "Active premium subscription required for the owner of the app. See https://github.com/ramsayleung/rspotify/issues/550 for more information."]
    fn test_pagination_sync() {
        let mut client = creds_client();
        client.config.pagination_chunks = 2;
        let album = AlbumId::from_uri(ALBUM).unwrap();

        let names = client
            .album_track(album, None)
            .map(|track| track.unwrap().name)
            .collect::<Vec<_>>();

        assert_eq!(names, SONG_NAMES);
    }

    /// This test iterates a request of 10 items, with 5 requests of 2 items.
    #[cfg(feature = "__async")]
    #[cfg_attr(not(target_arch = "wasm32"), tokio::test)]
    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
    #[ignore = "Active premium subscription required for the owner of the app. See https://github.com/ramsayleung/rspotify/issues/550 for more information."]
    async fn test_pagination_async() {
        use futures_util::StreamExt;

        let mut client = creds_client().await;
        client.config.pagination_chunks = 2;
        let album = AlbumId::from_uri(ALBUM).unwrap();

        let names = client
            .album_track(album, None)
            .map(|track| track.unwrap().name)
            .collect::<Vec<_>>()
            .await;

        assert_eq!(names, SONG_NAMES);
    }
}
