package io.delphiplatform.api.v3.bigtable.processing;

import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.Set;
import java.util.stream.Stream;

import fr.xebia.extras.selma.Selma;
import io.delphiplatform.api.util.CollectionUtils;
import io.delphiplatform.api.v3.bigtable.entity.YouTubeVideoStats;
import io.delphiplatform.api.v3.model.mapper.AgeBandsMapper;
import io.delphiplatform.api.v3.model.mapper.GendersMapper;
import io.delphiplatform.api.v3.model.mapper.TrafficSourceTypesMapper;
import io.delphiplatform.api.v3.model.mapper.YouTubeDeviceTypeMapper;
import io.delphiplatform.api.v3.model.mapper.YouTubeMetricsMapper;
import io.delphiplatform.api.v3.model.mapper.YouTubeOperatingSystemMapper;
import io.delphiplatform.api.v3.model.video.YouTubeDimensions;
import io.delphiplatform.api.v3.model.video.YouTubeMetrics;
import io.delphiplatform.api.v3.model.video.YouTubeSummaryItem;
import io.delphiplatform.api.v3.model.video.YoutubeContentType;
import lombok.extern.slf4j.Slf4j;

import static com.sonymusic.delphi.etl.apps.proto.Youtube.YoutubeAgeBands;
import static com.sonymusic.delphi.etl.apps.proto.Youtube.YoutubeDeviceType;
import static com.sonymusic.delphi.etl.apps.proto.Youtube.YoutubeGenders;
import static com.sonymusic.delphi.etl.apps.proto.Youtube.YoutubeOperatingSystem;
import static com.sonymusic.delphi.etl.apps.proto.Youtube.YoutubeStats;
import static com.sonymusic.delphi.etl.apps.proto.Youtube.YoutubeTrafficSource;
import static com.sonymusic.delphi.etl.apps.proto.Youtube.YoutubeWatchTime;

@Slf4j
@Service
public class YouTubeSummariesConverter {

    private final AgeBandsMapper ageBandsMapper;
    private final GendersMapper gendersMapper;
    private final TrafficSourceTypesMapper trafficSourceTypesMapper;
    private final YouTubeMetricsMapper youTubeMetricsMapper;
    private final YouTubeDeviceTypeMapper deviceTypeMapper;
    private final YouTubeOperatingSystemMapper operatingSystemMapper;

    public YouTubeSummariesConverter() {
        gendersMapper = Selma.builder(GendersMapper.class).build();
        ageBandsMapper = Selma.builder(AgeBandsMapper.class).build();
        trafficSourceTypesMapper = Selma.builder(TrafficSourceTypesMapper.class).build();
        deviceTypeMapper = Selma.builder(YouTubeDeviceTypeMapper.class).build();
        operatingSystemMapper = Selma.builder(YouTubeOperatingSystemMapper.class).build();
        youTubeMetricsMapper = Selma.builder(YouTubeMetricsMapper.class).build();
    }

    public Stream<YouTubeSummaryItem> convert(Stream<YouTubeVideoStats> youTubeVideoStats, Set<String> countryCodes) {
        boolean filterCountries = CollectionUtils.isNotEmpty(countryCodes);
        return youTubeVideoStats.flatMap(videoStats ->
            getAllCountries(videoStats).stream()
                .filter(filterCountries ? country -> CollectionUtils.contains(countryCodes, country) : country -> true)
                .map(country -> {
                    YoutubeStats streams = videoStats.getStreams() == null ? null
                        : videoStats.getStreams().getCountriesMap().get(country);
                    YoutubeStats demographics = videoStats.getDemographics() == null ? null
                        : videoStats.getDemographics().getCountriesMap().get(country);

                    YouTubeSummaryItem summaryItem = new YouTubeSummaryItem();
                    YouTubeDimensions dimensions = new YouTubeDimensions();
                    dimensions.date(videoStats.getDate());
                    dimensions.countryCode(country);
                    dimensions.videoId(videoStats.getVideoId());
                    dimensions.isrc(videoStats.getIsrc());
                    dimensions.projectNumber(videoStats.getProjectNumber());
                    dimensions.productFamilyId(videoStats.getProductFamilyId());
                    dimensions.contentType(YoutubeContentType.fromValue(videoStats.getContentType()));

                    summaryItem.setDimensions(dimensions);

                    YouTubeMetrics metrics = new YouTubeMetrics();
                    if (streams != null) {
                        YoutubeWatchTime watchTime = streams.getWatchTime();
                        if (watchTime != null) {
                            metrics.averageViewDurationPercentage(watchTime.getAverageViewDurationPercentage());
                            metrics.averageViewDurationSeconds(watchTime.getAverageViewDurationSeconds());
                        }
                        metrics = youTubeMetricsMapper.fillMetrics(metrics, streams.getEngagement());
                        metrics.views(streams.getStreams().getViews());

                        YoutubeTrafficSource sourceTrafficSource = streams.getTrafficSource();
                        metrics.trafficSourceTypes(trafficSourceTypesMapper.toTrafficSourceTypes(sourceTrafficSource));

                        YoutubeDeviceType deviceType = streams.getDeviceType();
                        metrics.deviceType(deviceTypeMapper.toDeviceType(deviceType));

                        YoutubeOperatingSystem operatingSystem = streams.getOperatingSystem();
                        metrics.operatingSystem(operatingSystemMapper.toOperatingSystem(operatingSystem));
                    }

                    if (demographics != null) {
                        YoutubeAgeBands sourceAgeBands = demographics.getDemographic().getAgeBandViewsPercentages();
                        metrics.ageBandViewsPercentages(ageBandsMapper.toAgeBands(sourceAgeBands));

                        YoutubeGenders sourceGenders = demographics.getDemographic().getGenderViewPercentages();
                        metrics.genderViewsPercentages(gendersMapper.toGender(sourceGenders));
                    }
                    summaryItem.setMetrics(metrics);
                    return summaryItem;
                }));
    }

    private Set<String> getAllCountries(YouTubeVideoStats videoStats) {
        Set<String> allCountries = new HashSet<>();

        if (videoStats.getStreams() != null && videoStats.getStreams().getCountriesMap() != null) {
            allCountries.addAll(videoStats.getStreams().getCountriesMap().keySet());
        }

        if (videoStats.getDemographics() != null && videoStats.getDemographics().getCountriesMap() != null) {
            allCountries.addAll(videoStats.getDemographics().getCountriesMap().keySet());
        }
        return allCountries;
    }

}
