package com.yfd.platform.utils.wrapper;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

public class QueryWrapperBuilder {
    // 字段缓存：类 -> 字段名集合（包含驼峰和下划线格式）
    private static final Map<Class<?>, Set<String>> FIELD_CACHE = new ConcurrentHashMap<>();
    /**
     * 将 QueryCondition 转换为 MyBatis-Plus 的 QueryWrapper
     *
     * @param condition   查询条件
     * @param entityClass 实体类（用于字段合法性校验）
     * @return QueryWrapper<T>
     */
    public static <T> QueryWrapper<T> build(QueryCondition condition, Class<T> entityClass) {
        QueryWrapper<T> wrapper = new QueryWrapper<>();
        // 修改 build 方法中的过滤条件处理部分
        condition.getFilters().forEach((field, value) -> {
            if (!field.contains("__")) { // 使用双下划线分隔符更安全
                return;
            }
            String[] parts = field.split("__");
            if (parts.length != 2) {
                return;
            }
            String realField = parts[0];
            String operator = parts[1];
            String column = camelToUnderline(realField);
            if (isValidField(column, entityClass)) {
                applyOperator(wrapper, column, operator, value);
            }
        });

        // 处理排序
        if (condition.getSortOrders() != null) {
            for (SortOrder order : condition.getSortOrders()) {
                String column = camelToUnderline(order.getProperty());
                if (!isValidField(column, entityClass)) {
                    continue;
                }
                if (order.getDirection() == SortDirection.ASC) {
                    wrapper.orderByAsc(column);
                } else {
                    wrapper.orderByDesc(column);
                }
            }
        }

        return wrapper;
    }

    // 在字段校验时增加格式检查
    private static boolean isValidField(String field) {
        // 只允许字母、数字和下划线
        return field.matches("^[a-zA-Z0-9_]+$");
    }

    // 运算符处理方法
    private static <T> void applyOperator(QueryWrapper<T> wrapper, String column, String operator, Object value) {
        switch (operator.toLowerCase()) {
            case "eq":
                wrapper.eq(column, value);
                break;
            case "ne":
                wrapper.ne(column, value);
                break;
            case "gt":
                wrapper.gt(column, value);
                break;
            case "ge":
                wrapper.ge(column, value);
                break;
            case "lt":
                wrapper.lt(column, value);
                break;
            case "le":
                wrapper.le(column, value);
                break;
            case "like":
                wrapper.like(column, value);
                break;
            case "notlike":
                wrapper.notLike(column, value);
                break;
            case "in":
                if (value instanceof Collection) {
                    wrapper.in(column, (Collection<?>) value);
                }
                break;
            default:
                throw new IllegalArgumentException("不支持的运算符: " + operator);
        }
    }

    // 驼峰转下划线（工具方法）
    private static String camelToUnderline(String str) {
        return str.replaceAll("([a-z0-9])([A-Z])", "$1_$2").toLowerCase();
    }

    // 下划线转驼峰（支持反向校验）
    private static String underlineToCamel(String str) {
        if (!str.contains("_")) {
            return str;
        }

        StringBuilder sb = new StringBuilder();
        String[] parts = str.split("_");
        sb.append(parts[0]);
        for (int i = 1; i < parts.length; i++) {
            if (!parts[i].isEmpty()) {
                sb.append(Character.toUpperCase(parts[i].charAt(0)));
                sb.append(parts[i].substring(1));
            }
        }
        return sb.toString();
    }

    // 字段合法性校验（扩展点）
    private static <T> boolean isValidField(String field, Class<T> entityClass) {
        // 双重校验：1.原始字段 2.驼峰转下划线反向校验
        return containsField(entityClass, field) ||
                containsField(entityClass, underlineToCamel(field));
    }

    private static <T> boolean containsField(Class<T> entityClass, String fieldName) {
        // 获取或缓存字段集合
        Set<String> fields = FIELD_CACHE.computeIfAbsent(entityClass, clazz ->
                Arrays.stream(clazz.getDeclaredFields())
                        .map(Field::getName)
                        .collect(Collectors.toSet())
        );

        return fields.contains(fieldName);
    }
}
