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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;

import io.delphiplatform.api.util.CollectionUtils;
import io.delphiplatform.api.v3.constant.DspConstants;
import io.delphiplatform.api.v3.model.StreamsCountryCodeRankInfo;
import io.delphiplatform.api.v3.rdb.service.amazon.AmazonMarketRankService;
import io.delphiplatform.api.v3.rdb.service.apple.music.AppleMusicMarketRankService;
import io.delphiplatform.api.v3.rdb.service.spotify.SpotifyMarketRankService;
import io.delphiplatform.api.v3.view.util.Params;

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

    private final SpotifyMarketRankService spotifyMarketRankService;
    private final AppleMusicMarketRankService appleMusicMarketRankService;
    private final AmazonMarketRankService amazonMarketRankService;

    @Autowired
    public MarketRankService(
        SpotifyMarketRankService spotifyMarketRankService,
        AppleMusicMarketRankService appleMusicMarketRankService,
        AmazonMarketRankService amazonMarketRankService
    ) {
        this.spotifyMarketRankService = spotifyMarketRankService;
        this.appleMusicMarketRankService = appleMusicMarketRankService;
        this.amazonMarketRankService = amazonMarketRankService;
    }

    @Transactional(readOnly = true)
    public Map<String, List<StreamsCountryCodeRankInfo>> getStreamsMarketRank(Params params) {
        Map<String, List<StreamsCountryCodeRankInfo>> marketRanksByDsp = new HashMap<>();
        List<String> requestedDsps = new ArrayList<>();

        if (CollectionUtils.isNotEmpty(params.getDsp())) {
            requestedDsps.addAll(params.getDsp());
        } else {
            requestedDsps.addAll(List.of(DspConstants.SPOTIFY, DspConstants.APPLE, DspConstants.AMAZON));
        }

        if (requestedDsps.contains(DspConstants.SPOTIFY)) {
            marketRanksByDsp.put(
                DspConstants.SPOTIFY,
                spotifyMarketRankService.findByCountryId(params.getCountryCode())
                    .stream()
                    .map(StreamsCountryCodeRankInfo::from)
                    .sorted(Comparator.comparing(StreamsCountryCodeRankInfo::getRank))
                    .collect(Collectors.toList())
            );
        }

        if (requestedDsps.contains(DspConstants.APPLE)) {
            marketRanksByDsp.put(
                DspConstants.APPLE,
                appleMusicMarketRankService.findByCountryId(params.getCountryCode())
                    .stream()
                    .map(StreamsCountryCodeRankInfo::from)
                    .sorted(Comparator.comparing(StreamsCountryCodeRankInfo::getRank))
                    .collect(Collectors.toList())
            );
        }

        if (requestedDsps.contains(DspConstants.AMAZON)) {
            marketRanksByDsp.put(
                DspConstants.AMAZON,
                amazonMarketRankService.findByCountryId(params.getCountryCode())
                    .stream()
                    .map(StreamsCountryCodeRankInfo::from)
                    .sorted(Comparator.comparing(StreamsCountryCodeRankInfo::getRank))
                    .collect(Collectors.toList())
            );
        }

        return marketRanksByDsp.entrySet().stream()
            .sorted(Entry.comparingByKey())
            .collect(Collectors.toMap(
                Entry::getKey,
                Entry::getValue,
                (m1, m2) -> m1,
                LinkedHashMap::new
            ));
    }
}
