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

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.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import io.delphiplatform.api.util.JpaUtils;
import io.delphiplatform.api.v3.model.apple.music.AppleMusicChart;
import io.delphiplatform.api.v3.rdb.entity.apple.music.AppleMusicChartEntity;
import io.delphiplatform.api.v3.rdb.repository.apple.music.AppleMusicChartRepository;
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;

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.CHART_RANK;
import static io.delphiplatform.api.v3.rdb.entity.CommonJpaPropertyNames.MARKET_RANK;

@Service
@Transactional(readOnly = true)
public class AppleMusicChartService {

    private final SpecificationProvider<AppleMusicChartEntity> specificationProvider;
    private final AppleMusicChartRepository repository;

    @Autowired
    public AppleMusicChartService(
        SpecificationProvider<AppleMusicChartEntity> specificationProvider,
        AppleMusicChartRepository repository
    ) {
        this.specificationProvider = specificationProvider;
        this.repository = repository;
    }

    public List<AppleMusicChart> getAppleMusicCharts(Params params) {
        Set<JpaPropertyPath> fetches = Set.of(JpaPropertyPath.ofJoin(MARKET_RANK));

        Specification<AppleMusicChartEntity> spec = JpaUtils.and(Arrays.asList(
            specificationProvider.multiValueSpec(APPLE_MUSIC_CHART_ID, params.getChartId()),
            specificationProvider.multiValueSpec(APPLE_MUSIC_COUNTRY_ID, params.getCountryCode()),
            specificationProvider.greaterThanOrEqualToValueSpec(CHART_RANK, params.getMinRank(),
                Collections.singletonList(MARKET_RANK)),
            specificationProvider.lessThanOrEqualToValueSpec(CHART_RANK, params.getMaxRank(),
                Collections.singletonList(MARKET_RANK)),
            specificationProvider.fetchesSpecOfPaths(fetches)
        ));

        return repository.findAll(spec)
            .stream()
            .map(AppleMusicChart::of)
            .collect(Collectors.toList());
    }

    public List<AppleMusicChartEntity> findChartsByIdsWithMarketRank(Collection<String> chartsIds) {
        Set<JpaPropertyPath> fetches = Set.of(JpaPropertyPath.ofJoin(MARKET_RANK));

        Specification<AppleMusicChartEntity> spec = JpaUtils.and(Arrays.asList(
            specificationProvider.multiValueSpec(APPLE_MUSIC_CHART_ID, chartsIds),

            specificationProvider.fetchesSpecOfPaths(fetches)
        ));

        return repository.findAll(spec);
    }
}
