package com.ruoyi.info.collection.validation;

import com.ruoyi.info.collection.annotation.EnumValid;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;

import java.lang.reflect.Method;

/**
 * 枚举值校验器
 * 验证字段值是否在指定枚举类的定义范围内
 *
 * @author ruoyi
 */
public class EnumValidator implements ConstraintValidator<EnumValid, String> {

    private EnumValid annotation;

    @Override
    public void initialize(EnumValid constraintAnnotation) {
        this.annotation = constraintAnnotation;
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
        // 如果允许忽略空值且值为空，则校验通过
        if (annotation.ignoreEmpty() && (value == null || value.trim().isEmpty())) {
            return true;
        }

        // 如果值为空且不允许忽略，则校验失败
        if (value == null || value.trim().isEmpty()) {
            return false;
        }

        Class<?> enumClass = annotation.enumClass();

        // 检查是否是枚举类
        if (!enumClass.isEnum()) {
            throw new IllegalArgumentException(enumClass.getName() + " 不是枚举类型");
        }

        // 获取枚举的所有实例
        Object[] enumConstants = enumClass.getEnumConstants();

        try {
            // 尝试调用枚举的getCode方法（如果存在）
            // 假设枚举类有getCode()方法返回枚举的code值
            for (Object enumConstant : enumConstants) {
                try {
                    Method getCodeMethod = enumClass.getMethod("getCode");
                    String code = (String) getCodeMethod.invoke(enumConstant);
                    if (value.equals(code)) {
                        return true;
                    }
                } catch (NoSuchMethodException e) {
                    // 如果没有getCode方法，使用name()方法
                    Enum<?> enumValue = (Enum<?>) enumConstant;
                    if (value.equals(enumValue.name())) {
                        return true;
                    }
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("枚举校验失败", e);
        }

        return false;
    }
}
