package io.delphiplatform.api.v3.rdb.service.apple.music;

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.Collections;
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.apple.music.AppleMusicChartTrackEntity;
import io.delphiplatform.api.v3.view.util.Params;

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

    private final AppleMusicTrackService trackService;
    private final AppleMusicChartTrackService chartTrackService;

    @Autowired
    public AppleMusicChartTrackAnalyticsService(AppleMusicTrackService trackService,
        AppleMusicChartTrackService chartTrackService) {
        this.trackService = trackService;
        this.chartTrackService = chartTrackService;
    }

    public List<ChartTracksAnalytics> getAppleMusicChartTracksAnalytics(Params params) {
        Set<String> trackIds = trackService.findAppleMusicTrackIds(params.getTrackId(), params.getIsrc());

        if (CollectionUtils.isEmpty(trackIds)
            && (CollectionUtils.isNotEmpty(params.getTrackId()) || CollectionUtils.isNotEmpty(params.getIsrc()))) {

            return Collections.emptyList();
        }

        LocalDate startDate = params.getStartDate();
        LocalDate endDate = params.getEndDate();

        Map<String, List<AppleMusicChartTrackEntity>> entitiesByTrackId =
            chartTrackService.findChartTracks(params.getSingleChartId(), trackIds, startDate, endDate);

        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(AppleMusicChartTrackEntity::getChartDate));
            final LocalDate maxDate =
                DateUtils.getMaxDate(entities.stream().map(AppleMusicChartTrackEntity::getChartDate));

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

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

        return analyticsResponse;
    }

}
