package ru.yandex.qe.dispenser.ws.quota.request.owning_cost.campaignOwningCost;

import java.math.BigInteger;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

import org.springframework.stereotype.Component;

import ru.yandex.qe.dispenser.domain.CampaignOwningCost;
import ru.yandex.qe.dispenser.domain.dao.campaign.CampaignOwningCostCache;
import ru.yandex.qe.dispenser.domain.dao.campaign.CampaignOwningCostDao;
import ru.yandex.qe.dispenser.ws.quota.request.owning_cost.QuotaChangeOwningCostManager;

/**
 * Manager for refresh calculated owning cost for campaign.
 *
 * @author Ruslan Kadriev <aqru@yandex-team.ru>
 */
@Component
public class CampaignOwningCostRefreshManager {
    private final CampaignOwningCostRefreshTransactionWrapper campaignOwningCostRefreshTransactionWrapper;
    private final QuotaChangeOwningCostManager quotaChangeOwningCostManager;
    private final CampaignOwningCostDao campaignOwningCostDao;
    private final CampaignOwningCostCache campaignOwningCostCache;

    public CampaignOwningCostRefreshManager(CampaignOwningCostRefreshTransactionWrapper campaignOwningCostRefreshTransactionWrapper,
                                            QuotaChangeOwningCostManager quotaChangeOwningCostManager,
                                            CampaignOwningCostDao campaignOwningCostDao,
                                            CampaignOwningCostCache campaignOwningCostCache) {
        this.campaignOwningCostRefreshTransactionWrapper = campaignOwningCostRefreshTransactionWrapper;
        this.quotaChangeOwningCostManager = quotaChangeOwningCostManager;
        this.campaignOwningCostDao = campaignOwningCostDao;
        this.campaignOwningCostCache = campaignOwningCostCache;
    }

    public void refresh() {
        Map<Long, BigInteger> owningCostByCampaignId = new ConcurrentHashMap<>();
        quotaChangeOwningCostManager.getCampaignIds().stream()
                .parallel()
                .forEach(campaignId -> owningCostByCampaignId.put(campaignId, campaignOwningCostRefreshTransactionWrapper.refresh(campaignId)));
        Collection<CampaignOwningCost> campaignOwningCosts = toCampaignOwningCost(owningCostByCampaignId);
        campaignOwningCostDao.upsertAll(campaignOwningCosts);
        campaignOwningCostCache.refresh();
    }

    private Collection<CampaignOwningCost> toCampaignOwningCost(Map<Long, BigInteger> owningCostByCampaignId) {
        return owningCostByCampaignId.entrySet().stream()
                .filter(e -> e.getValue() != null)
                .map(e -> CampaignOwningCost.builder()
                        .campaignId(e.getKey())
                        .owningCost(e.getValue())
                        .build())
                .collect(Collectors.toList());
    }
}
