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

import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import io.delphiplatform.api.util.CollectionUtils;
import io.delphiplatform.api.v3.model.tiktok.top.video.TikTokTopIsrcVideo;
import io.delphiplatform.api.v3.model.tiktok.top.video.TikTokTopIsrcVideoTopBy;
import io.delphiplatform.api.v3.model.tiktok.top.video.TikTokTopIsrcVideos;
import io.delphiplatform.api.v3.model.video.ExpandTo;
import io.delphiplatform.api.v3.rdb.entity.tiktok.video.FactTikTokTopVideoChartEntity;
import io.delphiplatform.api.v3.rdb.entity.tiktok.video.TikTokTopVideoLifetimeProjection;
import io.delphiplatform.api.v3.rdb.repository.tiktok.video.TikTokTopVideoChartRepository;
import io.delphiplatform.api.v3.rdb.repository.tiktok.video.TikTokTopVideoLifetimeRepository;
import io.delphiplatform.api.v3.rdb.service.EntityService;
import io.delphiplatform.api.v3.rdb.service.TrackService;
import io.delphiplatform.api.v3.rdb.service.specification.SpecificationProvider;
import io.delphiplatform.api.v3.view.util.Params;

@Service
public class TikTokIsrcTopVideoService extends EntityService<FactTikTokTopVideoChartEntity> {


    private final TikTokTopVideoChartRepository videoChartRepository;

    private final TikTokTopVideoLifetimeRepository videoLifetimeRepository;
    private final TrackService trackService;

    private final SpecificationProvider<FactTikTokTopVideoChartEntity> videoChartEntitySpecificationProvider;

    public TikTokIsrcTopVideoService(TikTokTopVideoChartRepository videoChartRepository,
        TikTokTopVideoLifetimeRepository videoLifetimeRepository, TrackService trackService,
        SpecificationProvider<FactTikTokTopVideoChartEntity> videoChartEntitySpecificationProvider) {
        super(videoChartRepository);
        this.videoChartRepository = videoChartRepository;
        this.videoLifetimeRepository = videoLifetimeRepository;
        this.trackService = trackService;
        this.videoChartEntitySpecificationProvider = videoChartEntitySpecificationProvider;
    }

    public TikTokTopIsrcVideos getTopVideosForIsrc(Params params) {

        return getTopVideosForIsrc(params.getIsrc(), params.getExpandTo(), params.getTikTokTopIsrcVideoTopBy(), params.getLimit());
    }

    private TikTokTopIsrcVideos getTopVideosForIsrc(List<String> isrc, Set<ExpandTo> expandTo,
        TikTokTopIsrcVideoTopBy tikTokTopIsrcVideoTopBy, Integer limit) {

        Set<String> isrcsToRequest = CollectionUtils.contains(expandTo, ExpandTo.RELATED_ISRCS)
            ? getRelatedIsrc(isrc)
            : Set.copyOf(isrc);

        List<FactTikTokTopVideoChartEntity> videoChartEntities = videoChartRepository.findAllByIsrcInAndTikTokChartId(
            isrcsToRequest, tikTokTopIsrcVideoTopBy.getDbValue());

        Set<String> allVideoIdsForIsrcs = videoChartEntities.stream().flatMap(e -> Stream.of(e.getVideoIds())).collect(Collectors.toSet());

        List<TikTokTopVideoLifetimeProjection> tikTokVideos = videoLifetimeRepository.findTikTokVideos(
            allVideoIdsForIsrcs,
            tikTokTopIsrcVideoTopBy.getDbValue(),
            PageRequest.of(0, limit));
        List<TikTokTopIsrcVideo> result = tikTokVideos
            .stream()
            .sorted(Comparator.comparing(TikTokTopVideoLifetimeProjection::getPosition))
            .map(TikTokTopIsrcVideo::of)
            .collect(Collectors.toList());

        return TikTokTopIsrcVideos.of(result);
    }

    private Set<String> getRelatedIsrc(List<String> isrc) {
        Set<String> relatedIsrcs = trackService.findRelatedIsrc(isrc);
        if (CollectionUtils.isEmpty(relatedIsrcs) && CollectionUtils.isNotEmpty(isrc)) {
            return new HashSet<>(isrc);
        }
        return relatedIsrcs;
    }

}
