package org.example.Utils;

import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;

public class NativeExtensionUtils {
    private NativeExtensionUtils() {
    } // 私有构造，防止实例化

    private static final Pattern NON_DIGIT_PATTERN = Pattern.compile("[^\\d\\.\\-]");
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 将对象转换为布尔值
     * 支持的类型包括：Boolean、String、Number、Character、null
     * 其他类型将返回默认值
     */
    public static boolean toBoolean(Object value) {
        return toBoolean(value, false);
    }

    public static String dmToBoolean(String input) {
        // 1. 处理空值/空字符串
        if (input == null || input.trim().isEmpty()) {
            return "";
        }

        // 2. 统一格式化：去首尾空格 + 转小写（兼容大小写、多余空格）
        String normalizedInput = input.trim().toLowerCase();

        // 3. 精准匹配目标字符串：f 或 false
        if ("f".equals(normalizedInput) || "false".equals(normalizedInput)) {
            return "0";
        }
        if ("t".equals(normalizedInput) || "ture".equals(normalizedInput)) {
            return "1";
        }
        // 4. 非目标字符串，返回格式化后的原内容（也可按需改为返回原输入/其他值）
        return normalizedInput;
    }

    /**
     * 将对象转换为布尔值，允许指定默认值
     * 支持的类型包括：Boolean、String、Number、Character、null
     */
    public static boolean toBoolean(Object value, boolean defaultValue) {
        if (value == null) {
            return defaultValue;
        }

        if (value instanceof Boolean) {
            return (Boolean) value;
        }

        if (value instanceof String) {
            String str = ((String) value).trim().toLowerCase();
            if (str.isEmpty()) {
                return defaultValue;
            }
            if ("true".equals(str) || "yes".equals(str) || "on".equals(str) || "1".equals(str)) {
                return true;
            }
            if ("false".equals(str) || "no".equals(str) || "off".equals(str) || "0".equals(str)) {
                return false;
            }
            return defaultValue;
        }

        if (value instanceof Number) {
            double num = ((Number) value).doubleValue();
            return num != 0;
        }

        if (value instanceof Character) {
            char c = (Character) value;
            return c != '0' && c != '\0';
        }

        return defaultValue;
    }

    /**
     * 安全地将字符串转换为int，处理null和空字符串
     *
     * @param str 输入字符串
     * @return 转换后的int值，若输入为null或格式错误则返回0
     */
    public static int parseInt(String str) {
        return parseInt(str, 0);
    }

    /**
     * 安全地将字符串转换为int，处理null和空字符串，并支持自定义默认值
     *
     * @param str          输入字符串
     * @param defaultValue 转换失败时的默认值
     * @return 转换后的int值，若失败则返回默认值
     */
    public static int parseInt(String str, int defaultValue) {
        if (str == null) {
            return defaultValue;
        }
        try {
            return Integer.parseInt(str.trim());
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }

    /**
     * 检查权限（示例方法，根据C#中的PublicUtil.CheckPurview实现）
     */
    public static boolean checkPurview(Object user, String purviewStr, String menuId) {
        // 实现与C#中PublicUtil.CheckPurview相同的逻辑
        // 示例返回，需根据实际需求调整
        return true;
    }

    public static int ToInt16(Object obj) {
        return (short) ToDouble(obj);
    }

    public static Integer ToInt32(Object obj) {
        return (int) ToDouble(obj);
    }

    public static long ToInt64(Object obj) {
        return (long) ToDouble(obj);
    }

    /**
     * 将任意对象转换为double类型，功能与C#版本完全一致
     *
     * @param obj 待转换的对象
     * @return 转换后的double值，失败则返回0
     */
    public static double ToDouble(Object obj) {
        // 将对象转为字符串并去除首尾空格（与C# (obj + "").Trim()等效）
        String val = Trim(obj == null ? "" : obj.toString());

        // 空字符串处理
        if (isNullOrEmpty(val)) {
            return 0;
        }

        try {
            // 检查是否包含非数字字符
            if (NON_DIGIT_PATTERN.matcher(val).find()) {
                int oldLength = val.length();
                // 去除所有非数字字符
                String intStr = NON_DIGIT_PATTERN.matcher(val).replaceAll("");

                // 处理后的字符串有效且长度小于原长度
                if (intStr.length() > 0 && intStr.length() < oldLength) {
                    return Double.parseDouble(intStr);
                }
                return 0;
            }

            // 无无效字符，直接转换原始对象
            return Double.parseDouble(val);
        } catch (Exception e) {
            // 任何异常都返回0（与C# catch所有异常一致）
            return 0;
        }
    }

    /**
     * 将任意对象转换为BigDecimal（对应C#的Decimal），功能与C#版本完全一致
     *
     * @param obj 待转换的对象
     * @return 转换后的BigDecimal值，失败则返回0
     */
    public static BigDecimal ToDecimal(Object obj) {
        // 将对象转为字符串并去除首尾空格（与C# (obj + "").Trim()等效）
        String val = (obj == null ? "" : obj.toString()).trim();

        // 空字符串处理
        if (val.isEmpty()) {
            return BigDecimal.ZERO;
        }

        // 处理布尔值情况（C#中bool类型的特殊处理）
        if (obj instanceof Boolean) {
            return (Boolean) obj ? BigDecimal.ONE : BigDecimal.ZERO;
        }

        // 处理字符串为"true"的情况（不区分大小写）
        if (val.equalsIgnoreCase("true")) {
            return BigDecimal.ONE;
        }

        try {
            // 检查是否包含非数字字符
            if (NON_DIGIT_PATTERN.matcher(val).find()) {
                int oldLength = val.length();
                // 去除所有非数字字符
                String intStr = NON_DIGIT_PATTERN.matcher(val).replaceAll("");

                // 处理后的字符串有效且长度小于原长度
                if (intStr.length() > 0 && intStr.length() < oldLength) {
                    return new BigDecimal(intStr);
                }
                return BigDecimal.ZERO;
            }

            // 无无效字符，直接转换原始对象
            return new BigDecimal(val);
        } catch (Exception e) {
            // 任何异常都返回0（与C# catch所有异常一致）
            return BigDecimal.ZERO;
        }
    }


    private static class DateFormatHolder {
        // 支持多种常见日期格式，提高解析成功率
        private static final SimpleDateFormat[] FORMATS = {
                new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US),
                new SimpleDateFormat("yyyy-MM-dd", Locale.US),
                new SimpleDateFormat("MM/dd/yyyy HH:mm:ss", Locale.US),
                new SimpleDateFormat("MM/dd/yyyy", Locale.US),
                new SimpleDateFormat("dd-MMM-yyyy", Locale.US),
                new SimpleDateFormat("yyyyMMddHHmmss", Locale.US)
        };
    }

    /**
     * 将任意对象转换为Date，功能与C#的ToDateTime扩展方法完全一致
     *
     * @param obj 待转换的对象
     * @return 转换后的Date，失败则返回最小日期值(1970-01-01 00:00:00)
     */
    public static Date toDateTime(Object obj) {
        // 处理空值情况
        String strValue = (obj == null) ? "" : obj.toString().trim();
        if (strValue.isEmpty()) {
            return new Date(0); // 对应C#的DateTime.MinValue，使用Unix纪元起始点
        }

        try {
            // 如果对象本身就是Date类型，直接返回
            if (obj instanceof Date) {
                return (Date) obj;
            }

            // 尝试解析字符串为日期，支持多种格式
            for (SimpleDateFormat format : DateFormatHolder.FORMATS) {
                try {
                    return format.parse(strValue);
                } catch (ParseException e) {
                    // 尝试下一种格式
                    continue;
                }
            }

            // 所有格式都无法解析时返回最小日期
            return new Date(0);
        } catch (Exception e) {
            // 任何异常都返回最小日期
            return new Date(0);
        }
    }

    private static String getTrimmedString(Object obj) {
        return obj == null ? "" : obj.toString().trim();
    }


    // 核心 Trim 方法
    public static String Trim(String str, char... trimChars) {
        if (str == null || str.isEmpty()) {
            return str;
        }

        if (trimChars == null || trimChars.length == 0) {
            return TrimHelper(str, 2); // 无参数时修剪空白字符
        }

        return TrimHelper(str, trimChars, 2); // 有参数时修剪指定字符
    }

    public static String TrimStart(String str, char... trimChars) {
        if (trimChars == null || trimChars.length == 0) {
            return TrimHelper(str, 0);
        }

        return TrimHelper(str, trimChars, 0);
    }

    public static String TrimEnd(String str, char... trimChars) {
        if (trimChars == null || trimChars.length == 0) {
            return TrimHelper(str, 1);
        }

        return TrimHelper(str, trimChars, 1);
    }

    // 修剪空白字符的辅助方法
    private static String TrimHelper(String str, int trimType) {
        int length = str.length();
        int start = 0;
        int end = length - 1;

        // 处理头部修剪
        if (trimType != 1) {
            for (start = 0; start < length; start++) {
                char c = str.charAt(start);
                if (!isWhiteSpace(c) && !isBOMWhitespace(c)) {
                    break;
                }
            }
        }

        // 处理尾部修剪（注意：C# 代码中此处错误地使用了 this[i]，应为 this[num]）
        if (trimType != 0) {
            for (end = length - 1; end >= start; end--) {
                char c = str.charAt(end);
                if (!isWhiteSpace(c) && !isBOMWhitespace(str.charAt(end))) { // 修正为 str.charAt(end)
                    break;
                }
            }
        }

        return createTrimmedString(str, start, end);
    }

    // 修剪指定字符的辅助方法
    private static String TrimHelper(String str, char[] trimChars, int trimType) {
        int length = str.length();
        int start = 0;
        int end = length - 1;

        // 处理头部修剪
        if (trimType != 1) {
            for (start = 0; start < length; start++) {
                char c = str.charAt(start);
                if (!contains(trimChars, c)) {
                    break;
                }
            }
        }

        // 处理尾部修剪
        if (trimType != 0) {
            for (end = length - 1; end >= start; end--) {
                char c = str.charAt(end);
                if (!contains(trimChars, c)) {
                    break;
                }
            }
        }

        return createTrimmedString(str, start, end);
    }

    // 创建修剪后的字符串
    private static String createTrimmedString(String str, int start, int end) {
        int length = end - start + 1;
        if (length == str.length()) {
            return str; // 无需修剪
        }
        if (length <= 0) {
            return ""; // 全修剪
        }
        return internalSubString(str, start, length);
    }

    // 内部子串截取（模拟 C# 的指针内存复制）
    private static String internalSubString(String str, int startIndex, int length) {
        return str.substring(startIndex, startIndex + length);
    }

    // 判断字符是否为空白（完全复刻 C# 逻辑）
    private static boolean isWhiteSpace(char c) {
        if (isLatin1(c)) {
            return isWhiteSpaceLatin1(c);
        }
        return Character.isWhitespace(c);
    }

    // 判断是否为 Latin-1 字符
    private static boolean isLatin1(char c) {
        return c <= 0xFF;
    }

    // 判断 Latin-1 字符是否为空白（完全复刻 C# 逻辑）
    private static boolean isWhiteSpaceLatin1(char c) {
        switch (c) {
            case ' ':
            case '\t':
            case '\n':
            case '\u000B':
            case '\f':
            case '\r':
            case '\u0085': // 下一行字符 (NEL)
            case '\u00A0': // 非中断空格
                return true;
            default:
                return false;
        }
    }

    // 判断字符是否为 BOM 空白（完全复刻 C# 逻辑）
    private static boolean isBOMWhitespace(char c) {
        return false; // C# 中直接返回 false
    }

    // 判断字符是否在数组中
    private static boolean contains(char[] array, char c) {
        for (char ch : array) {
            if (ch == c) {
                return true;
            }
        }
        return false;
    }

    /**
     * 从 Map 中获取指定键的值并转换为字符串，支持默认值
     *
     * @param map          源 Map
     * @param key          键名
     * @param defaultValue 默认值
     * @return 转换后的字符串值，如果键不存在或值为 null 则返回默认值
     */
    public static String getStringValue(Map<String, Object> map, String key, String defaultValue) {
        if (map == null || key == null) {
            return defaultValue;
        }

        Object value = map.get(key);
        if (value == null) {
            return defaultValue;
        }

        return value.toString();
    }

    /**
     * 从 Map 中获取指定键的值并转换为字符串，默认值为 null
     *
     * @param map 源 Map
     * @param key 键名
     * @return 转换后的字符串值，如果键不存在或值为 null 则返回 null
     */
    public static String getStringValue(Map<String, Object> map, String key) {
        return getStringValue(map, key, null);
    }

    /**
     * 从 Map 中获取指定键的值并转换为整数，支持默认值
     *
     * @param map          源 Map
     * @param key          键名
     * @param defaultValue 默认值
     * @return 转换后的整数值，如果键不存在、值为 null 或无法转换为整数则返回默认值
     */
    public static int getIntValue(Map<String, Object> map, String key, int defaultValue) {
        if (map == null || key == null) {
            return defaultValue;
        }

        Object value = map.get(key);
        if (value == null) {
            return defaultValue;
        }

        try {
            if (value instanceof Number) {
                return ((Number) value).intValue();
            } else {
                return Integer.parseInt(value.toString());
            }
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }

    /**
     * 将SQL Server的xtype转换为Java类型
     *
     * @param xtype SQL Server类型代码
     * @return 对应的Java类型
     */
    public static Type SqlxtypeToProType(int xtype) {
        switch (xtype) {
            // 字符串类型
            case 34:  // image
            case 35:  // text
            case 99:  // ntext
            case 167: // varchar
            case 173: // binary
            case 239: // nchar
            case 231: // nvarchar
            case 165: // varbinary
            case 175: // char
            case 36:  // uniqueidentifier
                return String.class;

            // 日期时间类型
            case 40:  // date
            case 41:  // time
            case 42:  // datetime2
            case 58:  // smalldatetime
            case 61:  // datetime
            case 189: // timestamp
            case 43:  // datetimeoffset
                return Date.class;

            // 整数类型
            case 48:  // tinyint
                return Byte.class;
            case 52:  // smallint
                return Short.class;
            case 56:  // int
                return Integer.class;
            case 127: // bigint
                return Long.class;

            // 浮点类型
            case 59:  // real
                return Float.class;
            case 62:  // float
                return Double.class;

            // 十进制类型
            case 106: // decimal
            case 108: // numeric
                return BigDecimal.class;

            // 货币类型
            case 122: // smallmoney
            case 60:  // money
                return Double.class;

            // 布尔类型
            case 104: // bit
                return Boolean.class;

            default:
                return Object.class;
        }
    }

    /**
     * 判断对象是否为null或空字符串
     */
    public static Boolean isNullOrEmpty(Object obj) {
        return obj == null || (obj instanceof String && ((String) obj).isEmpty());
    }

    // ------------------------------
    // 辅助方法：复刻 C# 的 TrimStart(字符) 逻辑
    // ------------------------------
    public static String trimStart(String str, char trimChar) {
        if (str == null || str.isEmpty()) {
            return str;
        }
        int startIndex = 0;
        // 从开头查找，直到找到非 trimChar 的字符
        while (startIndex < str.length() && str.charAt(startIndex) == trimChar) {
            startIndex++;
        }
        return str.substring(startIndex);
    }

    // ------------------------------
    // 辅助方法：复刻 C# 的 TrimEnd(字符) 逻辑
    // ------------------------------
    public static String trimEnd(String str, char trimChar) {
        if (str == null || str.isEmpty()) {
            return str;
        }
        int endIndex = str.length() - 1;
        // 从结尾查找，直到找到非 trimChar 的字符
        while (endIndex >= 0 && str.charAt(endIndex) == trimChar) {
            endIndex--;
        }
        return str.substring(0, endIndex + 1);
    }

    /**
     * 数组去重（对应C#的RemoveSameObj）
     *
     * @param arr 原始字符串数组
     * @return 去重后的列表（保留顺序）
     */
    public static List<String> removeSameObj(String[] arr) {
        if (arr == null || arr.length == 0) {
            return new ArrayList<>();
        }
        Set<String> set = new LinkedHashSet<>(); // 保留插入顺序的去重
        for (String s : arr) {
            if (s != null && !s.trim().isEmpty()) {
                set.add(s.trim());
            }
        }
        return new ArrayList<>(set);
    }

    /**
     * 列表拼接为字符串（对应C#的SJoin）
     *
     * @param list      字符串列表
     * @param separator 分隔符（如","）
     * @return 拼接后的字符串
     */
    public static String sJoin(List<String> list, String separator) {
        if (list == null || list.isEmpty()) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < list.size(); i++) {
            sb.append(list.get(i));
            if (i < list.size() - 1) {
                sb.append(separator);
            }
        }
        return sb.toString();
    }

    /**
     * 安全转换为int（对应C# int.TryParse）
     *
     * @param value        原始值（字符串/数字）
     * @param defaultValue 默认值
     * @return 转换后的int值
     */
    public static int parseIntSafely(Object value, int defaultValue) {
        if (value == null) {
            return defaultValue;
        }
        try {
            return Integer.parseInt(value.toString().trim());
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }

    /**
     * 安全获取数据表列值（对应C# layoutrow.Table.Columns.Contains + layoutrow["字段名"]）
     *
     * @param row        行数据（对应DataRow）
     * @param columnName 列名
     * @return 列值字符串（空值返回""）
     */
    public static String getTableColumnValue(Map<String, Object> row, String columnName) {
        if (row == null || !row.containsKey(columnName)) {
            return "";
        }
        return Objects.toString(row.get(columnName), "");
    }

    /**
     * 获取数据源列名列表（对应C# DataTable.Columns）
     *
     * @param dataSource 数据源
     * @return 列名列表
     */
    public static List<String> getColumnNames(List<Map<String, Object>> dataSource) {
        List<String> columnNames = new ArrayList<>();
        if (dataSource == null || dataSource.isEmpty()) {
            return columnNames;
        }
        // 取第一行的所有键作为列名（假设所有行列名一致）
        Map<String, Object> firstRow = dataSource.get(0);
        columnNames.addAll(firstRow.keySet());
        return columnNames;
    }

    /**
     * 字符串右侧补字符（对应C# String.PadRight）
     *
     * @param str     原字符串
     * @param length  目标长度
     * @param padChar 补全字符
     * @return 补全后的字符串
     */
    public static String padRight(String str, int length, char padChar) {
        if (str == null) {
            str = "";
        }
        if (str.length() >= length) {
            return str;
        }
        StringBuilder sb = new StringBuilder(str);
        while (sb.length() < length) {
            sb.append(padChar);
        }
        return sb.toString();
    }
}
