package io.delphiplatform.api.v3.view;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.ArrayList;
import java.util.List;

import io.delphiplatform.api.util.CollectionUtils;
import io.delphiplatform.api.v3.model.charts.ChartTrackState;
import io.delphiplatform.api.v3.model.charts.ChartTracksAnalytics;
import io.delphiplatform.api.v3.model.charts.ChartTracksAnalyticsResults;
import io.delphiplatform.api.v3.model.datahealth.DataHealthStatusSummary;
import io.delphiplatform.api.v3.model.datahealth.SpotifyChartsDataHealthStatusReport;
import io.delphiplatform.api.v3.model.spotify.ChartTrackMetricsDimension;
import io.delphiplatform.api.v3.model.spotify.SpotifyChart;
import io.delphiplatform.api.v3.model.spotify.SpotifyChartTrackStates;
import io.delphiplatform.api.v3.model.spotify.SpotifyCharts;
import io.delphiplatform.api.v3.model.spotify.SpotifyTrackChartsSearchResult;
import io.delphiplatform.api.v3.model.spotify.SpotifyTrackChartsSearchResults;
import io.delphiplatform.api.v3.rdb.service.spotify.SpotifyChartService;
import io.delphiplatform.api.v3.rdb.service.spotify.SpotifyChartTrackAnalyticsService;
import io.delphiplatform.api.v3.rdb.service.spotify.SpotifyChartTrackChangesService;
import io.delphiplatform.api.v3.rdb.service.spotify.SpotifyChartTrackStateService;
import io.delphiplatform.api.v3.rdb.service.spotify.SpotifyChartsDataHealthStatusService;
import io.delphiplatform.api.v3.rdb.service.spotify.SpotifyTrackService;
import io.delphiplatform.api.v3.rdb.service.spotify.SpotifyTracksChartAdditionsService;
import io.delphiplatform.api.v3.rdb.service.spotify.SpotifyTracksChartRemovalsService;
import io.delphiplatform.api.v3.rdb.service.spotify.SpotifyTracksChartsService;
import io.delphiplatform.api.v3.view.util.Params;

@Controller
@RequestMapping("${spring.data.rest.base-path:/v3}")
public class SpotifyChartsApiController implements SpotifyChartsApi {

    @Autowired
    private SpotifyTracksChartsService spotifyTracksChartsService;

    @Autowired
    private SpotifyChartService spotifyChartService;

    @Autowired
    private SpotifyTrackService trackService;

    @Autowired
    private SpotifyChartTrackStateService spotifyChartTrackStateService;

    @Autowired
    private SpotifyChartTrackChangesService spotifyChartTrackChangesService;

    @Autowired
    private SpotifyChartTrackAnalyticsService spotifyChartTrackAnalyticsService;

    @Autowired
    private SpotifyTracksChartAdditionsService spotifyTracksChartAdditionsService;

    @Autowired
    private SpotifyTracksChartRemovalsService spotifyTracksChartRemovalsService;

    @Autowired
    private SpotifyChartsDataHealthStatusService dataHealthStatusService;

    @Override
    public ResponseEntity<SpotifyCharts> getSpotifyCharts(Params params) {
        List<SpotifyChart> spotifyCharts = spotifyChartService.getSpotifyCharts(params);

        return ResponseEntity.ok(new SpotifyCharts(spotifyCharts));
    }

    @Override
    public ResponseEntity<SpotifyChartTrackStates> getSpotifyChartTracks(Params params) {
        List<ChartTrackState> chartTrackStates =
            spotifyChartTrackStateService.getSpotifyChartTracks(addTrackIdsForIsrc(params));

        return ResponseEntity.ok(new SpotifyChartTrackStates(chartTrackStates));
    }

    @Override
    public ResponseEntity<SpotifyChartTrackStates> getSpotifyChartsTracksAdditions(Params params) {
        return ResponseEntity.ok(
            new SpotifyChartTrackStates(
                spotifyChartTrackChangesService.getSpotifyChartTracksAdditions(addTrackIdsForIsrc(params))));
    }

    @Override
    public ResponseEntity<SpotifyChartTrackStates> getSpotifyChartsTracksRemovals(Params params) {
        return ResponseEntity.ok(
            new SpotifyChartTrackStates(
                spotifyChartTrackChangesService.getSpotifyChartTracksRemovals(addTrackIdsForIsrc(params))));
    }

    @Override
    public ResponseEntity<SpotifyTrackChartsSearchResults> getSpotifyTracksCharts(Params params) {
        List<SpotifyTrackChartsSearchResult> trackChartsSearchResults =
            spotifyTracksChartsService.getSpotifyTrackCharts(addTrackIdsForIsrc(params));
        return ResponseEntity.ok(new SpotifyTrackChartsSearchResults(trackChartsSearchResults));
    }

    @Override
    public ResponseEntity<SpotifyTrackChartsSearchResults> getSpotifyTracksChartsAdditions(Params params) {
        List<SpotifyTrackChartsSearchResult> additions = spotifyTracksChartAdditionsService.getSpotifyChartTracksAdditions(
            addTrackIdsForIsrc(params));
        return ResponseEntity.ok(new SpotifyTrackChartsSearchResults(additions));
    }

    @Override
    public ResponseEntity<SpotifyTrackChartsSearchResults> getSpotifyTracksChartsRemovals(Params params) {
        List<SpotifyTrackChartsSearchResult> removals = spotifyTracksChartRemovalsService.getSpotifyChartTracksRemovals(
            addTrackIdsForIsrc(params));
        return ResponseEntity.ok(new SpotifyTrackChartsSearchResults(removals));
    }

    @Override
    public ResponseEntity<SpotifyTrackChartsSearchResults> getSpotifyTracksChartsLifetime(Params params) {
        return ResponseEntity.ok(
            new SpotifyTrackChartsSearchResults(
                spotifyTracksChartsService.getSpotifyTracksChartsLifetime(addTrackIdsForIsrc(params))));
    }

    @Override
    public ResponseEntity<ChartTracksAnalyticsResults> getSpotifyChartsTracksAnalytics(Params params) {
        List<ChartTracksAnalytics> analytics =
            spotifyChartTrackAnalyticsService.getSpotifyChartTracksAnalytics(params);

        return ResponseEntity.ok(new ChartTracksAnalyticsResults(analytics));
    }

    @Override
    public ResponseEntity<SpotifyChartsDataHealthStatusReport<DataHealthStatusSummary>> getSpotifyChartsDataHealthStatus(Params params) {
        return ResponseEntity.ok(dataHealthStatusService.getSpotifyChartsDataHealthStatus(params));
    }

    private Params addTrackIdsForIsrc(Params params) {
        if (
            params.getChartTrackMetricsDimension() != null
            && params.getChartTrackMetricsDimension() == ChartTrackMetricsDimension.ISRC
            && CollectionUtils.isEmpty(params.getIsrc())
            && CollectionUtils.isNotEmpty(params.getTrackId())) {
            return params.toBuilder()
                .trackId(new ArrayList<>(trackService.findTracksWithSameIsrcByTrackId(params.getTrackId())))
                .build();
        }
        return params;
    }

}
