package ru.yandex.direct.web.entity.adgroup.service.cpm;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

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

import ru.yandex.direct.core.entity.adgroup.model.AdGroup;
import ru.yandex.direct.core.entity.adgroup.model.AdGroupSimple;
import ru.yandex.direct.core.entity.campaign.model.Campaign;
import ru.yandex.direct.core.entity.campaign.repository.CampaignRepository;
import ru.yandex.direct.core.entity.currency.model.cpmyndxfrontpage.CpmYndxFrontpageAdGroupPriceRestrictions;
import ru.yandex.direct.core.entity.currency.service.CpmYndxFrontpageCurrencyService;
import ru.yandex.direct.currency.Currency;
import ru.yandex.direct.web.entity.adgroup.model.WebCpmAdGroup;
import ru.yandex.direct.web.entity.adgroup.model.WebCpmAdGroupRetargeting;

import static java.util.Collections.singletonList;
import static org.assertj.core.util.Preconditions.checkState;
import static ru.yandex.direct.utils.CommonUtils.ifNotNull;
import static ru.yandex.direct.utils.FunctionalUtils.mapList;
import static ru.yandex.direct.web.entity.adgroup.converter.AdGroupConverterUtils.convertGeo;
import static ru.yandex.direct.web.entity.adgroup.converter.AdGroupConverterUtils.extractCpmAdGroupType;

@Component
class CpmAdGroupHelper {
    private final CampaignRepository campaignRepository;
    private final CpmYndxFrontpageCurrencyService cpmYndxFrontpageCurrencyService;

    @Autowired
    CpmAdGroupHelper(
            CampaignRepository campaignRepository,
            CpmYndxFrontpageCurrencyService cpmYndxFrontpageCurrencyService) {
        this.campaignRepository = campaignRepository;
        this.cpmYndxFrontpageCurrencyService = cpmYndxFrontpageCurrencyService;
    }

    /**
     * Возвращает фиксированную ставку для новых и измененных условий показа.
     * Если условия показа - ретаргетинги - она находится в Retargeting.priceContext,
     * иначе условия показа - фразы - ставка лежит в AdGroup.autoPrice.singlePrice
     */
    static BigDecimal getGeneralPrice(WebCpmAdGroup adGroup) {
        Double generalPrice;
        if (adGroup.getRetargetings() != null) {
            WebCpmAdGroupRetargeting retargeting = adGroup.getRetargetings().get(0);
            generalPrice = retargeting == null ? null : retargeting.getPriceContext();
        } else {
            generalPrice = adGroup.getGeneralPrice();
        }
        return ifNotNull(generalPrice, BigDecimal::valueOf);
    }

    public Campaign getCampaign(int shard, long campaignId) {
        List<Campaign> campaignsWithStrategy =
                campaignRepository.getCampaignsWithStrategy(shard, singletonList(campaignId));
        checkState(campaignsWithStrategy.size() == 1, "campaign not found");
        return campaignsWithStrategy.get(0);
    }

    public Map<Integer, CpmYndxFrontpageAdGroupPriceRestrictions> getCpmYndxFrontpagePriceRestrictions(
            int shard, List<WebCpmAdGroup> adGroups,
            Currency clientCurrency,
            Campaign campaign) {
        List<AdGroupSimple> fakeCoreAdGroups = mapList(adGroups, adGroup -> new AdGroup()
                .withCampaignId(campaign.getId())
                .withType(ifNotNull(adGroup, a -> extractCpmAdGroupType(a, campaign.getType())))
                .withGeo(ifNotNull(adGroup, a -> convertGeo(a.getGeo()))));
        return cpmYndxFrontpageCurrencyService
                .getAdGroupIndexesToPriceDataMapByAdGroups(fakeCoreAdGroups, shard, clientCurrency);
    }
}
