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

import java.util.List;
import java.util.Set;

import javax.annotation.ParametersAreNonnullByDefault;

import com.yandex.direct.api.v5.ads.ResumeRequest;
import com.yandex.direct.api.v5.ads.SuspendRequest;
import com.yandex.direct.api.v5.general.IdsCriteria;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import ru.yandex.direct.api.v5.validation.DefectType;
import ru.yandex.direct.core.entity.adgroup.model.AdGroupType;
import ru.yandex.direct.core.entity.banner.model.BannerWithSystemFields;
import ru.yandex.direct.dbutil.model.ClientId;
import ru.yandex.direct.model.ModelChanges;
import ru.yandex.direct.validation.builder.ItemValidationBuilder;
import ru.yandex.direct.validation.builder.When;
import ru.yandex.direct.validation.result.ValidationResult;

import static ru.yandex.direct.api.v5.entity.ads.AdsDefectTypes.maxBannersPerResumeRequest;
import static ru.yandex.direct.api.v5.entity.ads.AdsDefectTypes.maxBannersPerSuspendRequest;
import static ru.yandex.direct.api.v5.entity.ads.Constants.MAX_SUSPEND_RESUME_IDS_COUNT;
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.api.v5.validation.constraints.Constraints.notEmptyCollection;
import static ru.yandex.direct.api.v5.validation.constraints.Constraints.notNull;

@Component
@ParametersAreNonnullByDefault
public class AdsSuspendResumeRequestValidator {

    private final AdsAdGroupTypeValidator adsAdGroupTypeValidator;

    @Autowired
    public AdsSuspendResumeRequestValidator(AdsAdGroupTypeValidator adsAdGroupTypeValidator) {
        this.adsAdGroupTypeValidator = adsAdGroupTypeValidator;
    }

    public ValidationResult<ResumeRequest, DefectType> validate(ResumeRequest externalRequest) {
        ItemValidationBuilder<ResumeRequest, DefectType> vb = ItemValidationBuilder.of(externalRequest);
        vb.item(externalRequest.getSelectionCriteria(),
                ResumeRequest.PropInfo.SELECTION_CRITERIA.schemaName.getLocalPart())
                .check(notNull())
                .checkBy(idsCriteria -> validateIdsCriteria(idsCriteria, true), When.isValid());
        return vb.getResult();
    }

    public ValidationResult<SuspendRequest, DefectType> validate(SuspendRequest externalRequest) {
        ItemValidationBuilder<SuspendRequest, DefectType> vb = ItemValidationBuilder.of(externalRequest);
        vb.item(externalRequest.getSelectionCriteria(),
                SuspendRequest.PropInfo.SELECTION_CRITERIA.schemaName.getLocalPart())
                .check(notNull())
                .checkBy(idsCriteria -> validateIdsCriteria(idsCriteria, false), When.isValid());
        return vb.getResult();
    }

    private ValidationResult<IdsCriteria, DefectType> validateIdsCriteria(IdsCriteria idsCriteria, boolean resume) {
        ItemValidationBuilder<IdsCriteria, DefectType> vb = ItemValidationBuilder.of(idsCriteria);
        vb.item(idsCriteria.getIds(), "Ids")
                .check(notNull(), When.isValid())
                .check(notEmptyCollection(), When.isValid())
                .check(eachNotNull(), When.isValid())
                .check(maxListSize(MAX_SUSPEND_RESUME_IDS_COUNT),
                        resume
                                ? maxBannersPerResumeRequest(MAX_SUSPEND_RESUME_IDS_COUNT)
                                : maxBannersPerSuspendRequest(MAX_SUSPEND_RESUME_IDS_COUNT),
                        When.isValid());

        return vb.getResult();
    }

    public ValidationResult<List<ModelChanges<BannerWithSystemFields>>, DefectType> validateInternalRequest(
            ClientId clientId, List<ModelChanges<BannerWithSystemFields>> internalRequest,
            Set<AdGroupType> allowedAdGroupTypes) {
        return adsAdGroupTypeValidator.validateInternalRequest(clientId, internalRequest, allowedAdGroupTypes);
    }
}
