package ru.yandex.direct.api.v5.entity.keywords;

import ru.yandex.direct.api.v5.validation.DefectType;
import ru.yandex.direct.api.v5.validation.DefectTypes;
import ru.yandex.direct.core.entity.keyword.service.validation.KeywordDefectTranslations;
import ru.yandex.direct.core.entity.relevancematch.valdiation.RelevanceMatchDefectTranslations;
import ru.yandex.direct.core.validation.CommonDefectTranslations;
import ru.yandex.direct.i18n.types.Identity;

import static ru.yandex.direct.api.v5.entity.bids.validation.BidsDefectTypes.bidWontBeAccepted;
import static ru.yandex.direct.api.v5.validation.DefectTypes.invalidCollectionSize;
import static ru.yandex.direct.api.v5.validation.DefectTypes.maxElementsExceeded;
import static ru.yandex.direct.api.v5.validation.DefectTypes.minusWords;
import static ru.yandex.direct.api.v5.validation.DefectTypes.mustContainLettersOrDigitsOrPunctuations;
import static ru.yandex.direct.api.v5.validation.DefectTypes.notFound;
import static ru.yandex.direct.api.v5.validation.DefectTypes.warningDuplicated;

public class KeywordsDefectTypes {
    private KeywordsDefectTypes() {
    }

    private static CommonDefectTranslations commonTranslations() {
        return CommonDefectTranslations.INSTANCE;
    }

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

    private static KeywordDefectTranslations keywordDefectTranslations() {
        return KeywordDefectTranslations.INSTANCE;
    }

    private static RelevanceMatchDefectTranslations relevanceMatchDefectTranslations() {
        return RelevanceMatchDefectTranslations.INSTANCE;
    }

    public static DefectType keywordNotFound() {
        return notFound().withDetailedMessage(translations().keywordNotFoundDetailed());
    }

    public static DefectType adGroupNotFound() {
        return notFound().withDetailedMessage(translations().adGroupNotFoundDetailed());
    }

    public static DefectType maxElementsPerKeywordsAdd(int maxElements) {
        return DefectTypes.maxElementsPerRequest(maxElements)
                .withDetailedMessage(translations().maxElementsPerKeywordsAddDetailed(new Identity(maxElements)));
    }

    public static DefectType maxElementsPerKeywordsUpdate(int maxElements) {
        return DefectTypes.maxElementsPerRequest(maxElements)
                .withDetailedMessage(translations().maxElementsPerKeywordsUpdateDetailed(new Identity(maxElements)));
    }

    public static DefectType maxElementsPerKeywordsDelete(int maxElements) {
        return DefectTypes.maxIdsInSelection()
                .withDetailedMessage(translations().maxElementsPerKeywordsDeleteDetailed(new Identity(maxElements)));
    }

    public static DefectType keywordIsDuplicated() {
        return DefectTypes.duplicatedObject()
                .withDetailedMessage((path, value) -> translations().keywordIsDuplicatedDetailed());
    }

    public static DefectType maxKeywordsInAdGroup(Integer maxKeywordsInAdGroup) {
        return maxElementsExceeded(maxKeywordsInAdGroup)
                .withDetailedMessage(translations().maxKeywordsInAdGroupDetailed(new Identity(maxKeywordsInAdGroup)));
    }

    public static DefectType maxAutotargetingsInAdGroup() {
        return invalidCollectionSize()
                .withDetailedMessage(translations().maxAutotargetingsInAdGroupDetailed());
    }

    public static DefectType maxOfferRetargetingsInAdGroup() {
        return invalidCollectionSize()
                .withDetailedMessage(translations().maxOfferRetargetingsInAdGroupDetailed());
    }

    public static DefectType keywordAsMinusWord(String minusWord) {
        return minusWords()
                .withDetailedMessage(
                        (path, value) -> translations()
                                .keywordCouldNotBeUsedAsMinusWordQuot(minusWord, value.toString()));
    }

    public static DefectType minusWordsNoMinusPhrases() {
        return minusWords().withDetailedMessage(
                (path, value) -> translations().minusWordsNoMinusPhrasesDetailed(value.toString()));
    }

    public static DefectType keywordWithInvalidSymbols() {
        return mustContainLettersOrDigitsOrPunctuations()
                .withDetailedMessage((path, value) -> translations().keywordMustContainValidSymbols(value.toString()));
    }

    public static DefectType keywordContainsOnlyMinusWords() {
        return minusWords()
                .withDetailedMessage(
                        (path, value) -> translations().keywordCouldNotBeContainedMinusWord(value.toString()));
    }

    public static DefectType plusMarkInBrackets() {
        return DefectTypes.invalidChars().withDetailedMessage(
                (path, value) -> translations().keywordContainsInvalidModifiersInsideSquareBrackets(value.toString()));
    }

    public static DefectType invalidBracketsInKeyword() {
        return DefectTypes.invalidChars().withDetailedMessage(
                (path, value) -> translations().incorrectCombinationOfSquareBrackets(value.toString()));
    }

    public static DefectType keywordMaxLength(int maxLength, String invalidKeywords) {
        return DefectTypes.keywordMaxLength(maxLength).withDetailedMessage(
                (path, value) -> translations().keywordMaxLengthDetailedWords(maxLength, invalidKeywords));
    }

    public static DefectType minusWordMaxLength(int maxLength, String invalidMinus) {
        return DefectTypes.minusWordMaxLength(maxLength).withDetailedMessage(
                (path, value) -> translations().minusWordMaxLengthOnlyDetailed(maxLength, invalidMinus));
    }

    public static DefectType keywordMaxWords(int maxWords) {
        return DefectTypes.maxWords(maxWords).withDetailedMessage(
                (path, value) -> translations().maxWordsDetailed(maxWords, value.toString()));
    }

    public static DefectType keywordsTooLong(Integer maxLength) {
        return DefectTypes.maxStringSize(maxLength).withDetailedMessage(
                (path, value) -> translations().keywordsTooLongDetailed(
                        maxLength.toString(), value.toString().substring(0, 197) + "..."));
    }

    public static DefectType invalidQuotes() {
        return DefectTypes.invalidChars().withDetailedMessage(
                (path, value) -> translations().invalidQuotes(value.toString()));
    }

    public static DefectType containsOnlyStopWords() {
        return DefectTypes.containsOnlyStopWords().withDetailedMessage(
                (path, value) -> translations().onlyStopWords(value.toString().replace("+", "")));
    }

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

    public static DefectType warningDuplicatedId() {
        return warningDuplicated().withDetailedMessage(translations().keywordIdIsDuplicatedDetailed());
    }

    public static DefectType keywordForbiddenInThisAdGroup() {
        return DefectTypes.notEligibleObject().withDetailedMessage(
                keywordDefectTranslations().keywordForbiddenInThisAdGroup());
    }

    public static DefectType autotargetingPrefixIsNotAllowed() {
        return minusWords()
                .withDetailedMessage(translations().keywordCouldNotBeContainedMinusWord("---autotargeting"));
    }

    public static DefectType warningKeywordAlreadySuspended() {
        return new DefectType(10240,
                keywordDefectTranslations().keywordAlreadySuspendedShort());
    }

    public static DefectType warningKeywordNotSuspended() {
        return new DefectType(10241,
                keywordDefectTranslations().keywordNotSuspendedShort());
    }

    public static DefectType warningAutotargetingAlreadySuspended() {
        return new DefectType(10244,
                relevanceMatchDefectTranslations().autotargetingAlreadySuspendedShort());
    }

    public static DefectType warningAutotargetingNotSuspended() {
        return new DefectType(10245,
                relevanceMatchDefectTranslations().autotargetingNotSuspendedShort());
    }

    public static DefectType autotargetingCategoriesForbiddenInThisAdGroup() {
        return DefectTypes.notEligibleObject().withDetailedMessage(
                translations().autotargetingCategoriesForbiddenInThisAdGroup());
    }
}
