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

import com.google.common.collect.ImmutableMap;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import io.delphiplatform.api.util.CollectionUtils;
import io.delphiplatform.api.v3.model.service.ImageService;
import io.delphiplatform.api.v3.model.video.IncludeVideoChart;
import io.delphiplatform.api.v3.model.video.VideoChartPositionSummary;
import io.delphiplatform.api.v3.rdb.entity.video.TrendingVideoChartSummaryReportEntity;
import io.delphiplatform.api.v3.rdb.repository.TrendingVideoChartSummaryReportRepository;
import io.delphiplatform.api.v3.rdb.service.dto.JpaPropertyPath;
import io.delphiplatform.api.v3.rdb.service.specification.SpecificationProvider;
import io.delphiplatform.api.v3.view.util.Params;

@Service
@Transactional(readOnly = true)
public class VideoPositionSummaryService extends AbstractVideoPositionService<TrendingVideoChartSummaryReportEntity> {

    private static final ImmutableMap<String, String> SORT_BY_TO_ENTITY_FIELD_MAP = ImmutableMap.<String, String>builder()
        .put("chart.chart_id", "chart_chart_id")
        .put("chart.name", "chart_name")
        .put("chart.chart_group", "chart_chart_group")
        .put("chart.country_code", "chart_country_code_region_id")
        .put("chart.dsp", "chart_dsp_name")
        .put("chart.total_positions", "chart_num_tracks")

        .put("summary.earliest_position", "earliest_position")
        .put("summary.earliest_position_date", "earliest_position_date")
        .put("summary.latest_position", "latest_position")
        .put("summary.latest_position_date", "latest_position_date")
        .put("summary.max_position", "max_position")
        .put("summary.max_position_date", "max_position_date")
        .put("summary.min_position", "min_position")
        .put("summary.min_position_date", "min_position_date")
        .put("summary.total_days", "total_days")

        .put("video_id", "video_video_id")
        .put("video.video_id", "video_video_id")
        .put("video.video_title", "video_title")
        .put("video.channel_id", "video_channel_channel_id")
        .put("video.dsp_channel_id", "video_dsp_channel_id")
        .put("video.channel_title", "video_channel_title")
        .put("video.content_type", "video_content_type")
        .put("video.date_uploaded", "video_date_uploaded")
        .put("video.dsp", "video_dsp")
        .put("video.dsp_video_id", "video_dsp_video_id")
        .put("video.duration_seconds", "video_duration_seconds")
        .put("video.is_sony", "is_sony")
        .put("video.views", "video_views")
        .build();

    private final VideoService videoService;
    private final SpecificationProvider<TrendingVideoChartSummaryReportEntity> specificationProvider;
    private final ImageService imageService;

    @Autowired
    public VideoPositionSummaryService(VideoService videoService,
        TrendingVideoChartSummaryReportRepository repository,
        SpecificationProvider<TrendingVideoChartSummaryReportEntity> specificationProvider,
        ImageService imageService) {
        super(repository, SORT_BY_TO_ENTITY_FIELD_MAP);
        this.videoService = videoService;
        this.specificationProvider = specificationProvider;
        this.imageService = imageService;
    }

    public List<VideoChartPositionSummary> getVideoChartPositionSummaries(Params params) {
        List<String> videoIds = videoService.getVideoIds(params);
        if (CollectionUtils.isEmpty(videoIds) && params.hasAnyVideoParams()) {
            return Collections.emptyList();
        }
        Set<JpaPropertyPath> requestFetches = getFetches(params);

        Specification<TrendingVideoChartSummaryReportEntity> spec = and(Arrays.asList(
            specificationProvider.singleValueSpec("chartGroup", params.getChartGroup(),
                "chart"),
            specificationProvider.multiValueSpec("chartId", params.getChartId(),
                "chart"),
            specificationProvider.multiValueSpec("regionId", params.getCountryCode(), "region"),
            specificationProvider.multiValueSpec("videoId", videoIds, "video"),
            specificationProvider.singleValueSpec("isSony", params.getIsSonyVideo(), "video"),

            specificationProvider.fetchesSpecOfPaths(requestFetches)
        ));

        List<TrendingVideoChartSummaryReportEntity> entities = find(spec, getPageRequestSortByToCamelCase(params));

        return entities.stream()
            .map(e -> VideoChartPositionSummary.of(e, imageService,
                CollectionUtils.contains(params.getIncludeVideChart(), IncludeVideoChart.VIDEO)))
            .collect(Collectors.toList());
    }

}
