package ru.yandex.direct.api.v5.entity.audiencetargets.validation;

import ru.yandex.direct.api.v5.common.validation.DefaultApiPresentations;
import ru.yandex.direct.api.v5.common.validation.DefectPresentationsHolder;
import ru.yandex.direct.api.v5.entity.bids.validation.BidsDefectTypes;
import ru.yandex.direct.api.v5.validation.ApiDefectIds;
import ru.yandex.direct.core.entity.bids.container.ExternalFieldsBidsMapping;
import ru.yandex.direct.core.entity.bids.container.SetBidItem;
import ru.yandex.direct.core.entity.bids.validation.BidsDefects;
import ru.yandex.direct.i18n.types.Identity;

import static ru.yandex.direct.api.v5.entity.bids.validation.BidsDefectTypes.bidWontBeAcceptedInCaseOfAutoBudgetStrategy;
import static ru.yandex.direct.api.v5.entity.bids.validation.BidsDefectTypes.bidWontBeAcceptedSearchIsSwitchedOff;
import static ru.yandex.direct.api.v5.entity.bids.validation.BidsDefectTypes.fieldDoesNotMatchStrategy;
import static ru.yandex.direct.api.v5.entity.bids.validation.BidsDefectTypes.oneOfFieldsRequiredDetailed;
import static ru.yandex.direct.api.v5.entity.bids.validation.BidsDefectTypes.priorityWontBeAcceptedNotAutoBudgetStrategy;
import static ru.yandex.direct.api.v5.entity.bids.validation.BidsDefectTypes.requiredAtLeastOneOfFieldsForManualStrategy;
import static ru.yandex.direct.api.v5.validation.DefectTypes.badStatusCampaignArchivedOnUpdateBids;
import static ru.yandex.direct.api.v5.validation.DefectTypes.invalidValueNotGreaterThan;
import static ru.yandex.direct.api.v5.validation.DefectTypes.invalidValueNotLessThan;
import static ru.yandex.direct.api.v5.validation.DefectTypes.maxElementsPerRequest;
import static ru.yandex.direct.api.v5.validation.DefectTypes.mixedTypes;
import static ru.yandex.direct.api.v5.validation.DefectTypes.notFoundAudienceTargetByParameters;
import static ru.yandex.direct.api.v5.validation.DefectTypes.possibleOnlyOneField;
import static ru.yandex.direct.api.v5.validation.DefectTypes.requiredButEmpty;
import static ru.yandex.direct.api.v5.validation.DefectTypes.translations;

/**
 * DefectPresentations переопределённые для сервиса AudienceTargets.
 * Fallback на {@link DefaultApiPresentations#HOLDER}
 */
public class AudienceTargetsDefectPresentations {

    private static final ExternalFieldsBidsMapping BIDS_IDS_MAPPING =
            ExternalFieldsBidsMapping.builder()
                    .map(SetBidItem.ID, "Id")
                    .map(SetBidItem.AD_GROUP_ID, "AdGroupId")
                    .map(SetBidItem.CAMPAIGN_ID, "CampaignId")
                    .map(SetBidItem.PRICE_CONTEXT, "ContextBid")
                    .map(SetBidItem.PRICE_SEARCH, "Bid")
                    .map(SetBidItem.AUTOBUDGET_PRIORITY, "StrategyPriority")
                    .build();

    public static final DefectPresentationsHolder HOLDER = DefectPresentationsHolder
            .builderWithFallback(DefaultApiPresentations.HOLDER)
            // BidsDefects.CollectionIds
            .register(ApiDefectIds.CollectionIds.MAX_SHOW_CONDITIONS_PER_REQUEST,
                    t -> maxElementsPerRequest(t.getMaxSize())
                            .withDetailedMessage(translations().maxElementsPerRequestRetargetingIdsDetailed(
                                    new Identity(t.getMaxSize()))))
            .register(ApiDefectIds.CollectionIds.MAX_AD_GROUP_IDS_PER_REQUEST,
                    t -> maxElementsPerRequest(t.getMaxSize())
                            .withDetailedMessage(translations().maxElementsPerRequestRetargetingAdGroupIdsDetailed(
                                    new Identity(t.getMaxSize()))))
            .register(ApiDefectIds.CollectionIds.MAX_CAMPAIGN_IDS_PER_REQUEST,
                    t -> maxElementsPerRequest(t.getMaxSize())
                            .withDetailedMessage(translations().maxElementsPerRequestRetargetingCampaignIdsDetailed(
                                    new Identity(t.getMaxSize()))))
            // BidsDefects.Bids
            .register(BidsDefects.Bids.BAD_STATUS_CAMPAIGN_ARCHIVED_ON_UPDATE_BIDS,
                    t -> badStatusCampaignArchivedOnUpdateBids(t.getId()))
            .register(BidsDefects.Bids.NOT_FOUND_SHOW_CONDITION_BY_PARAMETERS,
                    t -> notFoundAudienceTargetByParameters())
            .register(BidsDefects.Bids.FIELD_DOES_NOT_MATCH_STRATEGY,
                    t -> fieldDoesNotMatchStrategy(BIDS_IDS_MAPPING.getBidsField(t.getField())))
            // BidsDefects.ModelDefects
            .register(BidsDefects.ModelDefects.REQUIRED_AT_LEAST_ONE_OF_FIELDS,
                    t -> BidsDefectTypes.requiredAtLeastOneOfFields(BIDS_IDS_MAPPING.getBidsFields(t)))
            .register(BidsDefects.ModelDefects.POSSIBLE_ONLY_ONE_FIELD,
                    t -> possibleOnlyOneField(BIDS_IDS_MAPPING.getBidsFields(t)))
            // BidsDefects.Ids
            .register(BidsDefects.Ids.MIXED_TYPES,
                    t -> mixedTypes())
            .register(BidsDefects.Ids.CONTEXT_PRICE_IS_NOT_SET_FOR_MANUAL_STRATEGY,
                    t -> requiredButEmpty())
            .register(BidsDefects.Ids.PRIORITY_IS_NOT_SET_FOR_AUTO_STRATEGY,
                    t -> requiredButEmpty())
            .register(BidsDefects.Ids.BID_FOR_SEARCH_WONT_BE_ACCEPTED_SEARCH_IS_SWITCHED_OFF,
                    t -> bidWontBeAcceptedSearchIsSwitchedOff())
            .register(BidsDefects.Ids.BID_FOR_SEARCH_WONT_BE_ACCEPTED_IN_CASE_OF_AUTOBUDGET_STRATEGY,
                    t -> bidWontBeAcceptedInCaseOfAutoBudgetStrategy())
            .register(BidsDefects.Ids.BID_FOR_CONTEXT_WONT_BE_ACCEPTED_IN_CASE_OF_AUTOBUDGET_STRATEGY,
                    t -> bidWontBeAcceptedInCaseOfAutoBudgetStrategy())
            .register(BidsDefects.Ids.PRIORITY_WONT_BE_ACCEPTED_IN_CASE_OF_NOT_AUTO_BUDGET_STRATEGY,
                    t -> priorityWontBeAcceptedNotAutoBudgetStrategy())
            .register(BidsDefects.ModelDefects.REQUIRED_AT_LEAST_ONE_OF_FIELDS_FOR_MANUAL_STRATEGY,
                    t -> requiredAtLeastOneOfFieldsForManualStrategy(BIDS_IDS_MAPPING.getBidsFields(t)))
            .register(BidsDefects.ModelDefects.REQUIRED_AT_LEAST_ONE_OF_FIELDS_FOR_AUTOBUDGET_STRATEGY,
                    t -> BidsDefectTypes
                            .requiredAtLeastOneOfFieldsForAutobudgetStrategy(BIDS_IDS_MAPPING.getBidsFields(t)))
            .register(BidsDefects.CurrencyAmountDefects.SEARCH_PRICE_IS_NOT_SMALLER_THAN_MAX,
                    t -> invalidValueNotGreaterThan(t.getMoneyValue()))
            .register(BidsDefects.CurrencyAmountDefects.CPM_PRICE_IS_NOT_SMALLER_THAN_MAX,
                    t -> invalidValueNotGreaterThan(t.getMoneyValue()))
            .register(BidsDefects.ModelDefects.ONE_OF_FIELDS_SHOULD_BE_SPECIFIED,
                    t -> oneOfFieldsRequiredDetailed(BIDS_IDS_MAPPING.getBidsFields(t)))
            .register(BidsDefects.CurrencyAmountDefects.SEARCH_PRICE_IS_NOT_GREATER_THAN_MIN,
                    t -> invalidValueNotLessThan(t.getMoneyValue()))
            .register(BidsDefects.CurrencyAmountDefects.CPM_PRICE_IS_NOT_GREATER_THAN_MIN,
                    t -> invalidValueNotLessThan(t.getMoneyValue()))
            .build();
}
