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

import com.google.common.collect.ImmutableMap;

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

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import io.delphiplatform.api.util.JpaUtils;
import io.delphiplatform.api.v3.rdb.entity.apple.music.AppleMusicChartTrackLifetimeEntity;
import io.delphiplatform.api.v3.rdb.entity.apple.music.AppleMusicIsrcAndChartAndTrackIds;
import io.delphiplatform.api.v3.rdb.entity.apple.music.AppleMusicTrackLocalizedId;
import io.delphiplatform.api.v3.rdb.repository.apple.music.AppleMusicChartTrackLifetimeRepository;
import io.delphiplatform.api.v3.rdb.service.EntityService;
import io.delphiplatform.api.v3.rdb.service.dto.JpaPropertyPath;
import io.delphiplatform.api.v3.rdb.service.specification.SpecificationProvider;

import static io.delphiplatform.api.v3.rdb.entity.CommonJpaPropertyNames.APPLE_MUSIC_CHART_ID;
import static io.delphiplatform.api.v3.rdb.entity.CommonJpaPropertyNames.APPLE_MUSIC_COUNTRY_ID;
import static io.delphiplatform.api.v3.rdb.entity.CommonJpaPropertyNames.APPLE_MUSIC_TRACK_ID;
import static io.delphiplatform.api.v3.rdb.entity.CommonJpaPropertyNames.ARTISTS;
import static io.delphiplatform.api.v3.rdb.entity.CommonJpaPropertyNames.CHART;
import static io.delphiplatform.api.v3.rdb.entity.CommonJpaPropertyNames.CHART_RANK;
import static io.delphiplatform.api.v3.rdb.entity.CommonJpaPropertyNames.ID_PROPERTY;
import static io.delphiplatform.api.v3.rdb.entity.CommonJpaPropertyNames.ISRC;
import static io.delphiplatform.api.v3.rdb.entity.CommonJpaPropertyNames.MARKET_RANK;
import static io.delphiplatform.api.v3.rdb.entity.CommonJpaPropertyNames.TRACK;

@Service
@Transactional(readOnly = true)
public class AppleMusicChartTrackLifetimeService extends EntityService<AppleMusicChartTrackLifetimeEntity> {

    private static final ImmutableMap<String, String> SORT_BY_TO_ENTITY_FIELD_MAP =
        ImmutableMap.<String, String>builder().build();

    private final AppleMusicChartTrackLifetimeRepository repository;
    private final SpecificationProvider<AppleMusicChartTrackLifetimeEntity> specificationProvider;

    public AppleMusicChartTrackLifetimeService(AppleMusicChartTrackLifetimeRepository repository,
        SpecificationProvider<AppleMusicChartTrackLifetimeEntity> specificationProvider) {
        super(repository, SORT_BY_TO_ENTITY_FIELD_MAP);
        this.repository = repository;
        this.specificationProvider = specificationProvider;
    }


    public Map<AppleMusicIsrcAndChartAndTrackIds, AppleMusicChartTrackLifetimeEntity> findTrackLifetimeMetrics(
        Set<String> appleMusicTrackIds,
        String chartId
    ) {
        return repository.findAll(JpaUtils.and(List.of(
                specificationProvider.multiValueSpec(
                    List.of(ID_PROPERTY, APPLE_MUSIC_TRACK_ID), appleMusicTrackIds),
                specificationProvider.singleValueSpec(
                    List.of(ID_PROPERTY, APPLE_MUSIC_CHART_ID), chartId)
            ))).stream()
            .collect(
                Collectors.toMap(AppleMusicChartTrackLifetimeEntity::getIsrcAndCharAndTrackIds, Function.identity()));
    }

    public List<AppleMusicChartTrackLifetimeEntity> findChartTrackLifetimeMetrics(
        Set<String> trackIds, Set<String> isrcs,
        Integer minRank, Integer maxRank,
        Set<String> countryCode
    ) {
        return repository.findAll(JpaUtils.and(Arrays.asList(
            specificationProvider.multiValueSpec(APPLE_MUSIC_TRACK_ID, trackIds),
            specificationProvider.multiValueSpec(ISRC, isrcs),

            specificationProvider.greaterThanOrEqualToValueSpec(CHART_RANK, minRank, List.of(CHART, MARKET_RANK)),
            specificationProvider.lessThanOrEqualToValueSpec(CHART_RANK, maxRank, List.of(CHART, MARKET_RANK)),

            specificationProvider.multiValueSpec(List.of(CHART, APPLE_MUSIC_COUNTRY_ID), countryCode),

            specificationProvider.fetchesSpecOfPaths(List.of(
                JpaPropertyPath.ofJoins(TRACK, ARTISTS),
                JpaPropertyPath.ofJoins(CHART, MARKET_RANK)
            ), true)
        )));
    }

    public Map<AppleMusicTrackLocalizedId, AppleMusicChartTrackLifetimeEntity> findChartTrackLifetimeMetrics(
        List<AppleMusicIsrcAndChartAndTrackIds> trackLifetimeIds) {
        return repository.findAllByIsrcChartAndTrackIdsIn(trackLifetimeIds).stream()
            .collect(Collectors.toMap(e -> new AppleMusicTrackLocalizedId(
                e.getTrack().getAppleMusicTrackId(),
                e.getChart().getAppleMusicCountryId()
            ), Function.identity()));
    }

    public Map<AppleMusicIsrcAndChartAndTrackIds, AppleMusicChartTrackLifetimeEntity> findChartTrackLifetimeMetricsByIds(
        List<AppleMusicIsrcAndChartAndTrackIds> trackLifetimeIds) {
        return repository.findAllByIsrcChartAndTrackIdsIn(trackLifetimeIds).stream()
            .collect(
                Collectors.toMap(AppleMusicChartTrackLifetimeEntity::getIsrcAndCharAndTrackIds, Function.identity()));
    }
}
