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.VideoChartPosition;
import io.delphiplatform.api.v3.rdb.entity.video.FactYoutubeVideoTrendingChartEntity;
import io.delphiplatform.api.v3.rdb.repository.FactTrendingVideoChartDailyRepository;
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 VideoPositionService extends AbstractVideoPositionService<FactYoutubeVideoTrendingChartEntity> {

    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("position.current", "current_position")
        .put("position.date", "date")
        .put("position.date_gap", "date_gap")
        .put("position.is_entry", "is_entry")
        .put("position.previous_date", "previous_date")
        .put("position.previous_position", "previous_position")
        .put("position.trend", "trend")
        .put("position.is_exit", "is_exit")
        .put("position.is_reentry", "is_reentry")
        .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.views", "video_views")
        .build();

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

    @Autowired
    public VideoPositionService(VideoService videoService,
        FactTrendingVideoChartDailyRepository repository,
        SpecificationProvider<FactYoutubeVideoTrendingChartEntity> specificationProvider,
        ImageService imageService) {
        super(repository, SORT_BY_TO_ENTITY_FIELD_MAP);
        this.videoService = videoService;
        this.specificationProvider = specificationProvider;
        this.imageService = imageService;
    }

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

        Specification<FactYoutubeVideoTrendingChartEntity> spec = and(Arrays.asList(
            specificationProvider.greaterThanOrEqualToValueSpec("date", params.getStartDate()),
            specificationProvider.lessThanOrEqualToValueSpec("date", params.getEndDate()),
            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<FactYoutubeVideoTrendingChartEntity> entities = find(spec, getPageRequestSortByToCamelCase(params));

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

}
