package ru.yandex.direct.web.entity.adgroup.converter;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import one.util.streamex.StreamEx;

import ru.yandex.direct.core.entity.adgroup.container.ComplexContentPromotionAdGroup;
import ru.yandex.direct.core.entity.adgroup.model.AdGroup;
import ru.yandex.direct.core.entity.adgroup.model.AdGroupType;
import ru.yandex.direct.core.entity.adgroup.model.ContentPromotionAdGroup;
import ru.yandex.direct.web.entity.adgroup.model.WebContentPromotionAdGroup;
import ru.yandex.direct.web.entity.adgroup.model.WebContentPromotionAdGroupType;

import static ru.yandex.direct.utils.CommonUtils.nvl;
import static ru.yandex.direct.utils.FunctionalUtils.mapList;
import static ru.yandex.direct.web.entity.adgroup.converter.AdGroupBidModifiersConverter.webAdGroupBidModifiersToCore;
import static ru.yandex.direct.web.entity.adgroup.converter.AdGroupConverterUtils.convertGeo;
import static ru.yandex.direct.web.entity.adgroup.converter.AdGroupConverterUtils.convertTags;
import static ru.yandex.direct.web.entity.adgroup.converter.RelevanceMatchConverter.webRelevanceMatchesToCore;
import static ru.yandex.direct.web.entity.adgroup.model.WebContentPromotionAdGroupType.VIDEO;
import static ru.yandex.direct.web.entity.banner.converter.ContentPromotionBannerConverter
        .webBannersToCoreContentPromotionBanners;
import static ru.yandex.direct.web.entity.keyword.converter.KeywordConverter.webKeywordsToCoreKeywords;

/**
 * Конвертер для групп объявлений продвижения контента.
 */
public class ContentPromotionAdGroupConverter {

    private ContentPromotionAdGroupConverter() {
    }

    public static List<ComplexContentPromotionAdGroup> webAdGroupsToCoreComplexContentPromotionAdGroups(
            @Nullable List<WebContentPromotionAdGroup> webContentPromotionAdGroups,
            long overridingCampaignId) {
        List<ComplexContentPromotionAdGroup> complexAdGroups = mapList(webContentPromotionAdGroups,
                adGroup -> webAdGroupToCoreComplexContentPromotionAdGroup(adGroup));

        if (complexAdGroups != null) {
            StreamEx.of(complexAdGroups)
                    .nonNull()
                    .map(ComplexContentPromotionAdGroup::getAdGroup)
                    .nonNull()
                    .forEach(adGroup -> adGroup.withCampaignId(overridingCampaignId));
        }

        return complexAdGroups;
    }

    public static ComplexContentPromotionAdGroup webAdGroupToCoreComplexContentPromotionAdGroup(
            @Nullable WebContentPromotionAdGroup webContentPromotionAdGroup) {
        WebContentPromotionAdGroupType adGroupContentType =
                nvl(webContentPromotionAdGroup.getAdGroupContentType(), VIDEO);
        return webContentPromotionAdGroup == null ? null : new ComplexContentPromotionAdGroup()
                .withAdGroup(webAdGroupToCoreAdGroup(webContentPromotionAdGroup, adGroupContentType))
                .withKeywords(webKeywordsToCoreKeywords(webContentPromotionAdGroup.getKeywords()))
                .withRelevanceMatches(webRelevanceMatchesToCore(webContentPromotionAdGroup.getRelevanceMatches()))
                .withComplexBidModifier(webAdGroupBidModifiersToCore(webContentPromotionAdGroup.getBidModifiers()))
                .withBanners(webBannersToCoreContentPromotionBanners(webContentPromotionAdGroup.getBanners()));
    }

    private static AdGroup webAdGroupToCoreAdGroup(
            @Nullable WebContentPromotionAdGroup webContentPromotionAdGroup,
            @Nonnull WebContentPromotionAdGroupType adGroupContentType) {
        if (webContentPromotionAdGroup == null) {
            return null;
        }
        List<String> minusKeywords = webContentPromotionAdGroup.getMinusKeywords() != null ?
                webContentPromotionAdGroup.getMinusKeywords() : new ArrayList<>();
        return buildCoreContentPromotionAdGroup(webContentPromotionAdGroup, adGroupContentType, minusKeywords);
    }

    private static AdGroup buildCoreContentPromotionAdGroup(
            @Nonnull WebContentPromotionAdGroup webContentPromotionAdGroup,
            @Nonnull WebContentPromotionAdGroupType adGroupContentType,
            List<String> minusKeywords) {
        return new ContentPromotionAdGroup()
                .withId(webContentPromotionAdGroup.getId())
                .withContentPromotionType(WebContentPromotionAdGroupType.toCoreValue(adGroupContentType))
                .withCampaignId(webContentPromotionAdGroup.getCampaignId())
                .withType(AdGroupType.CONTENT_PROMOTION)
                .withName(webContentPromotionAdGroup.getName())
                .withMinusKeywords(minusKeywords)
                .withGeo(convertGeo(webContentPromotionAdGroup.getGeo()))
                .withTags(convertTags(webContentPromotionAdGroup.getTags()))
                .withPageGroupTags(webContentPromotionAdGroup.getPageGroupTags())
                .withTargetTags(webContentPromotionAdGroup.getTargetTags());
    }
}
