package ru.yandex.qe.dispenser.ws.quota.update;

import java.time.Instant;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import ru.yandex.qe.dispenser.domain.Quota;
import ru.yandex.qe.dispenser.domain.QuotaHistoryEvent;
import ru.yandex.qe.dispenser.domain.QuotaView;
import ru.yandex.qe.dispenser.domain.dao.history.quota.QuotaHistoryDao;
import ru.yandex.qe.dispenser.domain.dao.quota.QuotaDao;
import ru.yandex.qe.dispenser.domain.dao.quota.QuotaUtils;
import ru.yandex.qe.dispenser.ws.quota.request.workflow.context.PerformerContext;

@Component
public class QuotaUpdateManager {

    @Autowired
    private QuotaDao quotaDao;

    @Autowired
    private QuotaHistoryDao quotaHistoryDao;

    public Collection<QuotaView> updateQuota(final Quota.ChangeHolder changeHolder, final PerformerContext ctx, final String issueKey) {
        final Set<Quota.Key> quotaKeysWithMaxChanges = changeHolder.getQuotaKeysWithMaxChanges();
        final Set<Quota> quotas = QuotaUtils.lockNearestQuotas(quotaDao, changeHolder);
        final Collection<QuotaView> quotaViews = quotaDao.checkAndApplyChanges(changeHolder, quotas);
        final Instant now = Instant.now();

        final List<QuotaHistoryEvent> history = quotas.stream()
                .filter(q -> quotaKeysWithMaxChanges.contains(q.getKey()))
                .filter(q -> {
                    final Long max = changeHolder.getMax(q.getKey());
                    final Long ownMax = changeHolder.getOwnMax(q.getKey());
                    return max != null && max != q.getMax() || ownMax != null && ownMax != q.getOwnMax();
                })
                .map(q -> {
                    final Long newMax = changeHolder.getMax(q.getKey());
                    final Long newOwnMax = changeHolder.getOwnMax(q.getKey());
                    return new QuotaHistoryEvent(ctx.getPerson().getId(), ctx.getTvmId(), now, ctx.getComment(), q.getId(), q.getKey(),
                            q.getMax(), newMax != null ? newMax : q.getMax(), q.getOwnMax(), newOwnMax != null ? newOwnMax : q.getOwnMax(), issueKey);
                })
                .collect(Collectors.toList());
        quotaHistoryDao.create(history);

        return quotaViews;
    }
}
