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.time.LocalDateTime;
import java.util.List;

import io.delphiplatform.api.integration.annotation.BigTable;
import io.delphiplatform.api.integration.annotation.SqlScript;
import io.delphiplatform.api.integration.model.PublicPlaylistTrackPositionModel;
import io.delphiplatform.api.integration.model.PublicPlaylistTrackPositionsModel;
import io.delphiplatform.api.integration.util.MockCurrentDateService;
import io.delphiplatform.api.v3.model.IncludeTracklistPlaylist;
import io.delphiplatform.api.v3.model.PlaylistStreamingForPeriodsInfo;
import io.delphiplatform.api.v3.model.apple.AppleArtist;
import io.delphiplatform.api.v3.model.spotify.SpotifyArtist;

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

public class TrackPositionsPlaylistsPublicIT extends BaseIT {

    /**
     * All 3 DSPs are tested to return positions and include data
     */
    @Test
    @SqlScript(scripts = "/scripts/TrackPositionsPlaylistsPublicIT/common_test_data_set_1.sql")
    @BigTable(table = "playlists", json =
        "/scripts/TrackPositionsPlaylistsPublicIT/BT_playlists_getPublicTrackPositionsPlaylists_loadData_allDsps.json")
    @BigTable(table = "playlist_tracks", json =
        "/scripts/TrackPositionsPlaylistsPublicIT/BT_playlist_tracks_getPublicTrackPositionsPlaylists_loadData_allDsps.json")
    @BigTable(table = "spotify", json =
        "/scripts/TrackPositionsPlaylistsPublicIT/BT_spotify_getPublicTrackPositionsPlaylists_loadData_allDsps.json")
    @BigTable(table = "apple_music", json =
        "/scripts/TrackPositionsPlaylistsPublicIT/BT_apple_music_getPublicTrackPositionsPlaylists_loadData_allDsps.json")
    @BigTable(table = "amazon_music", json =
        "/scripts/TrackPositionsPlaylistsPublicIT/BT_amazon_music_getPublicTrackPositionsPlaylists_loadData_allDsps.json")
    public void getPublicTrackPositionsPlaylists_loadData_allDsps() {
        LocalDate date1 = LocalDate.parse("2022-05-15");
        String isrc1 = "USQX91901111";

        String playlistIdSpotify1 = "spotify_1";
        String playlistNameSpotify1 = "playlistNameSpotify1";

        String playlistIdApple1 = "apple_1";
        String playlistNameApple1 = "playlistNameApple1";

        String playlistIdAmazonChartmetricWithCountry1 = "amazon_1_us";
        String playlistIdAmazonDsp1 = "B000000001";
        String playlistNameAmazon1 = "playlistNameAmazon1";

        String countryCode1 = "us";

        int currentPositionSpotify1 = 1;
        int previousPositionSpotify1 = 2;

        int currentPositionApple1 = 3;
        int previousPositionApple1 = 4;

        int currentPositionAmazon1 = 5;
        int previousPositionAmazon1 = 6;

        String dspTrackIdSpotify1 = "dspTrackIdSpotify1";
        String dspTrackNameSpotify1 = "dspTrackNameSpotify1";
        String dspTrackArtistIdSpotify1 = "dspTrackArtistIdSpotify1";
        String dspTrackArtistNameSpotify1 = "dspTrackArtistNameSpotify1";

        String albumIdSpotify1 = "testAlbumIdSpotify1";
        String albumNameSpotify1 = "testAlbumNameSpotify1";
        LocalDate albumReleaseDateSpotify1 = LocalDate.parse("2022-05-01");

        String dspTrackIdApple1 = "dspTrackIdApple1";
        String dspTrackNameApple1 = "dspTrackNameApple1";
        String dspTrackArtistIdApple1 = "dspTrackArtistIdApple1";
        String dspTrackArtistNameApple1 = "dspTrackArtistNameApple1";

        String albumIdApple1 = "testAlbumIdApple1";
        String albumNameApple1 = "testAlbumNameApple1";
        LocalDate albumReleaseDateApple1 = LocalDate.parse("2022-05-03");

        String dspTrackIdAmazon1 = "BT00000001";
        String dspTrackIdAmazonWithPrefix1 = "amazon_BT00000001";
        String dspTrackNameAmazon1 = "dspTrackNameAmazon1";

        String grasTrackId1 = "GRAS_A10328E00000000001";
        String grasTrackName1 = "testGrasTrackName1";
        String grasTrackProductId1 = "testProductId1";

        long streamsCountSpotify1 = 444L;
        long streamsCountApple1 = 555L;
        long streamsCountAmazon1 = 666L;

        LocalDateTime earliestDateTimeSpotify1 = LocalDateTime.parse("2022-05-02T00:00:00");
        LocalDateTime lastAddedDateTimeSpotify1 = LocalDateTime.parse("2022-05-02T01:00:00");
        LocalDateTime latestDateTimeSpotify1 = LocalDateTime.parse("2022-05-02T02:00:00");
        int earliestPositionSpotify1 = 4;

        LocalDateTime earliestDateTimeApple1 = LocalDateTime.parse("2022-05-03T00:00:00");
        LocalDateTime lastAddedDateTimeApple1 = LocalDateTime.parse("2022-05-03T01:00:00");
        LocalDateTime latestDateTimeApple1 = LocalDateTime.parse("2022-05-03T02:00:00");
        int earliestPositionApple1 = 5;

        /* perform test call */
        ResponseEntity<PublicPlaylistTrackPositionsModel> response = apiClient.sendAPIRequest(
            "/v3/public/track-positions/playlists?"
                + "start_date=" + date1.minusDays(5)
                + "&end_date=" + date1.plusDays(2)
                + "&isrc=" + isrc1
                + "&include=" + String.format("%s,%s,%s,%s",
                IncludeTracklistPlaylist.STREAMS_FOR_PERIOD.getValue(),
                IncludeTracklistPlaylist.PLAYLISTS.getValue(),
                IncludeTracklistPlaylist.TRACK_INFO.getValue(),
                IncludeTracklistPlaylist.GRAS_TRACK_INFO.getValue())
                + "&streams_country_code=" + countryCode1,
            PublicPlaylistTrackPositionsModel.class
        );

        Assertions.assertEquals(HttpStatus.OK, response.getStatusCode());
        Assertions.assertEquals(3, response.getBody().getCount());

        List<PublicPlaylistTrackPositionModel> positions = response.getBody().getItems();

        //SPOTIFY position
        PublicPlaylistTrackPositionModel positionSpotify1 = positions.stream().filter(pos -> SPOTIFY.equals(pos.getDsp()))
            .findFirst().orElse(null);

        //position
        Assertions.assertNotNull(positionSpotify1);
        Assertions.assertEquals(date1, positionSpotify1.getDate());
        Assertions.assertEquals(SPOTIFY, positionSpotify1.getDsp());
        Assertions.assertEquals(playlistIdSpotify1, positionSpotify1.getPlaylistId());
        Assertions.assertEquals(isrc1, positionSpotify1.getIsrc());

        Assertions.assertEquals(dspTrackIdSpotify1, positionSpotify1.getDspTrackId());
        Assertions.assertEquals(currentPositionSpotify1, positionSpotify1.getCurrent());
        Assertions.assertEquals(previousPositionSpotify1, positionSpotify1.getPrevious());
        //other fields omitted

        //streams
        PlaylistStreamingForPeriodsInfo countryStreamingPeriodsInfoSpotify1 = positionSpotify1.getStreamingInfo().get(countryCode1);
        Assertions.assertNotNull(countryStreamingPeriodsInfoSpotify1);
        Assertions.assertEquals(streamsCountSpotify1, countryStreamingPeriodsInfoSpotify1.getPeriodFor1Day().getIsrcInPlaylist());
        Assertions.assertEquals(streamsCountSpotify1, countryStreamingPeriodsInfoSpotify1.getPeriodFor7Days().getIsrcInPlaylist());
        Assertions.assertEquals(streamsCountSpotify1, countryStreamingPeriodsInfoSpotify1.getPeriodFor14Days().getIsrcInPlaylist());
        //streams for 'playlist' omitted

        //playlist
        Assertions.assertNotNull(positionSpotify1.getPlaylist());
        Assertions.assertEquals(playlistIdSpotify1, positionSpotify1.getPlaylist().getPlaylistId());
        Assertions.assertEquals(playlistNameSpotify1, positionSpotify1.getPlaylist().getName());
        Assertions.assertEquals(countryCode1, positionSpotify1.getPlaylist().getCountryCode());
        //other fields omitted

        //GRAS track
        Assertions.assertNotNull(positionSpotify1.getTrack());
        Assertions.assertEquals(grasTrackId1, positionSpotify1.getTrack().getTrackId());
        Assertions.assertEquals(isrc1, positionSpotify1.getTrack().getIsrc());
        Assertions.assertEquals(grasTrackName1, positionSpotify1.getTrack().getName());
        Assertions.assertEquals(grasTrackProductId1, positionSpotify1.getTrack().getProduct().getProductId());

        //DSP track
        Assertions.assertNotNull(positionSpotify1.getSpotifyTrack());
        Assertions.assertEquals(dspTrackIdSpotify1, positionSpotify1.getSpotifyTrack().getTrackId());
        Assertions.assertEquals(dspTrackNameSpotify1, positionSpotify1.getSpotifyTrack().getName());
        Assertions.assertEquals(isrc1, positionSpotify1.getSpotifyTrack().getIsrc());

        Assertions.assertEquals(albumIdSpotify1, positionSpotify1.getSpotifyTrack().getAlbum().getAlbumId());
        Assertions.assertEquals(albumNameSpotify1, positionSpotify1.getSpotifyTrack().getAlbum().getName());
        Assertions.assertEquals(albumReleaseDateSpotify1, positionSpotify1.getSpotifyTrack().getAlbum().getReleaseDate());

        Assertions.assertEquals(1, positionSpotify1.getSpotifyTrack().getArtists().size());
        SpotifyArtist dspTrackArtistSpotify1 = positionSpotify1.getSpotifyTrack().getArtists().get(0);
        Assertions.assertEquals(dspTrackArtistIdSpotify1, dspTrackArtistSpotify1.getArtistId());
        Assertions.assertEquals(dspTrackArtistNameSpotify1, dspTrackArtistSpotify1.getName());

        //data from lifetimes
        Assertions.assertEquals(earliestPositionSpotify1, positionSpotify1.getEarliestPosition());
        Assertions.assertEquals(earliestDateTimeSpotify1, positionSpotify1.getEarliestPositionDateTime());
        Assertions.assertEquals(lastAddedDateTimeSpotify1, positionSpotify1.getLastAddedDateTime());
        Assertions.assertEquals(latestDateTimeSpotify1, positionSpotify1.getLatestPositionDateTime());

        //APPLE position
        PublicPlaylistTrackPositionModel positionApple1 = positions.stream().filter(pos -> APPLE.equals(pos.getDsp()))
            .findFirst().orElse(null);

        //position
        Assertions.assertNotNull(positionApple1);
        Assertions.assertEquals(date1, positionApple1.getDate());
        Assertions.assertEquals(APPLE, positionApple1.getDsp());
        Assertions.assertEquals(playlistIdApple1, positionApple1.getPlaylistId());
        Assertions.assertEquals(isrc1, positionApple1.getIsrc());

        Assertions.assertEquals(dspTrackIdApple1, positionApple1.getDspTrackId());
        Assertions.assertEquals(currentPositionApple1, positionApple1.getCurrent());
        Assertions.assertEquals(previousPositionApple1, positionApple1.getPrevious());
        //other fields omitted

        //streams
        PlaylistStreamingForPeriodsInfo countryStreamingPeriodsInfoApple1 = positionApple1.getStreamingInfo().get(countryCode1);
        Assertions.assertNotNull(countryStreamingPeriodsInfoApple1);
        Assertions.assertEquals(streamsCountApple1, countryStreamingPeriodsInfoApple1.getPeriodFor1Day().getIsrcInPlaylist());
        Assertions.assertEquals(streamsCountApple1, countryStreamingPeriodsInfoApple1.getPeriodFor7Days().getIsrcInPlaylist());
        Assertions.assertEquals(streamsCountApple1, countryStreamingPeriodsInfoApple1.getPeriodFor14Days().getIsrcInPlaylist());
        //streams for 'playlist' omitted

        //playlist
        Assertions.assertNotNull(positionApple1.getPlaylist());
        Assertions.assertEquals(playlistIdApple1, positionApple1.getPlaylist().getPlaylistId());
        Assertions.assertEquals(playlistNameApple1, positionApple1.getPlaylist().getName());
        Assertions.assertEquals(countryCode1, positionApple1.getPlaylist().getCountryCode());
        //other fields omitted

        //GRAS track
        Assertions.assertNotNull(positionApple1.getTrack());
        Assertions.assertEquals(grasTrackId1, positionApple1.getTrack().getTrackId());
        Assertions.assertEquals(isrc1, positionApple1.getTrack().getIsrc());
        Assertions.assertEquals(grasTrackName1, positionApple1.getTrack().getName());
        Assertions.assertEquals(grasTrackProductId1, positionApple1.getTrack().getProduct().getProductId());

        Assertions.assertNotNull(positionApple1.getAppleTrack());
        Assertions.assertEquals(dspTrackIdApple1, positionApple1.getAppleTrack().getTrackId());
        Assertions.assertEquals(dspTrackNameApple1, positionApple1.getAppleTrack().getName());
        Assertions.assertEquals(isrc1, positionApple1.getAppleTrack().getIsrc());

        Assertions.assertEquals(albumIdApple1, positionApple1.getAppleTrack().getAlbum().getAlbumId());
        Assertions.assertEquals(albumNameApple1, positionApple1.getAppleTrack().getAlbum().getName());
        Assertions.assertEquals(albumReleaseDateApple1, positionApple1.getAppleTrack().getAlbum().getReleaseDate());

        Assertions.assertEquals(1, positionApple1.getAppleTrack().getArtists().size());
        AppleArtist dspTrackArtistApple1 = positionApple1.getAppleTrack().getArtists().get(0);
        Assertions.assertEquals(dspTrackArtistIdApple1, dspTrackArtistApple1.getArtistId());
        Assertions.assertEquals(dspTrackArtistNameApple1, dspTrackArtistApple1.getName());

        //data from lifetimes
        Assertions.assertEquals(earliestPositionApple1, positionApple1.getEarliestPosition());
        Assertions.assertEquals(earliestDateTimeApple1, positionApple1.getEarliestPositionDateTime());
        Assertions.assertEquals(lastAddedDateTimeApple1, positionApple1.getLastAddedDateTime());
        Assertions.assertEquals(latestDateTimeApple1, positionApple1.getLatestPositionDateTime());

        //AMAZON position
        PublicPlaylistTrackPositionModel positionAmazon1 = positions.stream().filter(pos -> AMAZON.equals(pos.getDsp()))
            .findFirst().orElse(null);

        //position
        Assertions.assertNotNull(positionAmazon1);
        Assertions.assertEquals(date1, positionAmazon1.getDate());
        Assertions.assertEquals(AMAZON, positionAmazon1.getDsp());
        Assertions.assertEquals(playlistIdAmazonChartmetricWithCountry1, positionAmazon1.getPlaylistId());
        Assertions.assertEquals(isrc1, positionAmazon1.getIsrc());

        Assertions.assertEquals(dspTrackIdAmazonWithPrefix1, positionAmazon1.getDspTrackId());
        Assertions.assertEquals(currentPositionAmazon1, positionAmazon1.getCurrent());
        Assertions.assertEquals(previousPositionAmazon1, positionAmazon1.getPrevious());
        //other fields omitted

        //streams
        PlaylistStreamingForPeriodsInfo countryStreamingPeriodsInfoAmazon1 = positionAmazon1.getStreamingInfo().get(countryCode1);
        Assertions.assertNotNull(countryStreamingPeriodsInfoAmazon1);
        Assertions.assertEquals(streamsCountAmazon1, countryStreamingPeriodsInfoAmazon1.getPeriodFor1Day().getIsrcInPlaylist());
        Assertions.assertEquals(streamsCountAmazon1, countryStreamingPeriodsInfoAmazon1.getPeriodFor7Days().getIsrcInPlaylist());
        Assertions.assertEquals(streamsCountAmazon1, countryStreamingPeriodsInfoAmazon1.getPeriodFor14Days().getIsrcInPlaylist());
        //streams for 'playlist' omitted

        //playlist
        Assertions.assertNotNull(positionAmazon1.getPlaylist());
        Assertions.assertEquals(playlistIdAmazonChartmetricWithCountry1, positionAmazon1.getPlaylist().getPlaylistId());
        Assertions.assertEquals(playlistNameAmazon1, positionAmazon1.getPlaylist().getName());
        Assertions.assertEquals(countryCode1, positionAmazon1.getPlaylist().getCountryCode());
        //amazon playlist id
        Assertions.assertEquals(playlistIdAmazonDsp1, positionAmazon1.getPlaylist().getAmazonPlaylistId());
        //other fields omitted

        //GRAS track
        Assertions.assertNotNull(positionAmazon1.getTrack());
        Assertions.assertEquals(grasTrackId1, positionAmazon1.getTrack().getTrackId());
        Assertions.assertEquals(isrc1, positionAmazon1.getTrack().getIsrc());
        Assertions.assertEquals(grasTrackName1, positionAmazon1.getTrack().getName());
        Assertions.assertEquals(grasTrackProductId1, positionAmazon1.getTrack().getProduct().getProductId());

        //DSP track
        Assertions.assertNotNull(positionAmazon1.getAmazonTrack());
        Assertions.assertEquals(dspTrackIdAmazon1, positionAmazon1.getAmazonTrack().getAmazonTrackId());
        Assertions.assertEquals(dspTrackNameAmazon1, positionAmazon1.getAmazonTrack().getName());
        Assertions.assertEquals(isrc1, positionAmazon1.getAmazonTrack().getIsrc());
        Assertions.assertEquals(countryCode1, positionAmazon1.getAmazonTrack().getCountryCode());
    }

    /**
     * Single position must be expanded into 2, based on country codes available in countries protobuf map.
     * <p>
     * APPLE DSP is used here, most of the code is the same across DSPs
     */
    @Test
    @SqlScript(scripts = "/scripts/TrackPositionsPlaylistsPublicIT/common_test_data_set_1.sql")
    @BigTable(table = "playlist_tracks", json =
        "/scripts/TrackPositionsPlaylistsPublicIT/BT_playlist_tracks_getPublicTrackPositionsPlaylists_loadData_countriesExpansion_apple.json")
    @BigTable(table = "playlists", json = "/scripts/BT_empty.json")
    public void getPublicTrackPositionsPlaylists_loadData_countriesExpansion_apple() {
        LocalDate date1 = LocalDate.parse("2022-05-15");
        String isrc1 = "USQX91901111";

        String playlistId1 = "apple_2";
        String playlistNameUS = "playlistNameUS";
        String playlistNameCA = "playlistNameCA";

        String countryCodeUS = "us";
        String countryCodeCA = "ca";

        String dspTrackIdUS = "dspTrackIdUS";
        String dspTrackIdCA = "dspTrackIdCA";

        int currentPositionUS = 1;
        int previousPositionUS = 2;

        int currentPositionCA = 11;
        int previousPositionCA = 22;

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

        Assertions.assertEquals(HttpStatus.OK, response.getStatusCode());
        Assertions.assertEquals(2, response.getBody().getCount());

        List<PublicPlaylistTrackPositionModel> positions = response.getBody().getItems();

        //position 1 - countryCode: us
        PublicPlaylistTrackPositionModel positionUS = positions.stream()
            .filter(pos -> countryCodeUS.equals(pos.getPlaylist().getCountryCode()))
            .findFirst().orElse(null);

        //position
        Assertions.assertNotNull(positionUS);
        Assertions.assertEquals(date1, positionUS.getDate());
        Assertions.assertEquals(playlistId1, positionUS.getPlaylistId());
        Assertions.assertEquals(isrc1, positionUS.getIsrc());

        Assertions.assertEquals(dspTrackIdUS, positionUS.getDspTrackId());
        Assertions.assertEquals(currentPositionUS, positionUS.getCurrent());
        Assertions.assertEquals(previousPositionUS, positionUS.getPrevious());
        //other fields omitted

        //playlist
        Assertions.assertEquals(playlistId1, positionUS.getPlaylist().getPlaylistId());
        Assertions.assertEquals(playlistNameUS, positionUS.getPlaylist().getName());
        Assertions.assertEquals(countryCodeUS, positionUS.getPlaylist().getCountryCode());
        //other fields omitted

        //position 2 - countryCode: ca
        PublicPlaylistTrackPositionModel positionCA = positions.stream()
            .filter(pos -> countryCodeCA.equals(pos.getPlaylist().getCountryCode()))
            .findFirst().orElse(null);

        //position
        Assertions.assertNotNull(positionCA);
        Assertions.assertEquals(date1, positionCA.getDate());
        Assertions.assertEquals(playlistId1, positionCA.getPlaylistId());
        Assertions.assertEquals(isrc1, positionCA.getIsrc());

        Assertions.assertEquals(dspTrackIdCA, positionCA.getDspTrackId());
        Assertions.assertEquals(currentPositionCA, positionCA.getCurrent());
        Assertions.assertEquals(previousPositionCA, positionCA.getPrevious());
        //other fields omitted

        //playlist
        Assertions.assertEquals(playlistId1, positionCA.getPlaylist().getPlaylistId());
        Assertions.assertEquals(playlistNameCA, positionCA.getPlaylist().getName());
        Assertions.assertEquals(countryCodeCA, positionCA.getPlaylist().getCountryCode());
        //other fields omitted
    }

    /**
     * Single position of country US must be expanded into 3, based on 'positions' (position places) available in tracks/positions protobuf map.
     * <p>
     * 3 positions though 2 tracks - one track may occupy multiple positions
     * <p>
     * APPLE DSP is used here, most of the code is the same across DSPs. Is not supported for Amazon
     */
    @Test
    @SqlScript(scripts = "/scripts/TrackPositionsPlaylistsPublicIT/common_test_data_set_1.sql")
    @BigTable(table = "playlist_tracks", json =
        "/scripts/TrackPositionsPlaylistsPublicIT/BT_playlist_tracks_getPublicTrackPositionsPlaylists_loadData_tracksAndPositionsExpansion_apple.json")
    @BigTable(table = "playlists", json = "/scripts/BT_empty.json")
    public void getPublicTrackPositionsPlaylists_loadData_tracksAndPositionsExpansion_apple() {
        LocalDate date1 = LocalDate.parse("2022-05-15");
        String isrc1 = "USQX91901111";

        String playlistId1 = "apple_3";
        String playlistName1 = "playlistName1";

        String countryCode1 = "us";

        String dspTrackId1 = "dspTrackId1";
        String dspTrackId2 = "dspTrackId2";

        int currentPosition1 = 1;
        int currentPosition2 = 11;
        int currentPosition3 = 111;

        int previousPosition1 = 2;

        ResponseEntity<PublicPlaylistTrackPositionsModel> response = apiClient.sendAPIRequest(
            "/v3/public/track-positions/playlists?"
                + "start_date=" + date1.minusDays(5)
                + "&end_date=" + date1.plusDays(2)
                + "&isrc=" + isrc1
                + "&expand_isrc_by_track_positions=true" //expand positions
                + "&include=" + String.format("%s",
                IncludeTracklistPlaylist.PLAYLISTS.getValue()),
            PublicPlaylistTrackPositionsModel.class
        );

        Assertions.assertEquals(HttpStatus.OK, response.getStatusCode());
        Assertions.assertEquals(3, response.getBody().getCount());

        List<PublicPlaylistTrackPositionModel> positions = response.getBody().getItems();

        //POSITION 1 - current position: currentPosition1
        PublicPlaylistTrackPositionModel position1 = positions.stream()
            .filter(pos -> currentPosition1 == pos.getCurrent())
            .findFirst().orElse(null);

        //position
        Assertions.assertNotNull(position1);
        Assertions.assertEquals(date1, position1.getDate());
        Assertions.assertEquals(playlistId1, position1.getPlaylistId());
        Assertions.assertEquals(isrc1, position1.getIsrc());

        Assertions.assertEquals(dspTrackId1, position1.getDspTrackId()); //dspTrackId1 at position currentPosition1
        Assertions.assertEquals(currentPosition1, position1.getCurrent()); //currentPosition1 is set
        Assertions.assertEquals(previousPosition1, position1.getPrevious());
        //other fields omitted

        //playlist
        Assertions.assertEquals(playlistId1, position1.getPlaylist().getPlaylistId());
        Assertions.assertEquals(playlistName1, position1.getPlaylist().getName());
        Assertions.assertEquals(countryCode1, position1.getPlaylist().getCountryCode());
        //other fields omitted

        //POSITION 2 - current position: currentPosition2
        PublicPlaylistTrackPositionModel position2 = positions.stream()
            .filter(pos -> currentPosition2 == pos.getCurrent())
            .findFirst().orElse(null);

        //position
        Assertions.assertNotNull(position2);
        Assertions.assertEquals(date1, position2.getDate());
        Assertions.assertEquals(playlistId1, position2.getPlaylistId());
        Assertions.assertEquals(isrc1, position2.getIsrc());

        Assertions.assertEquals(dspTrackId2, position2.getDspTrackId()); //dspTrackId2 at position currentPosition2
        Assertions.assertEquals(currentPosition2, position2.getCurrent()); //currentPosition2 is set
        Assertions.assertEquals(previousPosition1, position2.getPrevious());
        //other fields omitted

        //playlist
        Assertions.assertEquals(playlistId1, position2.getPlaylist().getPlaylistId());
        Assertions.assertEquals(playlistName1, position2.getPlaylist().getName());
        Assertions.assertEquals(countryCode1, position2.getPlaylist().getCountryCode());
        //other fields omitted

        //POSITION 3 - current position: currentPosition3
        PublicPlaylistTrackPositionModel position3 = positions.stream()
            .filter(pos -> currentPosition3 == pos.getCurrent())
            .findFirst().orElse(null);

        //position
        Assertions.assertNotNull(position3);
        Assertions.assertEquals(date1, position3.getDate());
        Assertions.assertEquals(playlistId1, position3.getPlaylistId());
        Assertions.assertEquals(isrc1, position3.getIsrc());

        Assertions.assertEquals(dspTrackId2, position3.getDspTrackId()); //dspTrackId2 at position currentPosition3 (!)
        Assertions.assertEquals(currentPosition3, position3.getCurrent()); //currentPosition3 is set
        Assertions.assertEquals(previousPosition1, position3.getPrevious());
        //other fields omitted

        //playlist
        Assertions.assertEquals(playlistId1, position3.getPlaylist().getPlaylistId());
        Assertions.assertEquals(playlistName1, position3.getPlaylist().getName());
        Assertions.assertEquals(countryCode1, position3.getPlaylist().getCountryCode());
        //other fields omitted
    }

    /**
     * Check that last date at which stream records are searched is equal to 'last data-complete date', taken from data-completeness PG table
     * <p>
     * Only streams for isrc-in-playlist are tested here - not whole playlist streams count, but date picking logic is same
     */
    @Test
    @SqlScript(scripts = "/scripts/TrackPositionsPlaylistsPublicIT/common_test_data_set_1.sql")
    @BigTable(table = "playlist_tracks", json =
        "/scripts/TrackPositionsPlaylistsPublicIT/BT_playlist_tracks_getPublicTrackPositionsPlaylists_streamsForPeriod_baseDatePicking.json")
    @BigTable(table = "playlists", json =
        "/scripts/TrackPositionsPlaylistsPublicIT/BT_playlists_getPublicTrackPositionsPlaylists_streamsForPeriod_baseDatePicking.json")
    @BigTable(table = "spotify", json =
        "/scripts/TrackPositionsPlaylistsPublicIT/BT_spotify_getPublicTrackPositionsPlaylists_streamsForPeriod_baseDatePicking.json")
    @BigTable(table = "apple_music", json =
        "/scripts/TrackPositionsPlaylistsPublicIT/BT_apple_music_getPublicTrackPositionsPlaylists_streamsForPeriod_baseDatePicking.json")
    @BigTable(table = "amazon_music", json =
        "/scripts/TrackPositionsPlaylistsPublicIT/BT_amazon_music_getPublicTrackPositionsPlaylists_streamsForPeriod_baseDatePicking.json")
    public void getPublicTrackPositionsPlaylists_streamsForPeriod_baseDatePicking() {
        LocalDateTime currentDateTime = LocalDateTime.parse("2023-01-15T00:00:00");
        LocalDate currentDate = currentDateTime.toLocalDate();

        MockCurrentDateService.setMockDateTime(currentDateTime);

        String isrc1 = "USQX91901111";

        String playlistIdSpotify1 = "spotify_4";
        String playlistIdApple1 = "apple_4";

        String playlistIdAmazonChartmetricWithCountry1 = "amazon_1_us";

        String countryCode1 = "us";

        /* perform test call */
        ResponseEntity<PublicPlaylistTrackPositionsModel> response = apiClient.sendAPIRequest(
            "/v3/public/track-positions/playlists?"
                + "start_date=" + currentDate.minusDays(7)
                + "&end_date=" + currentDate
                + "&isrc=" + isrc1
                + "&include=" + String.format("%s",
                IncludeTracklistPlaylist.STREAMS_FOR_PERIOD.getValue())
                + "&streams_country_code=" + countryCode1,
            PublicPlaylistTrackPositionsModel.class
        );

        Assertions.assertEquals(HttpStatus.OK, response.getStatusCode());
        Assertions.assertEquals(3, response.getBody().getCount());

        List<PublicPlaylistTrackPositionModel> positions = response.getBody().getItems();

        //SPOTIFY position
        PublicPlaylistTrackPositionModel positionSpotify1 = positions.stream().filter(pos -> SPOTIFY.equals(pos.getDsp()))
            .findFirst().orElse(null);

        //position
        Assertions.assertNotNull(positionSpotify1);
        Assertions.assertEquals(currentDate, positionSpotify1.getDate());
        Assertions.assertEquals(playlistIdSpotify1, positionSpotify1.getPlaylistId());
        Assertions.assertEquals(isrc1, positionSpotify1.getIsrc());

        //streams
        PlaylistStreamingForPeriodsInfo countryStreamingPeriodsInfoSpotify1 = positionSpotify1.getStreamingInfo().get(countryCode1);
        Assertions.assertNotNull(countryStreamingPeriodsInfoSpotify1);
        //'last data complete date' for SPOTIFY is currentDate so all 5 days of streams records are counted, last1Day=currentDate (streamsCount=50)
        Assertions.assertEquals(50, countryStreamingPeriodsInfoSpotify1.getPeriodFor1Day().getIsrcInPlaylist());
        Assertions.assertEquals(150, countryStreamingPeriodsInfoSpotify1.getPeriodFor7Days().getIsrcInPlaylist());

        //APPLE position
        PublicPlaylistTrackPositionModel positionApple1 = positions.stream().filter(pos -> APPLE.equals(pos.getDsp()))
            .findFirst().orElse(null);

        //position
        Assertions.assertNotNull(positionApple1);
        Assertions.assertEquals(currentDate, positionApple1.getDate());
        Assertions.assertEquals(playlistIdApple1, positionApple1.getPlaylistId());
        Assertions.assertEquals(isrc1, positionApple1.getIsrc());

        //streams
        PlaylistStreamingForPeriodsInfo countryStreamingPeriodsInfoApple1 = positionApple1.getStreamingInfo().get(countryCode1);
        Assertions.assertNotNull(countryStreamingPeriodsInfoApple1);
        //'last data complete date' for APPLE is currentDate-1 so 4 of 5 days of streams records are counted, last1Day=currentDate-1 (streamsCount=40)
        Assertions.assertEquals(40, countryStreamingPeriodsInfoApple1.getPeriodFor1Day().getIsrcInPlaylist());
        Assertions.assertEquals(100, countryStreamingPeriodsInfoApple1.getPeriodFor7Days().getIsrcInPlaylist());

        //AMAZON position
        PublicPlaylistTrackPositionModel positionAmazon1 = positions.stream().filter(pos -> AMAZON.equals(pos.getDsp()))
            .findFirst().orElse(null);

        //position
        Assertions.assertNotNull(positionAmazon1);
        Assertions.assertEquals(currentDate, positionAmazon1.getDate());
        Assertions.assertEquals(playlistIdAmazonChartmetricWithCountry1, positionAmazon1.getPlaylistId());
        Assertions.assertEquals(isrc1, positionAmazon1.getIsrc());

        //streams
        PlaylistStreamingForPeriodsInfo countryStreamingPeriodsInfoAmazon1 = positionAmazon1.getStreamingInfo().get(countryCode1);
        Assertions.assertNotNull(countryStreamingPeriodsInfoAmazon1);
        //'last data complete date' for AMAZON is currentDate-2 so 3 of 5 days of streams records are counted, last1Day=currentDate-2 (streamsCount=30)
        Assertions.assertEquals(30, countryStreamingPeriodsInfoAmazon1.getPeriodFor1Day().getIsrcInPlaylist());
        Assertions.assertEquals(60, countryStreamingPeriodsInfoAmazon1.getPeriodFor7Days().getIsrcInPlaylist());
    }
}
