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

import ru.yandex.direct.api.v5.entity.bids.service.validation.BidsDefectTranslations;
import ru.yandex.direct.api.v5.validation.DefectType;
import ru.yandex.direct.api.v5.validation.DefectTypes;
import ru.yandex.direct.i18n.Translatable;
import ru.yandex.direct.i18n.types.Identity;

import static ru.yandex.direct.api.v5.entity.bids.Constants.MAX_BID_ADGROUPIDS_PER_REQUEST;
import static ru.yandex.direct.api.v5.entity.bids.Constants.MAX_BID_CAMPAIGNIDS_PER_REQUEST;
import static ru.yandex.direct.api.v5.entity.bids.Constants.MAX_BID_IDS_PER_REQUEST;
import static ru.yandex.direct.api.v5.validation.DefectTypes.maxElementsPerRequest;
import static ru.yandex.direct.api.v5.validation.DefectTypes.notEligibleObject;
import static ru.yandex.direct.validation.result.PathHelper.field;
import static ru.yandex.direct.validation.result.PathHelper.path;

@SuppressWarnings("WeakerAccess")
public class BidsDefectTypes {
    public static DefectType keywordNotFound(String fieldName, Long id) {
        Identity identity = id == null ? null : new Identity(id);
        return DefectTypes.notFound()
                .withDetailedMessage((path, value) -> translations()
                        .keywordNotFoundFor(fieldName, identity));
    }

    public static DefectType requiredAtLeastOneOfFields(String fieldName) {
        return DefectTypes.requiredAtLeastOneOfFields()
                .withDetailedMessage((path, value) -> translations().requiredAtLeastOneOfFieldsDetailed(fieldName));
    }

    public static DefectType oneOfFieldsRequiredDetailed(String fieldName) {
        return DefectTypes.requiredAtLeastOneOfFields()
                .withDetailedMessage((path, value) -> translations().oneOfFieldsRequiredDetailed(fieldName));
    }

    public static DefectType requiredAnyOfSetBidFields() {
        return DefectTypes.requiredAtLeastOneOfFields()
                .withDetailedMessage((path, value) -> translations().requiredAtLeastOneOfFieldsThreeElements(
                        path(field("KeywordId")),
                        path(field("CampaignId")),
                        path(field("AdGroupId"))));
    }

    public static DefectType bidMustBeNotGreaterThan(Translatable currency, Translatable amountInApi) {
        return DefectTypes.invalidValue()
                .withDetailedMessage(
                        (path, value) -> translations()
                                .bidMustBeNotGreaterThan(path.getFieldName(), currency, amountInApi));
    }

    public static DefectType bidMustBeNotLessThan(Translatable currency, Translatable amountInApi) {
        return DefectTypes.invalidValue()
                .withDetailedMessage(
                        (path, value) -> translations()
                                .bidMustBeNotLessThan(path.getFieldName(), currency, amountInApi));
    }

    public static DefectType notEligibleObjectRelevanceMatchCantBeUsedInPriceConstructor(Long keywordId) {
        return notEligibleObject()
                .withDetailedMessage((path, value) -> translations()
                        .relevanceMatchCantBeUsedInPriceConstructor(new Identity(keywordId)));
    }

    public static DefectType fieldDoesNotMatchStrategy() {
        return new DefectType(9600,
                translations().fieldDoesNotMatchStrategyShort());
    }

    public static DefectType fieldDoesNotMatchStrategy(String fieldName) {
        return fieldDoesNotMatchStrategy().withDetailedMessage(
                (path, value) -> translations().fieldDoesNotMatchStrategy(fieldName));
    }

    public static DefectType fieldRequiredForSearchStrategy(String fieldName) {
        return fieldDoesNotMatchStrategy()
                .withDetailedMessage(translations().fieldRequiredForSearchStrategy(fieldName));
    }

    public static DefectType fieldRequiredForContextStrategy(String fieldName) {
        return fieldDoesNotMatchStrategy()
                .withDetailedMessage(translations().fieldRequiredForContextStrategy(fieldName));
    }

    public static DefectType dependentFieldMissing(String dependentField, String field) {
        return fieldDoesNotMatchStrategy()
                .withDetailedMessage(translations().dependentFieldMissing(dependentField, field));
    }

    public static DefectType strategyIsNotSet() {
        return bidWontBeAccepted().withDetailedMessage(
                (path, value) -> translations().bidWontBeAcceptedStrategyIsNotSet(path));
    }

    public static DefectType searchPriceIsNotSetForManualStrategy() {
        return fieldDoesNotMatchStrategy().withDetailedMessage(
                (path, value) -> translations().searchPriceMustBeSetForManualStrategy(path));
    }

    public static DefectType contextPriceIsNotSetForManualStrategy() {
        return fieldDoesNotMatchStrategy().withDetailedMessage(
                (path, value) -> translations().contextPriceMustBeSetForManualStrategy(path));
    }

    public static DefectType strategyPriorityIsNotSetForAutobudgetStrategy() {
        return fieldDoesNotMatchStrategy().withDetailedMessage(
                (path, value) -> translations().fieldMustBeSetForAutobudgetStrategy(path));
    }

    public static DefectType requiredAtLeastOneOfFieldsForManualStrategy(String fieldName) {
        return fieldDoesNotMatchStrategy().withDetailedMessage(
                (path, value) -> translations().requiredAtLeastOneOfFieldsForManualStrategyDetailed(fieldName));
    }

    public static DefectType requiredAtLeastOneOfFieldsForAutobudgetStrategy(String fieldName) {
        return fieldDoesNotMatchStrategy().withDetailedMessage(
                (path, value) -> translations().requiredAtLeastOneOfFieldsForAutobudgetStrategyDetailed(fieldName));
    }


    public static DefectType bidChangeNotAllowed() {
        return new DefectType(9601,
                translations().bidChangeNotAllowedShort());
    }

    public static DefectType bidChangeNotAllowedForAutobudgetStrategy() {
        return bidChangeNotAllowed()
                .withDetailedMessage(translations().autobudgetStrategyIsSetForCampaign());
    }

    public static DefectType bidChangeNotAllowedSearchIsSwitchedOff() {
        return bidChangeNotAllowed()
                .withDetailedMessage(translations().bidChangeNotAllowedSearchIsSwitchedOff());
    }

    public static DefectType bidChangeNotAllowedContextIsSwitchedOff() {
        return bidChangeNotAllowed()
                .withDetailedMessage(translations().bidChangeNotAllowedContextIsSwitchedOff());
    }

    public static DefectType bidChangeNotAllowedContextDependsOnSearch() {
        return bidChangeNotAllowed()
                .withDetailedMessage(translations().bidChangeNotAllowedContextDependsOnSearch());
    }

    public static DefectType bidWontBeAccepted() {
        return new DefectType(10160,
                translations().bidWontBeAccepted(), translations().bidWontBeAccepted());
    }

    public static DefectType bidWontBeAcceptedInCaseOfAutoBudgetStrategy() {
        return bidWontBeAccepted().withDetailedMessage(
                (path, value) -> translations().bidWontBeAcceptedInCaseOfAutoBudgetStrategy(path));
    }

    public static DefectType bidWontBeAcceptedInCaseOfContextDependsSearch() {
        return bidWontBeAccepted().withDetailedMessage(
                (path, value) -> translations().bidWontBeAcceptedContextDependsSearch(path));
    }

    public static DefectType bidWontBeAcceptedContextDependsOnSearch() {
        return bidWontBeAccepted().withDetailedMessage(translations().bidWontBeAcceptedContextDependsOnSearch());
    }

    public static DefectType bidNetworkWontBeAcceptedContextDependsOnSearch() {
        return bidWontBeAccepted().withDetailedMessage(translations().bidNetworkWontBeAcceptedContextDependsOnSearch());
    }

    public static DefectType bidWontBeAcceptedContextIsSwitchedOff() {
        return bidWontBeAccepted().withDetailedMessage(translations().bidWontBeAcceptedContextIsSwitchedOff());
    }

    public static DefectType bidWontBeAcceptedSearchIsSwitchedOff() {
        return bidWontBeAccepted().withDetailedMessage(translations().bidWontBeAcceptedSearchIsSwitchedOff());
    }

    public static DefectType searchBidWontBeAcceptedSearchIsSwitchedOff() {
        return bidWontBeAccepted().withDetailedMessage(translations().searchBidWontBeAcceptedSearchIsSwitchedOff());
    }

    public static DefectType bidWontBeAcceptedInCaseOfContextIsServingOff() {
        return bidWontBeAccepted().withDetailedMessage(
                (path, value) -> translations().bidWontBeAcceptedContextIsServingOff(path));
    }

    public static DefectType priorityWontBeAccepted() {
        return new DefectType(10161,
                translations().priorityWontBeAccepted(), translations().priorityWontBeAccepted());
    }

    public static DefectType priorityWontBeAcceptedNotAutoBudgetStrategy() {
        return priorityWontBeAccepted()
                .withDetailedMessage((path, value) -> translations().priorityWontBeAcceptedForManualStrategy(path));
    }

    public static DefectType maxKeywordBidsPerRequest() {
        return maxElementsPerRequest(MAX_BID_IDS_PER_REQUEST)
                .withDetailedMessage(translations().maxElementsPerRequestBidsIdsDetailed(
                        new Identity(MAX_BID_IDS_PER_REQUEST)));
    }

    public static DefectType maxAdGroupsBidsPerRequest() {
        return maxElementsPerRequest(MAX_BID_ADGROUPIDS_PER_REQUEST)
                .withDetailedMessage(translations().maxElementsPerRequestBidsAdGroupIdsDetailed(
                        new Identity(MAX_BID_ADGROUPIDS_PER_REQUEST)));
    }

    public static DefectType maxCampBidsPerRequest() {
        return maxElementsPerRequest(MAX_BID_CAMPAIGNIDS_PER_REQUEST)
                .withDetailedMessage(translations().maxElementsPerRequestBidsCampaignIdsDetailed(
                        new Identity(MAX_BID_CAMPAIGNIDS_PER_REQUEST)));
    }

    private static BidsDefectTranslations translations() {
        return BidsDefectTranslations.INSTANCE;
    }
}
