package io.delphiplatform.api.v3.view.util;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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.AggBy;
import io.delphiplatform.api.v3.model.SortOrder;
import io.delphiplatform.api.v3.rdb.entity.TrackEntity;
import io.delphiplatform.api.v3.rdb.service.ArtistService;
import io.delphiplatform.api.v3.rdb.service.GroupByType;
import io.delphiplatform.api.v3.rdb.service.TrackService;

@Service
public class ParamsHelper {

    private final TrackService trackService;
    private final ArtistService artistService;

    public ParamsHelper(
        TrackService trackService,
        ArtistService artistService
    ) {
        this.trackService = trackService;
        this.artistService = artistService;
    }

    @Transactional(readOnly = true)
    public Params loadAdditionalParamsForTrackPositions(Params params) {
        //if requested by artistId and no filtering by isrc - find all isrc's(tracks) for this artist and use all of them for positions lookup
        if (CollectionUtils.isNotEmpty(params.getArtistId())
            && CollectionUtils.isEmpty(params.getIsrc())) {

            List<TrackEntity> tracks = trackService.findAudioTracks(GroupByType.ISRC, params.getArtistId(), null);
            List<String> isrcs = tracks.stream()
                .map(TrackEntity::getIsrc)
                .collect(Collectors.toList());
            return params.toBuilder().isrc(isrcs).build();
        }

        return params;
    }

    @Transactional(readOnly = true)
    public Params loadAdditionalParamsForTrackStreams(Params params) {
        //if requested by artistId - in several cases we need to load additional params
        if (CollectionUtils.isNotEmpty(params.getArtistId())
            && CollectionUtils.isEmpty(params.getIsrc())) {

            //if requested by artistId with AggBy=ARTIST - just use this artistId for streams lookup
            if (params.getAggBy() == AggBy.ARTIST) {
                return params;
            }

            //if requested by artistId with AggBy=ISRC - find all isrc's(tracks) for this artist and use all of them for streams lookup
            if (params.getAggBy() == AggBy.ISRC) {
                List<TrackEntity> tracks = trackService.findAudioTracks(GroupByType.ISRC, params.getArtistId(), null);
                List<String> isrcs = tracks.stream()
                    .map(TrackEntity::getIsrc)
                    .collect(Collectors.toList());
                return params.toBuilder().isrc(isrcs).build();
            }

            //if requested by artistId with AggBy=null - resolve artistId into multiple and use all of them for streams lookup (DAE-7935)
            if (params.getAggBy() == null) {
                Set<String> artists = artistService.findArtistIdsByParticipantId(params.getArtistId());
                return params.toBuilder().additionalArtistIds(artists).build();
            }
        }

        return params;
    }

    public List<SortWithOrder> parseSortingLists(List<String> sortByList, List<SortOrder> sortOrderList) {
        if (CollectionUtils.isEmpty(sortByList)) {
            return Collections.emptyList();
        }

        return CollectionUtils.zipLists(sortByList, sortOrderList).stream()
            .map(SortWithOrder::new)
            .collect(Collectors.toList());
    }
}
