package ru.yandex.qe.dispenser.ws.quota.request.unbalanced;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import ru.yandex.qe.dispenser.domain.QuotaChangeRequest;
import ru.yandex.qe.dispenser.domain.dao.quota.request.QuotaChangeRequestDao;

/**
 * Transaction wrapper for page of request.
 *
 * @author Ruslan Kadriev <aqru@yandex-team.ru>
 */
@Component
public class QuotaChangeUnbalanceRefreshTransactionWrapper {
    public static final long LIMIT = 100L;

    private final QuotaChangeRequestDao quotaChangeRequestDao;
    private final QuotaChangeUnbalancedManager quotaChangeUnbalancedManager;

    public QuotaChangeUnbalanceRefreshTransactionWrapper(QuotaChangeRequestDao quotaChangeRequestDao,
                                                         QuotaChangeUnbalancedManager quotaChangeUnbalancedManager                                                         ) {
        this.quotaChangeRequestDao = quotaChangeRequestDao;
        this.quotaChangeUnbalancedManager = quotaChangeUnbalancedManager;
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public Long execute(Long fromId) {
        Set<Long> campaignIds = quotaChangeUnbalancedManager.getCampaignIds();
        List<QuotaChangeRequest> list = getRequests(fromId, campaignIds);

        if (list.isEmpty()) {
            return null;
        }

        Map<Long, Boolean> unbalancedByRequestId = quotaChangeUnbalancedManager.calculateFromRequests(list).stream()
                .collect(Collectors.toMap(QuotaChangeRequestUnbalancedResult::getRequestId,
                        QuotaChangeRequestUnbalancedResult::isUnbalanced, (a, b) -> !a ? b : true));

        updateUnbalance(unbalancedByRequestId);

        return list.get(list.size()-1).getId();
    }

    private List<QuotaChangeRequest> getRequests(Long fromId, Set<Long> campaignIds) {
        return quotaChangeRequestDao.readRequestsByCampaignsForUpdate(campaignIds, fromId, LIMIT);
    }

    private void updateUnbalance(Map<Long, Boolean> unbalancedByRequestId) {
        quotaChangeRequestDao.updateUnbalanced(unbalancedByRequestId);
    }
}
