package io.delphiplatform.api.integration;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import java.time.LocalDate;
import java.util.List;
import java.util.Map;

import io.delphiplatform.api.integration.annotation.BigTable;
import io.delphiplatform.api.integration.annotation.SqlScript;
import io.delphiplatform.api.integration.dto.PublicPlaylistPositionCountryDto;
import io.delphiplatform.api.integration.manager.TestBigtableManager.TrackPositionsReqParamsSet;
import io.delphiplatform.api.integration.model.PublicPlaylistTrackPositionAdditionModel;
import io.delphiplatform.api.integration.model.PublicPlaylistTrackPositionAdditionsModel;
import io.delphiplatform.api.v3.model.IncludeTracklistPlaylist;

import static io.delphiplatform.api.v3.constant.DspConstants.SPOTIFY;

public class TrackPositionsPlaylistsAdditionsPublicIT extends BaseIT {

    /**
     * Check that positions are differentiated by country code for Apple.
     * <p>
     * There are 2 similar positions on current date in same playlist for US and CA. Only CA is returned since US one also existed before current
     * date and thus is not an 'addition'
     */
    @Test
    @SqlScript(scripts = "/scripts/TrackPositionsPlaylistsAdditionsPublicIT/getPublicTrackPositionsPlaylistsAdditions_apple_countries.sql")
    @BigTable(table = "playlist_tracks", json =
        "/scripts/TrackPositionsPlaylistsAdditionsPublicIT/BT_playlist_tracks_getPublicTrackPositionsPlaylistsAdditions_apple_countries.json")
    @BigTable(table = "playlists", json = "/scripts/BT_empty.json")
    public void getPublicTrackPositionsPlaylistsAdditions_apple_countries() {
        LocalDate dateCurrent = LocalDate.parse("2022-05-16");

        String isrc1 = "USQX91901111";
        String playlistId1 = "apple_1";

        String countryCodeCA = "ca";

        ResponseEntity<PublicPlaylistTrackPositionAdditionsModel> response = apiClient.sendAPIRequest(
            "/v3/public/track-positions/playlists/additions?"
                + "start_date=" + dateCurrent
                + "&end_date=" + dateCurrent
                + "&isrc=" + isrc1
                + "&include=" + String.format("%s",
                IncludeTracklistPlaylist.PLAYLISTS.getValue()),
            PublicPlaylistTrackPositionAdditionsModel.class
        );

        Assertions.assertEquals(HttpStatus.OK, response.getStatusCode());

        //1 item expected - country = CA, US not returned since it existed on prev. day

        Assertions.assertEquals(1, response.getBody().getCount());

        List<PublicPlaylistTrackPositionAdditionModel> additions = response.getBody().getItems();

        PublicPlaylistTrackPositionAdditionModel additionCA = additions.stream()
            .filter(add -> countryCodeCA.equals(add.getPlaylist().getCountryCode()))
            .findFirst().orElse(null);

        Assertions.assertNotNull(additionCA);

        Assertions.assertEquals(playlistId1, additionCA.getPlaylistId());
        Assertions.assertEquals(isrc1, additionCA.getIsrc());

        Assertions.assertEquals(playlistId1, additionCA.getPlaylist().getPlaylistId());
    }

    /**
     * Check that positions are NOT differentiated by country code for Spotify.
     * <p>
     * There are 2 similar positions on current date and prev. date - in same playlist but with different countries - US and UNKNOWN. Nothing is
     * returned since same position existed before current date and thus is not an 'addition', despite having different countries between 2 dates
     */
    @Test
    @SqlScript(scripts = "/scripts/TrackPositionsPlaylistsAdditionsPublicIT/getPublicTrackPositionsPlaylistsAdditions_spotiy_countries.sql")
    @BigTable(table = "playlist_tracks", json =
        "/scripts/TrackPositionsPlaylistsAdditionsPublicIT/BT_playlist_tracks_getPublicTrackPositionsPlaylistsAdditions_spotiy_countries.json")
    @BigTable(table = "playlists", json = "/scripts/BT_empty.json")
    public void getPublicTrackPositionsPlaylistsAdditions_spotiy_countries() {
        LocalDate dateBeforeCurrent = LocalDate.parse("2022-05-15");
        LocalDate dateCurrent = LocalDate.parse("2022-05-16");

        String isrc1 = "USQX91901111";

        String playlistId1 = "spotify_1";

        String countryCodeUS = "us";
        String countryCodeUnknown = "unknown";

        String dspTrackId1 = "dspTrackId1";

        int currentPositionUS = 1;

        //CASE 1
        //pos. in country 'unknown' playlist on current date

        ResponseEntity<PublicPlaylistTrackPositionAdditionsModel> response1 = apiClient.sendAPIRequest(
            "/v3/public/track-positions/playlists/additions?"
                + "start_date=" + dateCurrent
                + "&end_date=" + dateCurrent
                + "&isrc=" + isrc1
                + "&include=" + String.format("%s",
                IncludeTracklistPlaylist.PLAYLISTS.getValue()),
            PublicPlaylistTrackPositionAdditionsModel.class
        );

        Assertions.assertEquals(HttpStatus.OK, response1.getStatusCode());

        //1 item expected - only one existing for now, country = unknown

        Assertions.assertEquals(1, response1.getBody().getCount());

        List<PublicPlaylistTrackPositionAdditionModel> additions = response1.getBody().getItems();

        PublicPlaylistTrackPositionAdditionModel additionUnknown = additions.stream()
            .filter(add -> countryCodeUnknown.equals(add.getPlaylist().getCountryCode()))
            .findFirst().orElse(null);

        Assertions.assertNotNull(additionUnknown);

        Assertions.assertEquals(playlistId1, additionUnknown.getPlaylistId());
        Assertions.assertEquals(isrc1, additionUnknown.getIsrc());

        Assertions.assertEquals(playlistId1, additionUnknown.getPlaylist().getPlaylistId());

        //CASE 2

        //now create pos. in US playlist on date before current
        bigtableManager.createPlaylistPublicTrackPosition(TrackPositionsReqParamsSet.BY_ISRC, dateBeforeCurrent, SPOTIFY, playlistId1, isrc1,
            Map.of(
                countryCodeUS,
                PublicPlaylistPositionCountryDto.builder()
                    .trackId(dspTrackId1)
                    .currentPosition(currentPositionUS)
                    .build()
            ),
            Map.of(countryCodeUS, Map.of(
                (long) currentPositionUS, dspTrackId1
            ))
        );

        ResponseEntity<PublicPlaylistTrackPositionAdditionsModel> response2 = apiClient.sendAPIRequest(
            "/v3/public/track-positions/playlists/additions?"
                + "start_date=" + dateCurrent
                + "&end_date=" + dateCurrent
                + "&isrc=" + isrc1
                + "&include=" + String.format("%s",
                IncludeTracklistPlaylist.PLAYLISTS.getValue()),
            PublicPlaylistTrackPositionAdditionsModel.class
        );

        Assertions.assertEquals(HttpStatus.OK, response2.getStatusCode());

        //now 0 items expected since there is 2nd similar position at date before current and thus item returned in case 1 is not
        // an 'addition' anymore. Despite that 2 items are on different countries playlists (unknown and US)

        Assertions.assertEquals(0, response2.getBody().getCount());
    }
}
