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

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

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import io.delphiplatform.api.util.CollectionUtils;
import io.delphiplatform.api.v3.constant.DspConstants;
import io.delphiplatform.api.v3.model.Playlist;
import io.delphiplatform.api.v3.model.service.ImageService;
import io.delphiplatform.api.v3.rdb.entity.ChartmetricToAmazonPlaylistIdMappingProjection;
import io.delphiplatform.api.v3.rdb.entity.PlaylistCountryProjection;
import io.delphiplatform.api.v3.rdb.entity.PlaylistEntity;
import io.delphiplatform.api.v3.rdb.repository.PlaylistRepository;

@Service
public class PlaylistService extends EntityService<PlaylistEntity> {

    private final PlaylistRepository playlistRepository;
    private final ImageService imageService;

    @Autowired
    public PlaylistService(PlaylistRepository playlistRepository, ImageService imageService) {
        super(playlistRepository);
        this.playlistRepository = playlistRepository;
        this.imageService = imageService;
    }

    @Transactional(readOnly = true)
    public List<Playlist> findAllById(Collection<String> ids) {
        return playlistRepository.findAllById(ids)
            .stream()
            .map(pl -> Playlist.from(pl, imageService))
            .collect(Collectors.toList());
    }

    @Transactional(readOnly = true)
    public List<PlaylistCountryProjection> getPlaylistCountries(Collection<String> playlistIds) {
        return playlistRepository.getPlaylistCountries(playlistIds);
    }

    @Transactional(readOnly = true)
    public List<Playlist> findByDsp(Collection<String> dsps, Pageable pageable) {
        Collection<String> dspsToQuery = CollectionUtils.isEmpty(dsps) ? DspConstants.ENABLED_DSPS : dsps;

        List<Playlist> playlists = playlistRepository.findByDsp(dspsToQuery, pageable).stream()
            .map(playlist -> Playlist.from(playlist, imageService))
            .collect(Collectors.toList());

        populatePlaylistsWithAmazonPlaylistId(playlists);

        return playlists;
    }

    @Transactional(readOnly = true)
    public void populatePlaylistsWithAmazonPlaylistId(List<Playlist> playlists) {
        List<Playlist> amazonPlaylists = playlists.stream()
            .filter(p -> DspConstants.AMAZON.equals(p.getDsp().getDspId()))
            .collect(Collectors.toList());

        Map<String, String> cmAmazonPlaylistIdToAmazonPlaylistId = getChartmetricToAmazonPlaylistIdMapping(
            amazonPlaylists.stream()
                .map(Playlist::getPlaylistId)
                .collect(Collectors.toSet())
        )
            .stream()
            .collect(Collectors.toMap(
                ChartmetricToAmazonPlaylistIdMappingProjection::getCmAmazonPlaylistIdWithCountry,
                ChartmetricToAmazonPlaylistIdMappingProjection::getAmazonPlaylistId
            ));

        amazonPlaylists.forEach(p -> {
            //resolve 'amazon playlist id' by 'chartmetric amazon playlist id'
            String amazonPlaylistId = cmAmazonPlaylistIdToAmazonPlaylistId.get(p.getPlaylistId());

            p.setAmazonPlaylistId(amazonPlaylistId);
        });
    }

    @Transactional(readOnly = true)
    public Playlist findOne(String playlistId) {
        Playlist playlist = playlistRepository.findById(playlistId)
            .map(p -> Playlist.from(p, imageService))
            .orElseThrow(NOT_FOUND);

        populatePlaylistsWithAmazonPlaylistId(Collections.singletonList(playlist));

        return playlist;
    }

    @Transactional(readOnly = true)
    public List<ChartmetricToAmazonPlaylistIdMappingProjection> getChartmetricToAmazonPlaylistIdMapping(
        Collection<String> cmAmazonPlaylistIds
    ) {
        if (CollectionUtils.isEmpty(cmAmazonPlaylistIds)) {
            return Collections.emptyList();
        }

        return playlistRepository.getChartmetricToAmazonPlaylistIdMapping(cmAmazonPlaylistIds);
    }
}
