package com.tuoheng.common.core.utils;


import com.tuoheng.common.core.exception.ServiceException;
import org.hibernate.validator.HibernateValidator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.util.CollectionUtils;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * @author chenyukun
 */
public class ValidatorUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(ValidatorUtils.class);

    private static Validator validatorFast = Validation.byProvider(HibernateValidator.class)
            .configure()
            .failFast(true)
            .buildValidatorFactory()
            .getValidator();

    private static Validator validatorAll = Validation.byProvider(HibernateValidator.class)
            .configure()
            .failFast(false)
            .buildValidatorFactory()
            .getValidator();

    /**
     * 校验遇到第一个不合法的字段直接返回不合法字段，后续字段不再校验
     * @param t t
     */
    public static <T> void validateFast(T t) {
        Set<ConstraintViolation<T>> validateResult = validatorFast.validate(t);
        buildResult(validateResult);
    }

    /**
     * 校验所有字段并返回不合法字段
     * @param t t
     */
    public static <T> void validateAll(T t) {
        Set<ConstraintViolation<T>> validateResult = validatorAll.validate(t);
        buildResult(validateResult);
    }

    /**
     * 封装验证结果
     * @param validateResult 验证结果
     * @param <T>
     */
    private static <T> void buildResult(Set<ConstraintViolation<T>> validateResult){
        Map<String, String> result = new HashMap<>(validateResult.size());
        if(!CollectionUtils.isEmpty(validateResult)) {
            Iterator<ConstraintViolation<T>> it = validateResult.iterator();
            while(it.hasNext()) {
                ConstraintViolation<T> cv = it.next();
                result.put(cv.getPropertyPath().toString(), cv.getMessage());
            }
            LOGGER.error("参数验证未通过，校验结果：{}", JacksonUtil.obj2json(result));
            throw new ServiceException(HttpStatus.BAD_REQUEST.value(), JacksonUtil.obj2json(result));
        }
        LOGGER.info("参数验证通过，校验异常数量：{}", validateResult.size());
    }
}
