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

import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import io.delphiplatform.api.util.CollectionUtils;
import io.delphiplatform.api.v3.constant.CountryCodeConstant;
import io.delphiplatform.api.v3.constant.DspConstants;
import io.delphiplatform.api.v3.model.Playlist;
import io.delphiplatform.api.v3.model.trackposition.PlaylistTrackPosition;
import io.delphiplatform.api.v3.model.PlaylistableModel;
import io.delphiplatform.api.v3.rdb.entity.PlaylistCountryProjection;

@Deprecated
@Service
public class PlaylistManager {

    private final PlaylistService playlistService;

    public PlaylistManager(PlaylistService playlistService) {
        this.playlistService = playlistService;
    }

    public <P extends PlaylistableModel> List<P> populatePlaylists(List<P> models) {
        Set<String> playlistIds = models
            .stream()
            .map(P::getPlaylistId)
            .collect(Collectors.toSet());

        Map<String, Playlist> allById = playlistService.findAllById(playlistIds)
            .stream()
            .collect(Collectors.toMap(Playlist::getPlaylistId, Function.identity()));

        models.forEach(position -> {
            Playlist playlist = allById.get(position.getPlaylistId());
            if (playlist != null) {
                position.setPlaylist(playlist);
            }
        });
        return models;
    }

    public Stream<PlaylistTrackPosition> filterPlaylistsByTypes(
        Stream<PlaylistTrackPosition> trackPositionsStream,
        Collection<String> playlistTypes) {
        if (CollectionUtils.isNotEmpty(playlistTypes)) {
            List<PlaylistTrackPosition> trackPositions = trackPositionsStream.collect(Collectors.toList());

            if (trackPositions.isEmpty()) {
                return Stream.empty();
            }

            Set<String> playlistIds = trackPositions.stream()
                .map(PlaylistTrackPosition::getPlaylistId)
                .collect(Collectors.toSet());

            Map<String, Playlist> allById = playlistService.findAllById(playlistIds).stream()
                .collect(Collectors.toMap(Playlist::getPlaylistId, Function.identity()));
            return trackPositions.stream()
                .filter(position -> {
                    Playlist playlist = allById.get(position.getPlaylistId());
                    return playlist != null && CollectionUtils.contains(playlistTypes, playlist.getPlaylistType());
                });
        } else {
            return trackPositionsStream;
        }
    }

    public Stream<PlaylistTrackPosition> filterPlaylistPositionsByCountryCodes(
        Stream<PlaylistTrackPosition> trackPositionsStream,
        Collection<String> countryCodes
    ) {
        if (CollectionUtils.isNotEmpty(countryCodes)) {
            List<PlaylistTrackPosition> trackPositions = trackPositionsStream.collect(Collectors.toList());

            if (trackPositions.isEmpty()) {
                return Stream.empty();
            }

            Set<String> unknownCountryPlaylistIds = trackPositions.stream()
                .filter(position -> position.getCountryCode() == null && position.getPlaylist() == null)
                .map(PlaylistTrackPosition::getPlaylistId)
                .collect(Collectors.toSet());

            Map<String, String> playlistCountryById = new HashMap<>();

            if (!unknownCountryPlaylistIds.isEmpty()) {
                playlistCountryById.putAll(
                    playlistService.getPlaylistCountries(unknownCountryPlaylistIds)
                        .stream()
                        .filter(prj -> prj.getCountryCodeValue() != null)
                        .collect(Collectors.toMap(
                            PlaylistCountryProjection::getPlaylistId,
                            PlaylistCountryProjection::getCountryCodeValue
                        ))
                );
            }

            return trackPositions.stream()
                .filter(position -> {
                    if (position.getCountryCode() != null) {
                        return countryCodes.contains(position.getCountryCode());

                    } else if (position.getPlaylist() != null) {
                        String countryCode = position.getPlaylist().getCountryCode().orElse(null);
                        return countryCode != null && countryCodes.contains(countryCode);
                    }

                    String countryCode = playlistCountryById.get(position.getPlaylistId());
                    return countryCode != null && countryCodes.contains(countryCode);
                });
        } else {
            return trackPositionsStream;
        }
    }
}
