package io.delphiplatform.api.integration;

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

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Optional;

import io.delphiplatform.api.integration.annotation.SqlScript;
import io.delphiplatform.api.integration.model.AmazonChartModel;
import io.delphiplatform.api.integration.model.AmazonChartPositionSummaryModel;
import io.delphiplatform.api.integration.model.AmazonChartTrackPositionModel;
import io.delphiplatform.api.integration.model.AmazonChartTrackPositionsModel;
import io.delphiplatform.api.integration.model.AmazonChartTrackSummariesModel;
import io.delphiplatform.api.integration.model.AmazonChartTrackSummaryModel;
import io.delphiplatform.api.integration.model.AmazonChartsDataHealthStatusReportModel;
import io.delphiplatform.api.integration.model.AmazonChartsModel;
import io.delphiplatform.api.integration.model.AmazonDataHealthStatusSummaryModel;
import io.delphiplatform.api.integration.model.AmazonTrackModel;
import io.delphiplatform.api.v3.constant.DspConstants;
import io.delphiplatform.api.v3.model.IncludeChart;
import io.delphiplatform.api.v3.model.SortOrder;
import io.delphiplatform.api.v3.model.amazon.AmazonChartType;
import io.delphiplatform.api.v3.model.datahealth.AmazonChartsDataHealthStatus;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

public class AmazonChartsIT extends BaseIT {

    @Test
    @SqlScript(scripts = "/scripts/AmazonChartsIT/common_test_data_set_1.sql")
    void getAmazonCharts() {
        String chartId1 = "chartId1";
        String countryCode1 = "us";

        String genreName1 = "Work, Study, Reading";

        ResponseEntity<AmazonChartsModel> response = apiClient.sendAPIRequest(
            "/v3/amazon/charts?"
                + "chart_id=" + chartId1
                + "&country_code=" + countryCode1
                + "&genre_name=" + URLEncoder.encode(genreName1, StandardCharsets.UTF_8)
                + "&sort_by=" + "country_code"
                + "&sort_order=" + SortOrder.DESC.getValue(),
            AmazonChartsModel.class
        );

        assertEquals(HttpStatus.OK, response.getStatusCode());
        AmazonChartsModel charts = response.getBody();
        assertEquals(1, charts.getItems().size());

        AmazonChartModel amazonChart = charts.getItems().get(0);
        assertEquals(chartId1, amazonChart.getChartId());
        assertEquals(5, amazonChart.getTotalPositions());
        assertEquals(genreName1, amazonChart.getGenre());
        assertEquals(countryCode1, amazonChart.getCountryCode());
    }

    @Test
    @SqlScript(scripts = {"/scripts/AmazonChartsIT/common_test_data_set_1.sql",
        "/scripts/AmazonChartsIT/getAmazonChartTrackPositions.sql"})
    void getAmazonChartTrackPositions() {
        String chartId1 = "chartId1";

        String trackId1 = "trackId1";
        boolean isSony = false;

        LocalDate startDate = LocalDate.of(2022, 10, 1);
        LocalDate endDate = LocalDate.of(2022, 10, 3);

        int minPosition = 0;
        int maxPosition = 10;
        boolean isExit = false;

        ResponseEntity<AmazonChartTrackPositionsModel> response = apiClient.sendAPIRequest(
            "/v3/amazon/charts/track-positions?"
                + "start_date=" + startDate
                + "&end_date=" + endDate
                + "&chart_id=" + chartId1
                + "&track_id=" + trackId1
                + "&min_position=" + minPosition
                + "&max_position=" + maxPosition
                + "&is_exit=" + isExit
                + "&is_sony=" + isSony
                + "&include=" + IncludeChart.TRACK.getValue()
                + "&sort_by=" + "chart.chart_id"
                + "&sort_order=" + SortOrder.DESC.getValue(),
            AmazonChartTrackPositionsModel.class
        );

        assertEquals(HttpStatus.OK, response.getStatusCode());
        AmazonChartTrackPositionsModel positions = response.getBody();
        assertNotNull(positions);
        assertEquals(1, positions.getItems().size());

        AmazonChartTrackPositionModel position = positions.getItems().get(0);
        AmazonChartModel chart = position.getChart().get();
        AmazonTrackModel track = position.getTrack().get();
        assertEquals(chartId1, chart.getChartId());
        assertEquals(trackId1, track.getAmazonTrackId());
        assertEquals(1, position.getPosition().getTotalDays());
    }

    @Test
    @SqlScript(scripts = {"/scripts/AmazonChartsIT/common_test_data_set_1.sql",
        "/scripts/AmazonChartsIT/getAmazonChartTrackPositionsSummary.sql"})
    void getAmazonChartTrackPositionsSummary() {
        String chartId1 = "chartId1";

        String trackId1 = "trackId1";
        boolean isSony = false;

        int earliestPosition1 = 15;
        int latestPosition1 = 5;
        int minPosition1 = 2;
        int maxPosition1 = 25;
        int totalDays1 = 20;

        LocalDate earliestPositionDate1 = LocalDate.of(2022, 10, 1);
        LocalDate latestPositionDate1 = LocalDate.of(2022, 10, 4);
        LocalDate minPositionDate1 = LocalDate.of(2022, 10, 2);
        LocalDate maxPositionDate1 = LocalDate.of(2022, 10, 3);

        ResponseEntity<AmazonChartTrackSummariesModel> response = apiClient.sendAPIRequest(
            "/v3/amazon/charts/track-positions/summary?"
                + "chart_id=" + chartId1
                + "&track_id=" + trackId1
                + "&is_sony=" + isSony
                + "&include=" + IncludeChart.TRACK.getValue()
                + "&sort_by=" + "chart.chart_id"
                + "&sort_order=" + SortOrder.DESC.getValue(),
            AmazonChartTrackSummariesModel.class
        );

        assertEquals(HttpStatus.OK, response.getStatusCode());
        AmazonChartTrackSummariesModel summaries = response.getBody();
        assertNotNull(summaries);
        assertNotNull(summaries.getItems());
        assertEquals(1, summaries.getItems().size());

        AmazonChartTrackSummaryModel amazonChartTrackSummary = summaries.getItems().get(0);
        assertEquals(chartId1, amazonChartTrackSummary.getChart().get().getChartId());
        assertEquals(trackId1, amazonChartTrackSummary.getTrack().get().getAmazonTrackId());

        AmazonChartPositionSummaryModel summary = amazonChartTrackSummary.getSummary();
        assertEquals(earliestPosition1, summary.getEarliestPosition());
        assertEquals(earliestPositionDate1, summary.getEarliestPositionDate());
        assertEquals(latestPosition1, summary.getLatestPosition());
        assertEquals(latestPositionDate1, summary.getLatestPositionDate());
        assertEquals(maxPosition1, summary.getMaxPosition());
        assertEquals(maxPositionDate1, summary.getMaxPositionDate());
        assertEquals(minPosition1, summary.getMinPosition());
        assertEquals(minPositionDate1, summary.getMinPositionDate());
        assertEquals(totalDays1, summary.getTotalDays());
    }

    @Test
    @SqlScript(scripts = "/scripts/AmazonChartsIT/getAmazonMusicChartsDataHealthStatus.sql")
    void getAmazonMusicChartsDataHealthStatus() {
        String countryCode1 = "us";

        ResponseEntity<AmazonChartsDataHealthStatusReportModel> response = apiClient.sendAPIRequest(
            "/v3/amazon/charts/data-health/status?"
                + "status=" + AmazonChartsDataHealthStatus.COMPLETE.getValue()
                + "&country_code=" + countryCode1,
            AmazonChartsDataHealthStatusReportModel.class
        );

        assertEquals(HttpStatus.OK, response.getStatusCode());
        AmazonDataHealthStatusSummaryModel chartSummary = Optional.ofNullable(response.getBody())
            .map(AmazonChartsDataHealthStatusReportModel::getDspChartTypeCountryCode)
            .map(r -> r.get(DspConstants.AMAZON))
            .map(r -> r.get(AmazonChartType.DAILY.getValue()))
            .map(r -> r.get("us"))
            .orElse(null);
        assertNotNull(chartSummary);

        LocalDateTime expectedMinDateTime = LocalDateTime.of(2022, 10, 1, 10, 0, 0);
        LocalDateTime expectedMaxDateTime = LocalDateTime.of(2022, 10, 1, 12, 0, 0);
        LocalDateTime expectedValidUntilDateTime = LocalDateTime.of(2022, 10, 1, 12, 0, 0);

        assertEquals(expectedMinDateTime, chartSummary.getMinDateTime());
        assertEquals(expectedMaxDateTime, chartSummary.getMaxDateTime());
        assertEquals(expectedValidUntilDateTime, chartSummary.getValidUntilDateTime());
    }

}
