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

import java.util.List;

import javax.annotation.ParametersAreNonnullByDefault;

import com.yandex.direct.api.v5.keywords.UpdateRequest;
import org.springframework.stereotype.Component;

import ru.yandex.direct.api.v5.entity.keywords.container.UpdateInputItem;
import ru.yandex.direct.api.v5.validation.DefectType;
import ru.yandex.direct.api.v5.validation.DefectTypes;
import ru.yandex.direct.core.entity.relevancematch.model.RelevanceMatch;
import ru.yandex.direct.validation.builder.Constraint;
import ru.yandex.direct.validation.builder.ItemValidationBuilder;
import ru.yandex.direct.validation.builder.ListValidationBuilder;
import ru.yandex.direct.validation.result.ValidationResult;

import static ru.yandex.direct.api.v5.entity.keywords.KeywordsDefectTypes.maxElementsPerKeywordsUpdate;
import static ru.yandex.direct.api.v5.validation.constraints.Constraints.eachNotNull;
import static ru.yandex.direct.api.v5.validation.constraints.Constraints.maxListSize;
import static ru.yandex.direct.utils.CollectionUtils.isEmpty;

@Component
@ParametersAreNonnullByDefault
public class KeywordsUpdateRequestValidator {
    static final int MAX_ELEMENTS = 1_000;

    public ValidationResult<UpdateRequest, DefectType> validate(UpdateRequest externalRequest) {
        ItemValidationBuilder<UpdateRequest, DefectType> vb = ItemValidationBuilder.of(externalRequest);
        vb.item(externalRequest.getKeywords(), UpdateRequest.PropInfo.KEYWORDS.schemaName.getLocalPart())
                .check(eachNotNull())
                .check(maxListSize(MAX_ELEMENTS), maxElementsPerKeywordsUpdate(MAX_ELEMENTS));
        return vb.getResult();
    }

    public ValidationResult<List<UpdateInputItem>, DefectType> validateInternalRequest(
            List<UpdateInputItem> internalRequest) {
        return ListValidationBuilder.<UpdateInputItem, DefectType>of(internalRequest)
                .checkEach(notEmptyRelevanceMatchCategories())
                .getResult();
    }

    private static Constraint<UpdateInputItem, DefectType> notEmptyRelevanceMatchCategories() {
        return Constraint.fromPredicate(item -> !item.hasRelevanceMatchChanges()
                        || item.getRelevanceMatchChanges().getPropIfChanged(RelevanceMatch.RELEVANCE_MATCH_CATEGORIES) == null
                        || !isEmpty(item.getRelevanceMatchChanges().getPropIfChanged(RelevanceMatch.RELEVANCE_MATCH_CATEGORIES)),
                DefectTypes.disableAllAutotargetingCategoriesIsForbidden());
    }
}
