package ru.yandex.direct.api.v5.entity.campaignsext.converter;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.ParametersAreNonnullByDefault;

import com.yandex.direct.api.v5.campaignsext.CampaignAddItem;
import com.yandex.direct.api.v5.campaignsext.ContentPromotionCampaignAddItem;
import com.yandex.direct.api.v5.campaignsext.ContentPromotionCampaignSetting;
import com.yandex.direct.api.v5.campaignsext.ContentPromotionCampaignSettingsEnum;
import com.yandex.direct.api.v5.general.YesNoEnum;
import one.util.streamex.StreamEx;

import ru.yandex.direct.api.v5.entity.campaigns.validation.CampaignsApiValidationSignals;
import ru.yandex.direct.core.entity.campaign.model.CampaignSource;
import ru.yandex.direct.core.entity.campaign.model.CampaignType;
import ru.yandex.direct.core.entity.campaign.model.ContentPromotionCampaign;
import ru.yandex.direct.core.entity.campaign.model.DbStrategy;
import ru.yandex.direct.core.entity.timetarget.model.GeoTimezone;

import static ru.yandex.direct.api.v5.entity.campaigns.converter.CampaignDataConverterKt.toAttributionModel;
import static ru.yandex.direct.api.v5.entity.campaigns.converter.CampaignDataConverterKt.toDate;
import static ru.yandex.direct.api.v5.entity.campaignsext.converter.CampaignDataConverterKt.extractCheckPositionIntervalEvent;
import static ru.yandex.direct.api.v5.entity.campaignsext.converter.CampaignDataConverterKt.extractDayBudget;
import static ru.yandex.direct.api.v5.entity.campaignsext.converter.CampaignDataConverterKt.extractDayBudgetShowMode;
import static ru.yandex.direct.api.v5.entity.campaignsext.converter.CampaignDataConverterKt.extractDisabledIps;
import static ru.yandex.direct.api.v5.entity.campaignsext.converter.CampaignDataConverterKt.extractEmail;
import static ru.yandex.direct.api.v5.entity.campaignsext.converter.CampaignDataConverterKt.extractEnableCheckPositionEvent;
import static ru.yandex.direct.api.v5.entity.campaignsext.converter.CampaignDataConverterKt.extractMinusKeywords;
import static ru.yandex.direct.api.v5.entity.campaignsext.converter.CampaignDataConverterKt.extractSendAccountNews;
import static ru.yandex.direct.api.v5.entity.campaignsext.converter.CampaignDataConverterKt.extractSmsFlags;
import static ru.yandex.direct.api.v5.entity.campaignsext.converter.CampaignDataConverterKt.extractSmsTimeInterval;
import static ru.yandex.direct.api.v5.entity.campaignsext.converter.CampaignDataConverterKt.extractTimeTarget;
import static ru.yandex.direct.api.v5.entity.campaignsext.converter.CampaignDataConverterKt.extractWarningBalance;
import static ru.yandex.direct.api.v5.entity.campaignsext.converter.ContentPromotionCampaignStrategyConverter.toCampaignStrategy;
import static ru.yandex.direct.core.entity.campaign.service.validation.CampaignConstants.DEFAULT_ADD_TO_FAVORITES;
import static ru.yandex.direct.core.entity.campaign.service.validation.CampaignConstants.DEFAULT_HAS_EXTENDED_GEO_TARGETING;
import static ru.yandex.direct.utils.CommonUtils.nvl;

@ParametersAreNonnullByDefault
public class ContentPromotionCampaignAddItemConverter {

    private static final Map<ContentPromotionCampaignSettingsEnum, Boolean> DEFAULT_SETTINGS = Map.of(
            ContentPromotionCampaignSettingsEnum.ADD_TO_FAVORITES, DEFAULT_ADD_TO_FAVORITES,
            ContentPromotionCampaignSettingsEnum.ENABLE_AREA_OF_INTEREST_TARGETING, DEFAULT_HAS_EXTENDED_GEO_TARGETING
    );

    public static CampaignsApiValidationSignals.CampaignWrapper convertContentPromotionCampaign(
            CampaignAddItem item,
            Long chiefUid,
            String userEmail,
            Map<String, GeoTimezone> timeZones,
            CampaignSource campaignSource,
            Set<String> knownSsps) {
        ContentPromotionCampaignAddItem contentPromotionItem = item.getContentPromotionCampaign();

        Map<ContentPromotionCampaignSettingsEnum, Boolean> settings =
                convertContentPromotionSettings(contentPromotionItem.getSettings());
        Set<Long> favoriteForUids = settings.get(ContentPromotionCampaignSettingsEnum.ADD_TO_FAVORITES) ?
                Set.of(chiefUid) : null;

        DbStrategy strategy = toCampaignStrategy(contentPromotionItem.getBiddingStrategy());
        var campaign = new ContentPromotionCampaign()
                .withSource(campaignSource)
                .withType(CampaignType.CONTENT_PROMOTION)
                .withName(item.getName())
                .withStrategy(strategy)
                .withHasExtendedGeoTargeting(settings.get(ContentPromotionCampaignSettingsEnum.ENABLE_AREA_OF_INTEREST_TARGETING))
                .withUseCurrentRegion(settings.get(ContentPromotionCampaignSettingsEnum.ENABLE_CURRENT_AREA_TARGETING))
                .withUseRegularRegion(settings.get(ContentPromotionCampaignSettingsEnum.ENABLE_REGULAR_AREA_TARGETING))
                .withFavoriteForUids(favoriteForUids)
                .withStartDate(toDate(item.getStartDate()))
                .withEndDate(toDate(item.getEndDate()))
                .withSmsTime(extractSmsTimeInterval(item))
                .withSmsFlags(extractSmsFlags(item))
                .withDayBudget(extractDayBudget(item))
                .withDayBudgetShowMode(extractDayBudgetShowMode(item))
                .withTimeZoneId(item.getTimeZone() == null ? 0 : timeZones.get(item.getTimeZone()).getTimezoneId())
                .withTimeTarget(extractTimeTarget(item))
                .withMetrikaCounters(CampaignsExtAddRequestConverter.toMetrikaCounters(contentPromotionItem.getCounterIds()))
                .withFio(item.getClientInfo())
                .withMinusKeywords(extractMinusKeywords(item))
                .withEmail(nvl(extractEmail(item.getNotification()), userEmail))
                .withWarningBalance(extractWarningBalance(item.getNotification()))
                .withCheckPositionIntervalEvent(extractCheckPositionIntervalEvent(item.getNotification()))
                .withEnableSendAccountNews(extractSendAccountNews(item))
                .withEnableCheckPositionEvent(extractEnableCheckPositionEvent(item.getNotification()))
                .withDisabledIps(extractDisabledIps(item))
                // disabledSsp для ContentPromotion - всегда пустой список
                // см. https://a.yandex-team.ru/arc_vcs/direct/api5/src/main/java/ru/yandex/direct/api/v5/entity/campaignsext/validation/CampaignsExtAddRequestValidator.kt?rev=r8888810#L250
                .withDisabledSsp(Collections.emptyList())
                .withAttributionModel(toAttributionModel(contentPromotionItem.getAttributionModel()));

        return new CampaignsApiValidationSignals.CampaignWrapper()
                .withRealCampaign(campaign)
                .withRequireServicing(settings.get(ContentPromotionCampaignSettingsEnum.REQUIRE_SERVICING));
    }

    private static Map<ContentPromotionCampaignSettingsEnum, Boolean> convertContentPromotionSettings(
            List<ContentPromotionCampaignSetting> settings) {
        Map<ContentPromotionCampaignSettingsEnum, Boolean> valueByOption = new HashMap<>();
        for (ContentPromotionCampaignSetting s : settings) {
            valueByOption.put(s.getOption(), s.getValue() == YesNoEnum.YES);
        }
        return StreamEx.of(ContentPromotionCampaignSettingsEnum.values())
                .mapToEntry(option -> valueByOption.getOrDefault(option, DEFAULT_SETTINGS.get(option)))
                .nonNullValues()
                .toMap();
    }

}
