package io.delphiplatform.api.v3.model.spotify;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.openapitools.jackson.nullable.JsonNullable;

import java.time.LocalDate;

import io.delphiplatform.api.v3.constant.CountryCodeConstant;
import io.delphiplatform.api.v3.model.charts.ChartTrackStateMetrics;
import io.delphiplatform.api.v3.rdb.entity.apple.music.AppleMusicChartTrackEntity;
import io.delphiplatform.api.v3.rdb.entity.apple.music.AppleMusicChartTrackId;
import io.delphiplatform.api.v3.rdb.entity.spotify.SpotifyChartTrackEntity;
import io.delphiplatform.api.v3.rdb.entity.spotify.SpotifyChartTrackId;

import static io.delphiplatform.api.v3.model.spotify.ChartTrackMetricsDimension.ISRC;
import static io.delphiplatform.api.v3.model.spotify.ChartTrackMetricsDimension.TRACK_ID;

public class ChartTrackStateMetricsTest {

    private static final LocalDate DATE = LocalDate.of(2020, 1, 1);
    private static final String TEST_ISRC = "ISRC1";

    @Test
    void testTransformFromSpotifyChartTrackEntity_dimension_track() {
        SpotifyChartTrackId sourceEntityId = new SpotifyChartTrackId();
        sourceEntityId.setChartDate(DATE);
        sourceEntityId.setSpotifyChartId("test-chart-id");
        //setting only fields used for entity transformation
        SpotifyChartTrackEntity sourceEntity = new SpotifyChartTrackEntity();
        sourceEntity.setId(sourceEntityId);
        sourceEntity.setSpotifyCountryId(CountryCodeConstant.WORLDWIDE);
        sourceEntity.setSpotifyTrackId("test-track-id");
        sourceEntity.setPrevChartDate(DATE.minusDays(1));
        sourceEntity.setEntry(false);
        sourceEntity.setReentry(false);
        sourceEntity.setCurrentPosition(1);
        sourceEntity.setPrevPosition(5);
        sourceEntity.setTrend(4);
        sourceEntity.setPeriodStreams(555);
        sourceEntity.setIsrcPeriodStreams(550);

        ChartTrackStateMetrics expectedResultEntity = new ChartTrackStateMetrics();
        expectedResultEntity.setDate(DATE);
        expectedResultEntity.setPreviousDate(DATE.minusDays(1));
        expectedResultEntity.setIsEntry(false);
        expectedResultEntity.setPosition(1);
        expectedResultEntity.setPreviousPosition(5);
        expectedResultEntity.setTrend(4);
        expectedResultEntity.setDateStreams(JsonNullable.of(555));
        expectedResultEntity.setIsrcDateStreams(JsonNullable.of(550));

        //both source entry, reentry = false. Expected entry = false
        ChartTrackStateMetrics transformedEntity = ChartTrackStateMetrics.of(sourceEntity, TRACK_ID);

        Assertions.assertEquals(expectedResultEntity, transformedEntity);

        //source entry = true; reentry = false. Expected entry = true
        sourceEntity.setEntry(true);
        expectedResultEntity.setIsEntry(true);

        transformedEntity = ChartTrackStateMetrics.of(sourceEntity, TRACK_ID);

        Assertions.assertEquals(expectedResultEntity, transformedEntity);

        //source entry = false; reentry = true. Expected entry = true
        sourceEntity.setEntry(false);
        sourceEntity.setReentry(true);
        expectedResultEntity.setIsEntry(true);

        transformedEntity = ChartTrackStateMetrics.of(sourceEntity, TRACK_ID);

        Assertions.assertEquals(expectedResultEntity, transformedEntity);
    }


    @Test
    void testTransformFromSpotifyChartTrackEntity_dimension_isrc() {
        SpotifyChartTrackId sourceEntityId = new SpotifyChartTrackId();
        sourceEntityId.setChartDate(DATE);
        sourceEntityId.setSpotifyChartId("test-chart-id");
        //setting only fields used for entity transformation
        SpotifyChartTrackEntity sourceEntity = new SpotifyChartTrackEntity();
        sourceEntity.setId(sourceEntityId);
        sourceEntity.setSpotifyCountryId(CountryCodeConstant.WORLDWIDE);
        sourceEntity.setSpotifyTrackId("test-track-id");
        sourceEntity.setIsrcPrevChartDate(DATE.minusDays(1));
        sourceEntity.setIsrc(TEST_ISRC);
        sourceEntity.setCurrentPosition(1);
        sourceEntity.setIsrcCurrentPosition(2);
        sourceEntity.setIsrcPrevPosition(5);
        sourceEntity.setIsrcIsEntry(false);
        sourceEntity.setIsrcIsReentry(false);
        sourceEntity.setIsrcTrend(4);
        sourceEntity.setPeriodStreams(555);
        sourceEntity.setIsrcPeriodStreams(550);

        ChartTrackStateMetrics expectedResultEntity = new ChartTrackStateMetrics();
        expectedResultEntity.setDate(DATE);
        expectedResultEntity.setPreviousDate(DATE.minusDays(1));
        expectedResultEntity.setIsEntry(false);
        expectedResultEntity.setPosition(1);
        expectedResultEntity.setIsrcPosition(2);
        expectedResultEntity.setPreviousPosition(5);
        expectedResultEntity.setTrend(4);
        expectedResultEntity.setDateStreams(JsonNullable.of(555));
        expectedResultEntity.setIsrcDateStreams(JsonNullable.of(550));

        //both source entry, reentry = false. Expected entry = false
        ChartTrackStateMetrics transformedEntity = ChartTrackStateMetrics.of(sourceEntity, ISRC);

        Assertions.assertEquals(expectedResultEntity, transformedEntity);

        //source isrcIsEntry = true; isrcIsReentry = false. Expected entry = true
        sourceEntity.setIsrcIsEntry(true);
        sourceEntity.setIsrcIsReentry(false);
        expectedResultEntity.setIsEntry(true);

        transformedEntity = ChartTrackStateMetrics.of(sourceEntity, ISRC);

        Assertions.assertEquals(expectedResultEntity, transformedEntity);

        //source isrcIsEntry = false; isrcIsReentry = true. Expected entry = true
        sourceEntity.setIsrcIsEntry(false);
        sourceEntity.setIsrcIsReentry(true);
        expectedResultEntity.setIsEntry(true);

        transformedEntity = ChartTrackStateMetrics.of(sourceEntity, ISRC);

        Assertions.assertEquals(expectedResultEntity, transformedEntity);

        //source isrcIsEntry = null; isrcIsReentry = null. Expected entry = false
        sourceEntity.setIsrcIsEntry(null);
        sourceEntity.setIsrcIsReentry(null);
        expectedResultEntity.setIsEntry(null);

        transformedEntity = ChartTrackStateMetrics.of(sourceEntity, ISRC);

        Assertions.assertEquals(expectedResultEntity, transformedEntity);
    }

    @Test
    void testTransformFromAppleMusicChartTrackEntity_dimension_track() {
        AppleMusicChartTrackId sourceEntityId = new AppleMusicChartTrackId();
        sourceEntityId.setChartDate(DATE);

        AppleMusicChartTrackEntity sourceEntity = new AppleMusicChartTrackEntity();
        sourceEntity.setId(sourceEntityId);
        sourceEntity.setPrevChartDate(DATE.minusDays(1));
        sourceEntity.setEntry(false);
        sourceEntity.setReentry(false);
        sourceEntity.setCurrentPosition(1);
        sourceEntity.setPrevPosition(5);
        sourceEntity.setTrend(4);

        ChartTrackStateMetrics expectedResultEntity = new ChartTrackStateMetrics();
        expectedResultEntity.setDate(DATE);
        expectedResultEntity.setPreviousDate(DATE.minusDays(1));
        expectedResultEntity.setIsEntry(false);
        expectedResultEntity.setPosition(1);
        expectedResultEntity.setPreviousPosition(5);
        expectedResultEntity.setTrend(4);
        expectedResultEntity.setDateStreams(JsonNullable.undefined());
        expectedResultEntity.setIsrcDateStreams(JsonNullable.undefined());

        //both source entry, reentry = false. Expected entry = false
        ChartTrackStateMetrics transformedEntity = ChartTrackStateMetrics.of(sourceEntity, TRACK_ID);
        Assertions.assertEquals(expectedResultEntity, transformedEntity);

        //source isrcIsEntry = true; isrcIsReentry = false. Expected entry = true
        sourceEntity.setEntry(true);
        sourceEntity.setReentry(false);
        expectedResultEntity.setIsEntry(true);
        transformedEntity = ChartTrackStateMetrics.of(sourceEntity, TRACK_ID);
        Assertions.assertEquals(expectedResultEntity, transformedEntity);

        //source isrcIsEntry = false; isrcIsReentry = true. Expected entry = true
        sourceEntity.setEntry(false);
        sourceEntity.setReentry(true);
        expectedResultEntity.setIsEntry(true);
        transformedEntity = ChartTrackStateMetrics.of(sourceEntity, TRACK_ID);
        Assertions.assertEquals(expectedResultEntity, transformedEntity);
    }

    @Test
    void testTransformFromAppleMusicChartTrackEntity_dimension_isrc() {
        AppleMusicChartTrackId sourceEntityId = new AppleMusicChartTrackId();
        sourceEntityId.setChartDate(DATE);

        AppleMusicChartTrackEntity sourceEntity = new AppleMusicChartTrackEntity();
        sourceEntity.setId(sourceEntityId);
        sourceEntity.setIsrcPrevChartDate(DATE.minusDays(1));
        sourceEntity.setIsrcIsEntry(false);
        sourceEntity.setIsrcIsReentry(false);
        sourceEntity.setCurrentPosition(1);
        sourceEntity.setIsrcCurrentPosition(2);
        sourceEntity.setIsrcPrevPosition(5);
        sourceEntity.setIsrcTrend(4);

        ChartTrackStateMetrics expectedResultEntity = new ChartTrackStateMetrics();
        expectedResultEntity.setDate(DATE);
        expectedResultEntity.setPreviousDate(DATE.minusDays(1));
        expectedResultEntity.setIsEntry(false);
        expectedResultEntity.setPosition(1);
        expectedResultEntity.setIsrcPosition(2);
        expectedResultEntity.setPreviousPosition(5);
        expectedResultEntity.setTrend(4);
        expectedResultEntity.setDateStreams(JsonNullable.undefined());
        expectedResultEntity.setIsrcDateStreams(JsonNullable.undefined());

        //both source entry, reentry = false. Expected entry = false
        ChartTrackStateMetrics transformedEntity = ChartTrackStateMetrics.of(sourceEntity, ISRC);
        Assertions.assertEquals(expectedResultEntity, transformedEntity);

        //source isrcIsEntry = true; isrcIsReentry = false. Expected entry = true
        sourceEntity.setIsrcIsEntry(true);
        sourceEntity.setIsrcIsReentry(false);
        expectedResultEntity.setIsEntry(true);
        transformedEntity = ChartTrackStateMetrics.of(sourceEntity, ISRC);
        Assertions.assertEquals(expectedResultEntity, transformedEntity);

        //source isrcIsEntry = false; isrcIsReentry = true. Expected entry = true
        sourceEntity.setIsrcIsEntry(false);
        sourceEntity.setIsrcIsReentry(true);
        expectedResultEntity.setIsEntry(true);
        transformedEntity = ChartTrackStateMetrics.of(sourceEntity, ISRC);
        Assertions.assertEquals(expectedResultEntity, transformedEntity);
    }
}
