package com.hdkj.lt.base.constraints;

import com.google.common.collect.Lists;
import com.hdkj.lt.base.annotations.EnumValid;
import com.hdkj.lt.base.enums.BaseValidEnum;
import org.apache.commons.lang3.StringUtils;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * @Description: 枚举校验器
 * @Author: wenhao
 * @Create: 2022/08/15 11:16
 * @Version: 1.0
 */
public class EnumValidator implements ConstraintValidator<EnumValid, Object> {

    private Class<?> enumClass;

    @Override
    public void initialize(EnumValid enumValid) {
        this.enumClass = enumValid.enumClass();
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        Class<?>[] interfaces = enumClass.getInterfaces();
        if (!needValidate(interfaces)) {
            return true;
        }
        try {
            return validate(value);
        } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 是否需要校验，只有实现了BaseValidEnum接口，才需要校验
     *
     * @param interfaces
     * @return
     */
    private boolean needValidate(Class<?>[] interfaces) {
        for (Class<?> inter : interfaces) {
            if (inter.getName().equals(BaseValidEnum.class.getName())) {
                return true;
            }
        }
        return false;
    }

    private boolean validate(Object value) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Method valuesMethod = enumClass.getMethod(BaseValidEnum.VALUES_METHOD);
        if (Objects.isNull(valuesMethod)) {
            return true;
        }
        // 如果是空时 交给NotEmpty等注解判断
        if (Objects.isNull(value) || Objects.equals(StringUtils.EMPTY, value)) {
            return true;
        }
        BaseValidEnum<?>[] validEnums = (BaseValidEnum<?>[]) valuesMethod.invoke(null);
        List<Object> validValues = Lists.newArrayList(Optional.of(value).map(e -> e.toString().split(",")).orElse(null));
        for (Object validValue : validValues) {
            boolean validRes = false; //枚举值比对，默认比对值错误
            for (BaseValidEnum<?> validEnum : validEnums) {
                if (Objects.equals(validEnum.getCode(), validValue)) {
                    validRes = true; //相同比对成功
                    break;
                }
            }
            if (!validRes) { //只要是有一次比对错误就给 校验结果赋值，多次赋值也没关系
                return false;
            }
        }
        return true;
    }

}
