package org.example.Utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import jakarta.servlet.http.HttpSession;
import org.example.Entity.System.LoginUserInfo;
import org.example.Enums.SystemEnums;
import org.example.Enums.SystemTypeEnums;
import org.example.Impl.BaseImpl;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.imageio.ImageIO;
import javax.script.ScriptException;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.security.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static org.apache.ibatis.ognl.OgnlOps.convertValue;
import static org.example.Enums.SystemEnums.BillMenuEnum.*;
import static org.example.Enums.SystemEnums.ControlType.LabDateTime;
import static org.springframework.data.config.ParsingUtils.setPropertyValue;

public class PublicUtil {
    private static final Logger log = LoggerFactory.getLogger(PublicUtil.class);



    // 字符串转 bool
    public static Object EvalCond(String cond, JsEngine.ErrorHandler onError, boolean replaceEd) {
        if (cond == null || cond.isEmpty()) {
            return true;
        }
        if (cond.startsWith("!") || cond.startsWith("@")) {
            return true;
        }
        if (cond.indexOf("{") > -1) {
            String _cond = cond;
            if (!replaceEd) {
                _cond = SqlToCode(cond);
            }
            return JsEngine.Eval(ReqSqlPmsByRow(null, null, _cond, SystemTypeEnums.PmType.sql, null), onError);
        }
        return JsEngine.Eval(cond, onError);
    }

    public static Object EvalCond(String cond) {
        return EvalCond(cond, null, true);
    }

    // 检查是否有字段属性方法
// 反射工具方法：检查对象是否有指定属性
// 缓存类的方法，避免重复反射（提升性能）
    private static final ConcurrentHashMap<Class<?>, Map<String, Method>> METHOD_CACHE = new ConcurrentHashMap<>();

    /**
     * 检查对象是否有指定属性（支持任意类型）
     */
    public static boolean hasProperty(Object obj, String propertyName) {
        if (obj == null || propertyName == null || propertyName.isEmpty()) {
            return false;
        }

        try {
            // 1. 检查标准 JavaBean 属性（通过 getter）
            Class<?> clazz = obj.getClass();
            // 尝试标准 getter: getXxx()
            String getterName = "get" + capitalize(propertyName);
            Method getter = clazz.getMethod(getterName);
            if (getter != null) {
                Object value = getter.invoke(obj);
                return value != null; // 关键修改：验证值非空
            }
            return false;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 设置对象属性值（适用于所有 DTO）
     */
    public static void setPropertyValue(Object obj, String propertyName, Object value) {
        if (obj == null || propertyName == null || propertyName.isEmpty()) {
            return;
        }

        try {
            Class<?> clazz = obj.getClass();
            BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
            PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();

            for (PropertyDescriptor descriptor : descriptors) {
                if (descriptor.getName().equalsIgnoreCase(propertyName)) {
                    Method setter = descriptor.getWriteMethod();
                    if (setter != null) {
                        // 处理基本类型的自动装箱/拆箱
                        Object convertedValue = convertValue(value, setter.getParameterTypes()[0]);
                        setter.invoke(obj, convertedValue);
                    }
                    return;
                }
            }
        } catch (Exception e) {
            log.error("Exception caught", e);
            // 处理异常：记录日志或抛出运行时异常
        }
    }

    /**
     * 首字母大写
     */
    private static String capitalize(String str) {
        if (str == null || str.isEmpty()) return str;
        return Character.toUpperCase(str.charAt(0)) + str.substring(1);
    }


    /**
     * 将源对象转换为目标类型的对象(任意转任意)
     *
     * @param source      源对象
     * @param targetClass 目标类型的Class
     * @param <T>         目标类型的泛型
     * @return 转换后的目标对象
     */
    public static <T> T convert(Object source, Class<T> targetClass) {
        if (source == null || targetClass == null) {
            return null;
        }

        try {
            // 创建目标类的实例
            T target = targetClass.getDeclaredConstructor().newInstance();

            // 1. 复制基础属性（通过 getter/setter）
            Map<String, PropertyDescriptor> sourceProperties = getPropertyDescriptors(source.getClass());
            Map<String, PropertyDescriptor> targetProperties = getPropertyDescriptors(targetClass);

            for (String propertyName : targetProperties.keySet()) {
                if (sourceProperties.containsKey(propertyName)) {
                    PropertyDescriptor sourcePd = sourceProperties.get(propertyName);
                    PropertyDescriptor targetPd = targetProperties.get(propertyName);

                    if (isAssignable(sourcePd.getPropertyType(), targetPd.getPropertyType())) {
                        Method readMethod = sourcePd.getReadMethod();
                        Method writeMethod = targetPd.getWriteMethod();

                        if (readMethod != null && writeMethod != null) {
                            Object value = readMethod.invoke(source);
                            writeMethod.invoke(target, value);
                        }
                    }
                }
            }

            return target;

        } catch (Exception e) {
            throw new RuntimeException("对象转换失败: " + e.getMessage(), e);
        }
    }


    /**
     * 将列表转换为目标类型的列表
     */
    public static <S, T> List<T> convertList(List<S> sourceList, Class<T> targetClass) {
        if (sourceList == null || sourceList.isEmpty()) {
            return Collections.emptyList();
        }

        return sourceList.stream().map(source -> convert(source, targetClass)).collect(Collectors.toList());
    }

    /**
     * 将 Map<String, Object> 转换为任意类型的 DTO
     */
    public static <T> T convertMapToDto(Map<String, Object> sourceMap, Class<T> targetClass) {
        if (sourceMap == null || targetClass == null) {
            return null;
        }

        try {
            T target = targetClass.getDeclaredConstructor().newInstance();
            BeanInfo beanInfo = Introspector.getBeanInfo(targetClass);

            // 构建小写键的Map，用于大小写不敏感匹配
            Map<String, Object> lowerCaseSourceMap = new HashMap<>();
            for (Map.Entry<String, Object> entry : sourceMap.entrySet()) {
                lowerCaseSourceMap.put(entry.getKey().toLowerCase(), entry.getValue());
            }

            for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) {
                String propertyName = pd.getName();
                Method setter = pd.getWriteMethod();

                if (setter != null) {
                    Object value = null;

                    // 1. 尝试精确匹配
                    if (sourceMap.containsKey(propertyName)) {
                        value = sourceMap.get(propertyName);
                    }
                    // 2. 尝试大小写不敏感匹配
                    else {
                        String lowerCasePropertyName = propertyName.toLowerCase();
                        if (lowerCaseSourceMap.containsKey(lowerCasePropertyName)) {
                            value = lowerCaseSourceMap.get(lowerCasePropertyName);
                        }
                    }

                    if (value != null) {
                        Object convertedValue = convertType(value, pd.getPropertyType());
                        setter.invoke(target, convertedValue);
                    }
                }
            }

            return target;

        } catch (Exception e) {
            throw new RuntimeException("Map转换为DTO失败: " + e.getMessage(), e);
        }
    }

    /**
     * 类型转换辅助方法
     */
    private static Object convertType(Object value, Class<?> targetType) {
        if (value == null) {
            return null;
        }

        // 如果类型已经匹配，直接返回
        if (targetType.isAssignableFrom(value.getClass())) {
            return value;
        }

        // 处理基本数据类型
        if (targetType == String.class) {
            return value.toString();
        } else if (targetType == Integer.class || targetType == int.class) {
            return Integer.valueOf(value.toString());
        } else if (targetType == Long.class || targetType == long.class) {
            return Long.valueOf(value.toString());
        } else if (targetType == Double.class || targetType == double.class) {
            return Double.valueOf(value.toString());
        } else if (targetType == Boolean.class || targetType == boolean.class) {
            return Boolean.valueOf(value.toString());
        }
        // 可以添加更多类型转换逻辑，如日期类型等

        return value; // 默认不转换
    }

    /**
     * 获取类的所有属性描述符
     */
    private static Map<String, PropertyDescriptor> getPropertyDescriptors(Class<?> clazz) {
        Map<String, PropertyDescriptor> properties = new HashMap<>();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
            for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) {
                if (!"class".equals(pd.getName())) {
                    properties.put(pd.getName(), pd);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("获取类属性失败: " + e.getMessage(), e);
        }
        return properties;
    }

    /**
     * 检查源类型是否可以赋值给目标类型，或支持简单的类型转换
     */
    private static boolean isAssignable(Class<?> sourceType, Class<?> targetType) {
        // 基本类型及其包装类的兼容性检查
        if (targetType.isAssignableFrom(sourceType)) {
            return true;
        }

        // 处理基本类型和包装类的转换
        if (sourceType.isPrimitive()) {
            sourceType = getWrapperClass(sourceType);
        }

        if (targetType.isPrimitive()) {
            targetType = getWrapperClass(targetType);
        }

        // 字符串到基本类型/包装类的转换
        if (String.class.equals(sourceType)) {
            return targetType.equals(String.class) || targetType.equals(Integer.class) || targetType.equals(Long.class) || targetType.equals(Double.class) || targetType.equals(Float.class) || targetType.equals(Boolean.class);
        }

        return false;
    }

    /**
     * 获取基本类型对应的包装类
     */
    private static Class<?> getWrapperClass(Class<?> primitiveType) {
        if (int.class.equals(primitiveType)) return Integer.class;
        if (long.class.equals(primitiveType)) return Long.class;
        if (double.class.equals(primitiveType)) return Double.class;
        if (float.class.equals(primitiveType)) return Float.class;
        if (boolean.class.equals(primitiveType)) return Boolean.class;
        if (char.class.equals(primitiveType)) return Character.class;
        if (byte.class.equals(primitiveType)) return Byte.class;
        if (short.class.equals(primitiveType)) return Short.class;
        return primitiveType;
    }

    //    SqlToCode方法
    public static String SqlToCode(String str) {
        // 1. 复刻C#的string.IsNullOrEmpty判断
        if (str == null || str.isEmpty()) {
            return "";
        }

        // 2. 复刻前缀判断：以@或!开头直接返回原字符串
        if (str.startsWith("@") || str.startsWith("!")) {
            return str;
        }

        // 3. 第一步替换：双引号替换为单引号
        String result = str.replace("\"", "'");

        // 4. 正则替换1：or → ||（匹配独立的or关键词）
        String regexOr = "(?is)(?<=([ \\r\\n\\)\\'\\}]))or(?=([ \\r\\n\\(\\'\\{]))";
        result = replaceWithRegex(result, regexOr, "||");

        // 5. 正则替换2：and → &&（匹配独立的and关键词）
        String regexAnd = "(?is)(?<=([ \\r\\n\\)\\'\\}]))and(?=([ \\r\\n\\(\\'\\{]))";
        result = replaceWithRegex(result, regexAnd, "&&");

        // 6. 正则替换3：多个等号 → ==
        String regexEqual = "(?is)(?<=([ \\r\\n\\)\\'])?[^><!])=+(?=([ \\r\\n\\(\\'])?)";
        result = replaceWithRegex(result, regexEqual, "==");

        // 7. 正则替换4：<> → !=
        String regexNotEqual = "(?is)(?<= |\\r\\n|\\)|'?)<>(?= |\\r\\n|\\(|'?)";
        result = replaceWithRegex(result, regexNotEqual, "!=");

        // 8. 正则替换5：>== → >=
        String regexGreaterEqual = "(?is)(?<=([ \\r\\n\\)\\']))>==(?=([ \\r\\n\\(\\']))";
        result = replaceWithRegex(result, regexGreaterEqual, ">=");

        // 9. 正则替换6：<== → <=
        String regexLessEqual = "(?is)(?<=([ \\r\\n\\)\\']))<==(?=([ \\r\\n\\(\\']))";
        result = replaceWithRegex(result, regexLessEqual, "<=");

        return result;
    }

    private static String replaceWithRegex(String input, String regex, String replacement) {
        // 编译正则：对应C\#的RegexOptions.IgnoreCase + RegexOptions.Multiline
        // (?i)=IgnoreCase，(?s)=DOTALL，Pattern.MULTILINE对应C\#的Multiline
        Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
        Matcher matcher = pattern.matcher(input);
        return matcher.replaceAll(replacement);
    }

    // ReqSqlPmsByRow方法
    public static String ReqSqlPmsByRow(Map<String, Object> rowMap, Map<String, Object> leftMap, String param, SystemTypeEnums.PmType pmType) {
        return ReqSqlPmsByRow(rowMap, leftMap, param, pmType, null);
    }

    public static String ReqSqlPmsByRow(Map<String, Object> rowMap, Map<String, Object> leftMap, String param) {
        return ReqSqlPmsByRow(rowMap, leftMap, param, SystemTypeEnums.PmType.sql, null);
    }

    public static String ReqSqlPmsByRow(Map<String, Object> rowMap, Map<String, Object> leftMap, String param, SystemTypeEnums.PmType pmType, LoginUserInfo user) {
        if (user == null) {
            user = new BaseImpl().getUser();
        }
        return new PmAnalyzer(user, param, pmType).FillPms(rowMap, leftMap, pmType);
    }

    public static String ReqSqlPms(Map<String, Object> rowMap, Map<String, Object> leftMap, String param, SystemTypeEnums.PmType pmType, LoginUserInfo user) {
        if (user == null) {
            user = new BaseImpl().getUser();
        }
        return new PmAnalyzer(user, param, pmType).FillPms(rowMap, leftMap, pmType);
    }

    public static List<String> getParamValue(String param) {
        String sqlParamRegex = "\\{([^{|}])+}";
        List<String> list = new ArrayList<>();
        Pattern pattern = Pattern.compile(sqlParamRegex);
        Matcher matcher = pattern.matcher(param);
        while (matcher.find()) {
            String value = matcher.group();
            if (!list.contains(value)) {
                list.add(value);
            }
        }
        return list;
    }

    // 获取用户权限信息
    public static String GetPurviews(Map<String, Object> dt) {
        StringBuilder kcPurview = new StringBuilder();
        for (Map.Entry<String, Object> entry : dt.entrySet()) {
            String columnName = entry.getKey();
            String purview = Objects.toString(entry.getValue(), "");
            if (!purview.isEmpty() && columnName.toLowerCase().indexOf("purview") > -1) {
                kcPurview.append(purview).append(",");
            }
        }
        return kcPurview.toString();
    }

    // 检查权限
    public static String CheckPurview(LoginUserInfo user, String kcPurview, String menuid) {
        if (user == null && RequestContextHolder.getRequestAttributes() != null) {
            HttpSession session = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getSession();
            if (session != null) {
                user = new BaseImpl().getUser();
            }
        }
        if (user != null && "管理员".equals(user.UserName)) {
            return "AllPurview";
        }
        if (kcPurview == null || kcPurview.isEmpty() || menuid == null || menuid.isEmpty()) {
            return "";
        }
        kcPurview = "," + kcPurview + ",";
        String allPurview = "," + menuid + ",";
        String readPurview = "," + menuid + "|,";
        if (!kcPurview.contains(allPurview)) {
            if (!kcPurview.contains(readPurview)) {
                return "";
            } else {
                return "ReadPurview";
            }
        } else {
            return "AllPurview";
        }
    }

    // 获取单据右键菜单的查询前缀
    public static String GetBillConMenuKey(SystemEnums.BillMenuEnum _enum) {
        switch (_enum) {
            case BillSource:
                return "BILLSOURCE_";
            case BillSourceDetail:
                return "SOURCEDETAIL_";
            case BillDetail:
                return "BILLDETAIL_";
            default:
                return "";
        }
    }

    // ext 时间格式 format 转换为对应的程序的 format
    public static String ExtDateFormatToPro(String sourceformat) {
        if (sourceformat == null || sourceformat.isEmpty()) {
            return null;
        }
        String formater = sourceformat.replaceAll("y+", "yyyy");
        formater = formater.replaceAll("m+", "MM");
        formater = formater.replaceAll("d+", "dd");
        formater = formater.replaceAll("D+", "DD");
        formater = formater.replaceAll("s+", "ss");
        formater = formater.replaceAll("h+", "hh");
        formater = formater.replaceAll("H+", "HH");
        formater = formater.replaceAll("i+", "MM");
        return formater;
    }

    // 程序的 format 转换为对应的 ext 时间格式
    public static String ProDateFormatToExt(String sourceformat) {
        if (sourceformat == null || sourceformat.isEmpty()) {
            return null;
        }
        String formater = sourceformat.replaceAll("y+", "Y");
        formater = formater.replaceAll("m+", "i");
        formater = formater.replaceAll("M+", "m");
        formater = formater.replaceAll("d+", "d");
        formater = formater.replaceAll("D+", "D");
        formater = formater.replaceAll("s+", "s");
        formater = formater.replaceAll("h+", "h");
        formater = formater.replaceAll("H+", "H");
        return formater;
    }

    // 获取一些默认的格式
    public static String GetFormatByCType(int ctype) {
        SystemEnums.ControlType _FieldType = SystemEnums.ControlType.values()[ctype];
        return GetFormatByCType(_FieldType);
    }

    public static String GetFormatByCType(SystemEnums.ControlType ctype) {
        String format = null;
        switch (ctype) {
            case LabDate:
                format = format == null ? "yyyy-MM-dd" : format;
                break;
            case LabDateTime:
            case LabCheckDateTimeShort:
                format = format == null ? "yyyy-MM-dd HH:mm:ss" : format;
                break;
            case LabDateTimeShort:
                format = format == null ? "yyyy-MM-dd HH:mm" : format;
                break;
            case LabTime:
            case LabCheckTime:
                format = format == null ? "HH:mm:ss" : format;
                break;
            case LabShortTime:
            case LabCheckShortTime:
                format = format == null ? "HH:mm" : format;
                break;
            case LabYearTime:
            case LabLabYearTime:
                format = format == null ? "yyyy-MM" : format;
                break;
            default:
                format = null;
                break;
        }
        return format;
    }

    // ctype 转换为程序类型字符串
    public static SystemTypeEnums.FieldType GetProTypeByCType(SystemEnums.ControlType ctype) {
        switch (ctype) {
            case LabQQ:
            case LabWWW:
            case LabText:
            case LabRemark:
            case LabComboxText:
            case LabComboxValue:
            case LabMultiSelectText:
            case LabMultiSelectValue:
            case LabComboxTextParam:
            case LabComboxValueParam:
                return SystemTypeEnums.FieldType.VarChar;
            case LabCheckDateTimeShort:
            case LabCheckTime:
            case LabCheckShortTime:
            case LabDate:
            case LabDateTime:
            case LabDateTimeShort:
            case LabTime:
            case LabShortTime:
                return SystemTypeEnums.FieldType.DateTime;
            case LabPhone:
            case LabTextInt:
                return SystemTypeEnums.FieldType.Int32;
            default:
                return SystemTypeEnums.FieldType.Text;
        }
    }

    // 转换为 ext column 类型
    public static String GetEColumnTypeByCType(SystemEnums.ControlType ctype) {
        switch (ctype) {
            case LabCheckDateTimeShort:
            case LabCheckTime:
            case LabCheckShortTime:
            case LabDate:
            case LabDateTime:
            case LabDateTimeShort:
            case LabTime:
            case LabShortTime:
                return "datecolumn";
            case LabPicEx:
                return "filecolumn";
            case LabTextInt:
                return "numbercolumn";
            case LabProgress:
                return "progresscolumn";
            case LabCheckBox:
                return "checkcolumn";
            default:
                return "gridcolumn";
        }
    }

    public static String TypeToColumnType(Class<?> ctype) {
        if (Date.class.isAssignableFrom(ctype) ||
                LocalDate.class.isAssignableFrom(ctype) ||
                LocalDateTime.class.isAssignableFrom(ctype) ||
                Timestamp.class.isAssignableFrom(ctype)) {
            return "datecolumn";
        }
//        if (ctype == Timestamp.class) {
//            return "datecolumn";
//        }
        if (ctype == Integer.class || ctype == Float.class || ctype == Double.class || ctype == Long.class || ctype == java.math.BigDecimal.class) {
            return "numbercolumn";
        }
        if (ctype == Boolean.class) {
            return "checkcolumn";
        }
        return "gridcolumn";
    }

    // 转换为 ext data.field 类型
    public static String GetEFieldTypeByCType(SystemEnums.ControlType ctype, String format) {
        switch (ctype) {
            case LabCheckDateTimeShort:
            case LabCheckTime:
            case LabCheckShortTime:
            case LabDate:
            case LabDateTime:
            case LabDateTimeShort:
            case LabTime:
            case LabShortTime:
                return "date";
            case LabTextInt:
                if ((format + "").indexOf(".") > -1 || format == null || format.isEmpty()) {
                    return "float";
                }
                return "int";
            case LabCheckBox:
                return "bool";
            default:
                return "auto";
        }
    }

    // 获取各类型的默认值
    public static Object GetDefaultValByCType(SystemEnums.ControlType ctype) {
        switch (ctype) {
            case LabCheckDateTimeShort:
            case LabCheckTime:
            case LabCheckShortTime:
            case LabDate:
            case LabDateTime:
            case LabDateTimeShort:
            case LabTime:
            case LabShortTime:
                return new Date(System.currentTimeMillis());
            case LabTextInt:
                return 0;
            case LabCheckBox:
                return true;
            default:
                return "";
        }
    }

    // 获取 sql 操作的各类型的默认值
    public static String GetSqlDefaultValByCType(SystemEnums.ControlType ctype) {
        switch (ctype) {
            case LabCheckDateTimeShort:
            case LabCheckTime:
            case LabCheckShortTime:
            case LabDate:
            case LabDateTime:
            case LabDateTimeShort:
            case LabTime:
            case LabShortTime:
                return "null";
            case LabTextInt:
                return "0";
            default:
                return "''";
        }
    }

    /**
     * 根据数据类型获取SQL默认值
     *
     * @param type     数据类型Class对象
     * @param nullAble 是否允许为null
     * @return SQL默认值字符串
     */
    public static String GetSqlDefaultValByType(Class<?> type, boolean nullAble) {
        String value;
        if (type == null) {
            return "''";
        }
        if (type == Timestamp.class || type.getSuperclass() == Timestamp.class) {
            value = "null";
            if (!nullAble) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                return "'" + sdf.format(new Date(System.currentTimeMillis())) + "'";
            }
        }    // 处理值类型（对应C#中ValueType）
        else if (isValueType(type)) {
            value = "0";
        }
        // 引用类型默认返回空字符串
        else {
            value = "''";
        }

        return value;
    }

    /**
     * 判断子类关系（模拟C#的IsSubclassOf）
     *
     * @param child  子类
     * @param parent 父类
     * @return 是否为子类
     */
    private static boolean isSubclassOf(Class<?> child, Class<?> parent) {
        if (child == null || parent == null) {
            return false;
        }
        return parent.isAssignableFrom(child) && !child.equals(parent);
    }

    /**
     * 判断是否为值类型（模拟C#的ValueType）
     * Java中值类型包括基本类型及其包装类、枚举等
     *
     * @param type 类型
     * @return 是否为值类型
     */
    private static boolean isValueType(Class<?> type) {
        if (type == null) {
            return false;
        }
        // 基本类型（int, long, double等）
        if (type.isPrimitive()) {
            return true;
        }
        // 基本类型包装类（Integer, Long, Double等）
        if (type == Integer.class || type == Long.class || type == Double.class ||
                type == Float.class || type == Short.class || type == Byte.class ||
                type == Boolean.class || type == Character.class) {
            return true;
        }
        // 枚举类型
        if (type.isEnum()) {
            return true;
        }
        // 其他值类型判断（根据实际需求扩展）
        return false;
    }

    //达梦的适配xtype
    public static int DMSqltypeToProType(String type) {
        switch (type) {
            case "DATETIME":
                return 40;
            case "BLOB":
                return 34;
            case "TEXT":
                return 35;
            //99没有查到
            case "VARCHAR":
                return 167;
            //173没有用户表
            case "NCHAR":
                return 173;
            case "NVARCHAR":
                return 231;
            case "VARBINARY":
                return 165;
            case "CHAR":
                return 175;
            //36在达梦中为VARCHAR
            //8018为人大金仓的
            //8016为人大金仓的
//                return String.class;

            case "DATE":
                return 40;
            case "TIME":
                return 41;
            //42对应为TIMESTAMP
            //58没有查到
            case "TIMESTAMP"://对应61
                return 42;
            case "BINARY"://对应189
                return 189;
            //43没有用户表
            //7881为人大金仓的
            //7754为人大金仓的
//                return Timestamp.class;

            case "SMALLINT":
                return 48;
            //52在达梦中为SMALLINT
            case "INT":
                return 56;
            //5063为人大金仓的
//                return Integer.class;

            case "REAL":
                return 59;
            case "DOUBLE":
                return 62;
//                return Float.class;

            case "DECIMAL":
                return 106;
            case "NUMERIC":
                return 108;
            //122没有查到
            //60在达梦中为DECIMAL
            //5067为人大金仓的
//                return Double.class;

            case "BIT":
                return 104;
//                return Boolean.class;

            case "BIGINT":
                return 127;
//                return Long.class;
//
            default:
                return 0;
//                return String.class;

        }
    }

    // 将数据库 xtype 类型转换为程序类型
    public static Class<?> SqlxtypeToProType(int xtype) {
        switch (xtype) {
            case 34:
            case 35:
            case 99:
            case 167:
            case 173:
            case 239:
            case 231:
            case 165:
            case 175:
            case 36:
            case 8018:
            case 8016:
                return String.class;
            case 40:
            case 41:
            case 42:
            case 58:
            case 61:
            case 189:
            case 43:
            case 7881:
            case 7754:
                return Timestamp.class;
            case 48:
            case 52:
            case 56:
            case 5063:
                return Integer.class;
            case 59:
            case 62:
                return Float.class;
            case 106:
            case 108:
            case 122:
            case 60:
            case 5067:
                return Double.class;
            case 104:
                return Boolean.class;
            case 127:
                return Long.class;
            default:
                return String.class;
        }
    }

    // URL 转换为 Dll 信息
    public static Map<String, String> UrlToDllInfo(String url) {
        if (url.indexOf("app.html") > -1) {
            Map<String, String> queryPms = new HashMap<>();
            String[] parts = url.split("\\?");
            if (parts.length > 1) {
                String[] params = parts[1].split("&");
                for (String param : params) {
                    String[] kv = param.split("=");
                    if (kv.length > 1) {
                        if (!kv[0].toLowerCase().equals("username") && !kv[0].toLowerCase().equals("password")) {
                            queryPms.put(kv[0].toLowerCase(), kv[1]);
                        }
                    }
                }
                if (queryPms.containsKey("xtype")) {
                    queryPms.put("moduleid", queryPms.getOrDefault("moduleid", queryPms.getOrDefault("dllcoid", "")));
                    queryPms.put("idValue", queryPms.getOrDefault("idvalue", queryPms.getOrDefault("id", "")));
                }
            }
            return queryPms;
        }
        return null;
    }

    // 加带有账号密码的链接转换为加密链接
    public static String ToEnUrl(String url) {
        String[] urlParams = url.split("\\?");
        if (urlParams.length > 1) {
            String[] queryParams = urlParams[1].split("&");
            List<String> qpLS = new ArrayList<>();
            Map<String, Object> pms = new HashMap<>();
            for (String q : queryParams) {
                String[] eqParams = q.split("=");
                if (eqParams.length > 1) {
                    if (eqParams[0].toLowerCase().equals("username") || eqParams[0].toLowerCase().equals("password")) {
                        pms.put(eqParams[0], eqParams[1]);
                    } else {
                        qpLS.add(eqParams[0] + "=" + java.net.URLEncoder.encode(eqParams[1]));
                    }
                }
            }
            if (!pms.isEmpty()) {
                Calendar calendar = Calendar.getInstance();
                calendar.add(Calendar.DAY_OF_YEAR, 1);
                long timestamp = calendar.getTimeInMillis() / 1000;
                pms.put("exp", timestamp);
            }
            // 这里需要实现 AESUtil.MobileEncrypt 和 JSON.Encode 的逻辑
            String encryptedPms = "";
            try {
                encryptedPms = java.net.URLEncoder.encode(encryptedPms);
            } catch (Exception e) {
                log.error("Exception caught", e);
            }
            return urlParams[0] + "?" + String.join("&", qpLS) + "&pms=" + encryptedPms;
        }
        return url;
    }

    // 注意：方法必须返回处理后的新字符串，不能是void！
    public static String fixSqlCompatibility(String sql) {
        if (sql == null || sql.isEmpty()) {
            return sql;
        }
        log.debug(String.valueOf("sql: " + sql));
        // 1. 移除with(nolock)（兼容：with(nolock)、WITH(NOLOCK)、with ( nolock ) 等格式）
        String sqlAfterRemoveNolock = sql.replaceAll("(?i)with\\s*\\(\\s*nolock\\s*\\)", "");
        log.debug(String.valueOf("移除with(nolock)后：" + sqlAfterRemoveNolock)); // 加日志验证这一步是否生效

        // 2. 替换convert日期转换为cast（解决格式码120的兼容性问题）
        Pattern convertPattern = Pattern.compile(
                "convert\\(date,\\s*convert\\(varchar\\(10\\),\\s*(\\w+\\.\\w+)\\s*,\\s*120\\)\\s*\\)",
                Pattern.CASE_INSENSITIVE
        );
        String sqlAfterFixConvert = convertPattern.matcher(sqlAfterRemoveNolock).replaceAll("cast($1 as date)");
        log.debug(String.valueOf("修复convert后：" + sqlAfterFixConvert)); // 加日志验证这一步

        // 3. 给表名加dbo.前缀（处理from/join后的表）
        String sqlAfterAddDbo = sqlAfterFixConvert
                .replaceAll("(?i)from\\s+(\\w+)(\\s+\\w+)?", "from dbo.$1$2") // from 表名
                .replaceAll("(?i)join\\s+(\\w+)(\\s+\\w+)?", "join dbo.$1$2"); // join 表名
        log.debug(String.valueOf("添加dbo.前缀后：" + sqlAfterAddDbo)); // 加日志验证这一步
        return sqlAfterAddDbo;
    }

    public static String EvalCondtionToCode(String str) {
        if (NativeExtensionUtils.isNullOrEmpty(str)) {
            return str;
        }
        str = str.replace(" ", "")
                .replace("''<", "0<")
                .replace("''>", "0>")
                .replace(">''", ">0")
                .replace("<''", "<0")
                .replace("--", "+")
                .replace("!===", "!=")
                .replace(">==", ">=")
                .replace("<==", "<=");
        return str;
    }

    public static String GenerateRandomCode(int length) {
        final String chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
        var random = new Random();
        // 用StringBuilder高效拼接字符（Java中替代string拼接）
        StringBuilder sb = new StringBuilder(length);

        // 核心逻辑：循环length次，每次随机选一个字符
        for (int i = 0; i < length; i++) {
            int randomIndex = random.nextInt(chars.length());
            sb.append(chars.charAt(randomIndex));
        }

        // 转成最终字符串返回
        return sb.toString();
    }

    //

    /**
     * 生成验证码图片，输出到OutputStream（对应C#的MemoryStream）
     *
     * @param code         验证码字符串（如之前生成的随机码）
     * @param outputStream 输出流（MemoryStream对应Java的ByteArrayOutputStream）
     * @throws IOException 图片写入异常
     */
    public static void GenerateCaptchaImage(String code, OutputStream outputStream) throws IOException {
        int charSpacing = 15; // 字符间距
        int startX = 5;
        // 1. 创建BufferedImage（对应C#的Bitmap）
        BufferedImage image = new BufferedImage(120, 40, BufferedImage.TYPE_INT_RGB);
        // 2. 获取Graphics2D（对应C#的Graphics）
        Graphics2D graphics = image.createGraphics();
        Random random = new Random();

        try {
            // ===== 1. 配置绘图质量（对应C#的SmoothingMode/CompositingQuality）=====
            // 抗锯齿（对应C#的SmoothingMode.AntiAlias）
            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            // 高质量插值（对应C#的CompositingQuality.HighQuality）
            graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
            // 整体渲染质量优先
            graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);

            // ===== 2. 设置白色背景（对应C#的Clear(Color.White)）=====
            graphics.setColor(Color.WHITE);
            graphics.fillRect(0, 0, 120, 40);

            // ===== 3. 绘制15条随机干扰线（对应C#的干扰线逻辑）=====
            for (int i = 0; i < 15; i++) {
                int x1 = random.nextInt(120);
                int y1 = random.nextInt(40);
                int x2 = random.nextInt(120);
                int y2 = random.nextInt(40);

                // 生成随机颜色（对应C#的Color.FromArgb(150-255, 0-100, 0-100, 0-100)）
                Color randomColor = new Color(
                        random.nextInt(106) + 150, // 150~255
                        random.nextInt(101),       // 0~100
                        random.nextInt(101),       // 0~100
                        random.nextInt(101)        // 0~100
                );
                // 随机线宽（1~2，对应C#的random.Next(1,3)）
                Stroke stroke = new BasicStroke(random.nextInt(2) + 1);
                graphics.setStroke(stroke);
                graphics.setColor(randomColor);
                graphics.drawLine(x1, y1, x2, y2);
            }

            // ===== 4. 绘制100个矩形干扰点（对应C#的矩形干扰点）=====
            for (int i = 0; i < 100; i++) {
                int x = random.nextInt(120);
                int y = random.nextInt(40);

                Color randomColor = new Color(
                        random.nextInt(106) + 150, // 150~255
                        random.nextInt(256),
                        random.nextInt(256),
                        random.nextInt(256)
                );
                graphics.setColor(randomColor);
                graphics.fillRect(x, y, 2, 2); // 2x2的矩形点
            }

            // ===== 5. 绘制验证码文字（核心：倾斜+阴影+间距）=====
            // 基础字体（对应C#的Arial 16号粗体）
            Font baseFont = new Font("Arial", Font.BOLD, 16);
            int currentX = startX;

            for (int i = 0; i < code.length(); i++) {
                char c = code.charAt(i);
                // 随机倾斜值（-0.3~0.3，对应C#的random.Next(-3,4)*0.1f）
                float shear = random.nextInt(7) - 3; // -3~3
                shear *= 0.1f;

                // 创建倾斜变换（对应C#的Matrix.Shear）
                AffineTransform transform = new AffineTransform();
                transform.shear(shear, 0); // x轴倾斜，y轴不变

                // 应用倾斜变换到字体（对应C#的shearedFont）
                Font shearedFont = baseFont.deriveFont(transform);
                graphics.setFont(shearedFont);

                // 绘制主文字（黑色，对应C#的SolidBrush(Color.Black)）
                graphics.setColor(Color.BLACK);
                graphics.drawString(String.valueOf(c), currentX, 8);

                // 绘制模糊阴影（对应C#的模糊效果：偏移1像素，半透明灰色）
                graphics.setColor(new Color(128, 128, 128, 100)); // ARGB，100是透明度
                graphics.drawString(String.valueOf(c), currentX + 1, 9);
                graphics.drawString(String.valueOf(c), currentX - 1, 7);

                // 重置变换（避免影响下一个字符）
                graphics.setTransform(new AffineTransform());

                // 增加字符间距
                currentX += charSpacing;
            }

            // ===== 6. 绘制50个椭圆前景干扰点（对应C#的前景干扰点）=====
            for (int i = 0; i < 50; i++) {
                int x = random.nextInt(120);
                int y = random.nextInt(40);

                Color randomColor = new Color(
                        random.nextInt(101) + 50, // 50~150
                        random.nextInt(256),
                        random.nextInt(256),
                        random.nextInt(256)
                );
                graphics.setColor(randomColor);
                graphics.fillOval(x, y, 1, 1); // 1x1的椭圆点
            }

            // ===== 7. 保存图片到输出流（PNG格式，对应C#的bitmap.Save）=====
            ImageIO.write(image, "PNG", outputStream);
        } finally {
            // 释放资源（对应C#的using）
            graphics.dispose();
            image.flush();
        }
    }
}
