package org.xyzh.common.utils.validation;

import org.xyzh.common.utils.validation.method.ValidateMethod;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * @description 校验工具类
 * @filename ValidationUtils.java
 * @author yslg
 * @copyright xyzh
 * @since 2025-10-16
 */
public class ValidationUtils {

    /**
     * @description 校验对象
     * @param obj 待校验的对象
     * @param validationParams 校验参数列表
     * @return ValidationResult 校验结果
     */
    public static ValidationResult validate(Object obj, List<ValidationParam> validationParams) {
        ValidationResult result = new ValidationResult();
        
        if (obj == null) {
            result.addError("待校验对象不能为null");
            return result;
        }
        
        if (validationParams == null || validationParams.isEmpty()) {
            return result;
        }
        
        for (ValidationParam param : validationParams) {
            try {
                Object fieldValue = getFieldValue(obj, param.getFieldName());
                validateField(param, fieldValue, result);
            } catch (Exception e) {
                result.addError(param.getFieldLabel() + "字段获取失败: " + e.getMessage());
            }
        }
        
        return result;
    }

    /**
     * @description 校验Map对象
     * @param map 待校验的Map
     * @param validationParams 校验参数列表
     * @return ValidationResult 校验结果
     */
    public static ValidationResult validateMap(Map<String, Object> map, List<ValidationParam> validationParams) {
        ValidationResult result = new ValidationResult();
        
        if (map == null) {
            result.addError("待校验Map不能为null");
            return result;
        }
        
        if (validationParams == null || validationParams.isEmpty()) {
            return result;
        }
        
        for (ValidationParam param : validationParams) {
            Object fieldValue = map.get(param.getFieldName());
            validateField(param, fieldValue, result);
        }
        
        return result;
    }

    /**
     * @description 校验单个字段
     * @param param 校验参数
     * @param fieldValue 字段值
     * @param result 校验结果
     */
    private static void validateField(ValidationParam param, Object fieldValue, ValidationResult result) {
        String fieldLabel = param.getFieldLabel();
        
        // 1. 必填校验
        if (param.isRequired()) {
            if (fieldValue == null) {
                result.addError(fieldLabel + "不能为空");
                return;
            }
            if (fieldValue instanceof String) {
                String strValue = (String) fieldValue;
                if (!param.isAllowEmpty() && strValue.trim().isEmpty()) {
                    result.addError(fieldLabel + "不能为空字符串");
                    return;
                }
            }
        }
        
        // 如果值为null且非必填，跳过后续校验
        if (fieldValue == null) {
            return;
        }
        
        // 2. 类型校验
        if (param.getFieldType() != null) {
            if (!param.getFieldType().isAssignableFrom(fieldValue.getClass())) {
                result.addError(fieldLabel + "类型错误，期望类型: " + param.getFieldType().getSimpleName() + 
                        ", 实际类型: " + fieldValue.getClass().getSimpleName());
                return;
            }
        }
        
        // 3. 字符串长度校验
        if (fieldValue instanceof String) {
            String strValue = (String) fieldValue;
            if (param.getMinLength() != null && strValue.length() < param.getMinLength()) {
                result.addError(fieldLabel + "长度不能少于" + param.getMinLength() + "个字符");
            }
            if (param.getMaxLength() != null && strValue.length() > param.getMaxLength()) {
                result.addError(fieldLabel + "长度不能超过" + param.getMaxLength() + "个字符");
            }
        }
        
        // 4. 数字范围校验
        if (fieldValue instanceof Number) {
            double numValue = ((Number) fieldValue).doubleValue();
            if (param.getMinValue() != null && numValue < param.getMinValue().doubleValue()) {
                result.addError(fieldLabel + "不能小于" + param.getMinValue());
            }
            if (param.getMaxValue() != null && numValue > param.getMaxValue().doubleValue()) {
                result.addError(fieldLabel + "不能大于" + param.getMaxValue());
            }
        }
        
        // 5. 正则表达式校验
        if (param.getPattern() != null && fieldValue instanceof String) {
            String strValue = (String) fieldValue;
            if (!Pattern.matches(param.getPattern(), strValue)) {
                String errorMsg = fieldLabel + "格式不正确";
                if (param.getPatternDesc() != null) {
                    errorMsg += "，" + param.getPatternDesc();
                }
                result.addError(errorMsg);
            }
        }
        
        // 6. 自定义校验
        if (param.getCustomValidator() != null) {
            try {
                if (!param.getCustomValidator().test(fieldValue)) {
                    String errorMsg = param.getCustomErrorMessage();
                    if (errorMsg == null || errorMsg.isEmpty()) {
                        errorMsg = fieldLabel + "校验失败";
                    }
                    result.addError(errorMsg);
                }
            } catch (Exception e) {
                result.addError(fieldLabel + "自定义校验异常: " + e.getMessage());
            }
        }
        
        // 7. 使用ValidateMethod校验（枚举类型）
        if (param.getValidateMethodType() != null) {
            try {
                ValidateMethod method = param.getValidateMethodType().createInstance();
                if (!method.validate(fieldValue)) {
                    String errorMsg = method.getErrorMessage();
                    if (errorMsg != null && !errorMsg.isEmpty()) {
                        result.addError(errorMsg);
                    } else {
                        result.addError(fieldLabel + "校验失败");
                    }
                }
            } catch (Exception e) {
                result.addError(fieldLabel + "校验异常: " + e.getMessage());
            }
        }
        
        // 8. 使用ValidateMethod校验（直接传入实例，保留兼容性）
        if (param.getValidateMethod() != null) {
            try {
                if (!param.getValidateMethod().validate(fieldValue)) {
                    String errorMsg = param.getValidateMethod().getErrorMessage();
                    if (errorMsg != null && !errorMsg.isEmpty()) {
                        result.addError(errorMsg);
                    } else {
                        result.addError(fieldLabel + "校验失败");
                    }
                }
            } catch (Exception e) {
                result.addError(fieldLabel + "校验异常: " + e.getMessage());
            }
        }
    }

    /**
     * @description 获取对象字段值（支持getter方法和直接访问）
     * @param obj 对象
     * @param fieldName 字段名
     * @return 字段值
     * @throws Exception 异常
     */
    private static Object getFieldValue(Object obj, String fieldName) throws Exception {
        if (obj instanceof Map) {
            return ((Map<?, ?>) obj).get(fieldName);
        }
        
        Class<?> clazz = obj.getClass();
        
        // 首先尝试getter方法
        try {
            String getterName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
            return clazz.getMethod(getterName).invoke(obj);
        } catch (NoSuchMethodException e) {
            // getter方法不存在，尝试直接访问字段
            try {
                Field field = clazz.getDeclaredField(fieldName);
                field.setAccessible(true);
                return field.get(obj);
            } catch (NoSuchFieldException ex) {
                // 尝试父类
                Class<?> superClass = clazz.getSuperclass();
                if (superClass != null) {
                    Field field = superClass.getDeclaredField(fieldName);
                    field.setAccessible(true);
                    return field.get(obj);
                }
                throw ex;
            }
        }
    }

    /**
     * @description 快速创建必填字符串校验参数
     * @param fieldName 字段名
     * @param fieldLabel 字段标签
     * @return ValidationParam
     */
    public static ValidationParam requiredString(String fieldName, String fieldLabel) {
        return ValidationParam.builder()
                .fieldName(fieldName)
                .fieldLabel(fieldLabel)
                .required()
                .fieldType(String.class)
                .build();
    }

    /**
     * @description 快速创建必填字符串校验参数（带长度限制）
     * @param fieldName 字段名
     * @param fieldLabel 字段标签
     * @param minLength 最小长度
     * @param maxLength 最大长度
     * @return ValidationParam
     */
    public static ValidationParam requiredString(String fieldName, String fieldLabel, int minLength, int maxLength) {
        return ValidationParam.builder()
                .fieldName(fieldName)
                .fieldLabel(fieldLabel)
                .required()
                .fieldType(String.class)
                .minLength(minLength)
                .maxLength(maxLength)
                .build();
    }

    /**
     * @description 快速创建必填数字校验参数
     * @param fieldName 字段名
     * @param fieldLabel 字段标签
     * @param minValue 最小值
     * @param maxValue 最大值
     * @return ValidationParam
     */
    public static ValidationParam requiredNumber(String fieldName, String fieldLabel, Number minValue, Number maxValue) {
        return ValidationParam.builder()
                .fieldName(fieldName)
                .fieldLabel(fieldLabel)
                .required()
                .minValue(minValue)
                .maxValue(maxValue)
                .build();
    }

    /**
     * @description 快速创建邮箱校验参数
     * @param fieldName 字段名
     * @param fieldLabel 字段标签
     * @param required 是否必填
     * @return ValidationParam
     */
    public static ValidationParam email(String fieldName, String fieldLabel, boolean required) {
        return ValidationParam.builder()
                .fieldName(fieldName)
                .fieldLabel(fieldLabel)
                .required(required)
                .fieldType(String.class)
                .pattern("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$")
                .patternDesc("请输入有效的邮箱地址")
                .build();
    }

    /**
     * @description 快速创建手机号校验参数
     * @param fieldName 字段名
     * @param fieldLabel 字段标签
     * @param required 是否必填
     * @return ValidationParam
     */
    public static ValidationParam phone(String fieldName, String fieldLabel, boolean required) {
        return ValidationParam.builder()
                .fieldName(fieldName)
                .fieldLabel(fieldLabel)
                .required(required)
                .fieldType(String.class)
                .pattern("^1[3-9]\\d{9}$")
                .patternDesc("请输入有效的手机号码")
                .build();
    }
}

