package io.delphiplatform.api.v3.rdb.service.spotify;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import io.delphiplatform.api.util.CollectionUtils;
import io.delphiplatform.api.util.DateUtils;
import io.delphiplatform.api.v3.model.AnalyticsMetrics;
import io.delphiplatform.api.v3.model.charts.ChartTracksAnalytics;
import io.delphiplatform.api.v3.model.charts.ChartTracksAnalyticsMetricGroup;
import io.delphiplatform.api.v3.rdb.entity.spotify.SpotifyChartTrackEntity;
import io.delphiplatform.api.v3.view.util.Params;

@Service
@Transactional(readOnly = true)
public class SpotifyChartTrackAnalyticsService {

    private final SpotifyChartTrackService spotifyChartTrackService;

    @Autowired
    public SpotifyChartTrackAnalyticsService(SpotifyChartTrackService spotifyChartTrackService) {
        this.spotifyChartTrackService = spotifyChartTrackService;
    }

    public List<ChartTracksAnalytics> getSpotifyChartTracksAnalytics(Params params) {
        Map<String, List<SpotifyChartTrackEntity>> entitiesByTrackId = spotifyChartTrackService
            .findChartTracks(params.getSingleChartId(), params.getStartDate(), params.getEndDate(), params.getTrackId(),
                params.getIsrc());

        boolean includesTrackPositions = CollectionUtils
            .contains(params.getAnalyticsMetrics(), AnalyticsMetrics.POSITIONS);

        List<ChartTracksAnalytics> analyticsResponse = new ArrayList<>();

        entitiesByTrackId.forEach((trackId, entities) -> {
            final LocalDate minDate =
                DateUtils.getMinDate(entities.stream().map(SpotifyChartTrackEntity::getChartDate));
            final LocalDate maxDate =
                DateUtils.getMaxDate(entities.stream().map(SpotifyChartTrackEntity::getChartDate));

            Set<String> trackIsrcs = entities.stream()
                .map(SpotifyChartTrackEntity::getIsrc)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

            analyticsResponse.add(ChartTracksAnalytics.of(
                trackId,
                minDate,
                maxDate,
                CollectionUtils.getIntSummaryStatistics(
                    entities.stream().map(SpotifyChartTrackEntity::getCurrentPosition)
                ),
                includesTrackPositions ?
                    ChartTracksAnalyticsMetricGroup
                        .of(minDate, maxDate, entities) : null,
                trackIsrcs
            ));
        });

        return analyticsResponse;
    }

}
