package ru.yandex.qe.dispenser.ws.param;

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

import javax.ws.rs.QueryParam;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.google.common.collect.Sets;

import ru.yandex.qe.dispenser.domain.Campaign;
import ru.yandex.qe.dispenser.domain.Service;
import ru.yandex.qe.dispenser.domain.dao.bot.service.reserve.BotReserveDao;
import ru.yandex.qe.dispenser.domain.dao.bot.service.reserve.BotServiceReserveFilterImpl;
import ru.yandex.qe.dispenser.domain.dao.campaign.CampaignDao;

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE)
public class BotServiceReserveFilterParam {
    @QueryParam("service")
    private Set<Service> services;
    @QueryParam("bigorder")
    private Set<Long> bigOrderIds;
    @QueryParam("campaign")
    private Set<Long> campaigns;
    @QueryParam("campaignBigOrders")
    private Set<Long> campaignBigOrders;

    public <T> Stream<T> getFilteredReserveStream(final BotReserveDao<T> reserveDao, final CampaignDao campaignDao) {
        final BotServiceReserveFilterImpl filter = new BotServiceReserveFilterImpl();

        filter.setBigOrderIds(bigOrderIds);
        filter.setServices(services);
        filter.setCampaignIds(campaigns);

        if (!campaignBigOrders.isEmpty()) {
            final List<Campaign.CampaignOrder> campaignOrders = campaignDao.getCampaignOrders(campaignBigOrders);
            if (campaignOrders.size() != campaignBigOrders.size()) {
                final Set<Long> actualCampaignOrderIds = campaignOrders.stream().map(Campaign.CampaignOrder::getId).collect(Collectors.toSet());
                final Set<Long> missingCampaignOrderIds = Sets.difference(campaignBigOrders, actualCampaignOrderIds);
                throw new IllegalArgumentException("Invalid campaign order ids: " + missingCampaignOrderIds.stream()
                        .map(Object::toString).collect(Collectors.joining(", ")));
            }
            filter.setCampaignBigOrders(new HashSet<>(campaignOrders));
        }

        return reserveDao.getReserveStreamFiltered(filter);
    }
}
