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

import com.yandex.direct.api.v5.changes.CheckRequest;
import org.apache.commons.collections4.CollectionUtils;

import ru.yandex.direct.api.v5.validation.DefectType;
import ru.yandex.direct.api.v5.validation.wrapper.DirectApiValidator;
import ru.yandex.direct.validation.builder.ItemValidationBuilder;
import ru.yandex.direct.validation.result.ValidationResult;

import static ru.yandex.direct.api.v5.validation.DefectTypes.maxElementsPerRequest;
import static ru.yandex.direct.api.v5.validation.DefectTypes.mutuallyExclusiveParameters;
import static ru.yandex.direct.api.v5.validation.DefectTypes.noOneOfRequiredParameters;
import static ru.yandex.direct.api.v5.validation.constraints.Constraints.maxListSize;

public class CheckValidator implements DirectApiValidator<CheckRequest> {
    private static final String CHECK_PARAMS = String.join(", ",
            CheckRequest.PropInfo.CAMPAIGN_IDS.schemaName.getLocalPart(),
            CheckRequest.PropInfo.AD_GROUP_IDS.schemaName.getLocalPart(),
            CheckRequest.PropInfo.AD_IDS.schemaName.getLocalPart());

    private static final String TIMESTAMP_FIELD_NAME =
            CheckRequest.PropInfo.TIMESTAMP.schemaName.getLocalPart();

    private static final int CAMPAIGN_ID_LIMIT = 3_000;
    private static final int ADGROUP_ID_LIMIT = 10_000;
    private static final int AD_ID_LIMIT = 50_000;

    @Override
    public ValidationResult<CheckRequest, DefectType> apply(CheckRequest checkRequest) {
        ItemValidationBuilder<CheckRequest, DefectType> vb = ItemValidationBuilder.of(checkRequest);
        vb.item(checkRequest.getTimestamp(), TIMESTAMP_FIELD_NAME)
                .checkBy(new ChangesTimestampValidator(TIMESTAMP_FIELD_NAME, false));
        vb.check(r -> {
            int fieldsCount = 0;
            if (CollectionUtils.isNotEmpty(r.getCampaignIds()))
                fieldsCount++;
            if (CollectionUtils.isNotEmpty(r.getAdGroupIds()))
                fieldsCount++;
            if (CollectionUtils.isNotEmpty(r.getAdIds()))
                fieldsCount++;
            if (fieldsCount == 0) {
                return noOneOfRequiredParameters(CHECK_PARAMS);
            }
            if (fieldsCount > 1) {
                return mutuallyExclusiveParameters(CHECK_PARAMS);
            }
            return null;
        });
        vb.item(checkRequest.getCampaignIds(), "CampaignIds")
                .check(
                        maxListSize(CAMPAIGN_ID_LIMIT),
                        maxElementsPerRequest(CAMPAIGN_ID_LIMIT)
                );
        vb.item(checkRequest.getAdGroupIds(), "AdGroupIds")
                .check(
                        maxListSize(ADGROUP_ID_LIMIT),
                        maxElementsPerRequest(ADGROUP_ID_LIMIT)
                );
        vb.item(checkRequest.getAdIds(), "AdIds")
                .check(
                        maxListSize(AD_ID_LIMIT),
                        maxElementsPerRequest(AD_ID_LIMIT)
                );
        return vb.getResult();
    }
}
