package org.xyzh.common.utils.validation.method;

import java.lang.reflect.Field;
import java.util.function.BiFunction;

/**
 * @description 字段比较校验方法，用于比较对象中的两个字段
 * @filename FieldCompareValidateMethod.java
 * @author Claude Code
 * @copyright xyzh
 * @since 2025-12-26
 */
public class FieldCompareValidateMethod implements ObjectValidateMethod {

    /**
     * 第一个字段名称
     */
    private final String field1Name;

    /**
     * 第二个字段名称
     */
    private final String field2Name;

    /**
     * 字段标签（用于错误消息）
     */
    private final String fieldLabel;

    /**
     * 比较函数：(field1Value, field2Value) -> Boolean
     * 返回 true 表示校验通过，false 表示校验失败
     */
    private final BiFunction<Object, Object, Boolean> compareFunction;

    /**
     * 自定义错误消息
     */
    private final String customErrorMessage;

    /**
     * 构造函数
     *
     * @param field1Name 第一个字段名称
     * @param field2Name 第二个字段名称
     * @param fieldLabel 字段标签
     * @param compareFunction 比较函数
     * @param customErrorMessage 自定义错误消息
     */
    public FieldCompareValidateMethod(String field1Name,
                                      String field2Name,
                                      String fieldLabel,
                                      BiFunction<Object, Object, Boolean> compareFunction,
                                      String customErrorMessage) {
        this.field1Name = field1Name;
        this.field2Name = field2Name;
        this.fieldLabel = fieldLabel;
        this.compareFunction = compareFunction;
        this.customErrorMessage = customErrorMessage;
    }

    @Override
    public Boolean validate(Object targetObject) {
        if (targetObject == null) {
            return true;
        }

        try {
            // 获取第一个字段的值
            Object field1Value = getFieldValue(targetObject, field1Name);

            // 获取第二个字段的值
            Object field2Value = getFieldValue(targetObject, field2Name);

            // 如果任意字段为null，跳过校验
            if (field1Value == null || field2Value == null) {
                return true;
            }

            // 执行比较函数
            return compareFunction.apply(field1Value, field2Value);

        } catch (Exception e) {
            throw new RuntimeException("字段比较校验失败: " + e.getMessage(), e);
        }
    }

    @Override
    public String getErrorMessage() {
        if (customErrorMessage != null && !customErrorMessage.trim().isEmpty()) {
            return customErrorMessage;
        }
        return fieldLabel + "校验失败";
    }

    @Override
    public String getName() {
        return "字段比较校验";
    }

    /**
     * 获取字段值（支持嵌套字段）
     *
     * @param obj 对象
     * @param fieldName 字段名称（支持 "field" 或 "nested.field"）
     * @return 字段值
     */
    private Object getFieldValue(Object obj, String fieldName) throws Exception {
        if (fieldName == null || fieldName.trim().isEmpty()) {
            return null;
        }

        // 支持嵌套字段访问（如 "user.name"）
        String[] fieldParts = fieldName.split("\\.");
        Object currentObj = obj;

        for (String part : fieldParts) {
            if (currentObj == null) {
                return null;
            }

            // 获取字段
            Field field = findField(currentObj.getClass(), part);
            if (field == null) {
                throw new NoSuchFieldException("字段不存在: " + part);
            }

            // 设置可访问
            field.setAccessible(true);

            // 获取字段值
            currentObj = field.get(currentObj);
        }

        return currentObj;
    }

    /**
     * 查找字段（包括父类）
     *
     * @param clazz 类
     * @param fieldName 字段名称
     * @return 字段
     */
    private Field findField(Class<?> clazz, String fieldName) {
        Class<?> currentClass = clazz;
        while (currentClass != null) {
            try {
                return currentClass.getDeclaredField(fieldName);
            } catch (NoSuchFieldException e) {
                currentClass = currentClass.getSuperclass();
            }
        }
        return null;
    }
}
