package com.ruoyi.common.utils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class MapUtils {
    // 定义静态Map
    private static final Map<Class<?>, Class<?>> PRIMITIVE_WRAPPER_MAP;
    private static final Map<Class<?>, Class<?>> WRAPPER_PRIMITIVE_MAP;

    static {
        // 初始化 primitiveWrapperMap
        Map<Class<?>, Class<?>> primitiveWrapperMap = new HashMap<>();
        primitiveWrapperMap.put(boolean.class, Boolean.class);
        primitiveWrapperMap.put(byte.class, Byte.class);
        primitiveWrapperMap.put(char.class, Character.class);
        primitiveWrapperMap.put(short.class, Short.class);
        primitiveWrapperMap.put(int.class, Integer.class);
        primitiveWrapperMap.put(long.class, Long.class);
        primitiveWrapperMap.put(float.class, Float.class);
        primitiveWrapperMap.put(double.class, Double.class);
        PRIMITIVE_WRAPPER_MAP = Collections.unmodifiableMap(primitiveWrapperMap);

        // 初始化 wrapperPrimitiveMap
        Map<Class<?>, Class<?>> wrapperPrimitiveMap = new HashMap<>();
        wrapperPrimitiveMap.put(Boolean.class, boolean.class);
        wrapperPrimitiveMap.put(Byte.class, byte.class);
        wrapperPrimitiveMap.put(Character.class, char.class);
        wrapperPrimitiveMap.put(Short.class, short.class);
        wrapperPrimitiveMap.put(Integer.class, int.class);
        wrapperPrimitiveMap.put(Long.class, long.class);
        wrapperPrimitiveMap.put(Float.class, float.class);
        wrapperPrimitiveMap.put(Double.class, double.class);
        WRAPPER_PRIMITIVE_MAP = Collections.unmodifiableMap(wrapperPrimitiveMap);
    }
    /**
     * 安全获取值，支持所有基础类型之间的互相转换
     */
    @SuppressWarnings("unchecked")
    public static <T> T getValue(Map<String, Object> map, String key, Class<T> targetType) {
        return getValue(map, key, targetType, null);
    }

    /**
     * 安全获取值，支持所有基础类型之间的互相转换，带默认值
     */
    @SuppressWarnings("unchecked")
    public static <T> T getValue(Map<String, Object> map, String key,
                                 Class<T> targetType, T defaultValue) {
        // 基础检查
        if (map == null || key == null || targetType == null) {
            return defaultValue;
        }

        if (!map.containsKey(key)) {
            return defaultValue;
        }

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

        // 如果已经是目标类型，直接返回
        if (isAssignableFrom(value.getClass(), targetType)) {
            return (T) value;
        }

        try {
            // 转换为目标类型
            return convertValue(value, targetType);
        } catch (Exception e) {
            return defaultValue;
        }
    }

    /**
     * 检查类型是否兼容（支持包装类型和基本类型）
     */
    private static boolean isAssignableFrom(Class<?> from, Class<?> to) {
        // 如果是同一个类
        if (to.isAssignableFrom(from)) {
            return true;
        }

        // 检查基本类型和包装类型的兼容性
        if (to.isPrimitive()) {
            Class<?> wrapperClass = PRIMITIVE_WRAPPER_MAP.get(to);
            return wrapperClass != null && wrapperClass.isAssignableFrom(from);
        } else if (from.isPrimitive()) {
            Class<?> primitiveClass = WRAPPER_PRIMITIVE_MAP.get(to);
            return primitiveClass != null && primitiveClass == from;
        }

        return false;
    }

    /**
     * 核心转换方法 - 支持所有基础类型互相转换
     */
    @SuppressWarnings("unchecked")
    public static <T> T convertValue(Object value, Class<T> targetType) {
        // 先转为字符串，作为中间转换桥梁
        String stringValue = value != null ? value.toString() : "";

        // 处理空字符串
        if (stringValue.trim().isEmpty()) {
            return getDefaultValue(targetType);
        }

        // 数值类型的特殊处理
        if (isNumericType(targetType)) {
            return convertNumericValue(value, stringValue, targetType);
        }

        // 布尔类型
        if (targetType == Boolean.class || targetType == boolean.class) {
            return (T) convertToBoolean(value, stringValue);
        }

        // 字符类型
        if (targetType == Character.class || targetType == char.class) {
            return (T) convertToCharacter(value, stringValue);
        }

        // 字符串类型
        if (targetType == String.class) {
            return (T) stringValue;
        }

        // 默认尝试直接转换（可能会失败）
        try {
            return (T) value;
        } catch (ClassCastException e) {
            throw new IllegalArgumentException("无法将类型 " + value.getClass() + " 转换为 " + targetType);
        }
    }

    /**
     * 数值类型转换
     */
    @SuppressWarnings("unchecked")
    private static <T> T convertNumericValue(Object value, String stringValue, Class<T> targetType) {
        // 使用BigDecimal作为中间类型进行高精度转换
        BigDecimal bigDecimal;

        try {
            if (value instanceof Number) {
                if (value instanceof BigDecimal) {
                    bigDecimal = (BigDecimal) value;
                } else if (value instanceof BigInteger) {
                    bigDecimal = new BigDecimal((BigInteger) value);
                } else {
                    bigDecimal = BigDecimal.valueOf(((Number) value).doubleValue());
                }
            } else {
                bigDecimal = new BigDecimal(stringValue.trim());
            }

            // 根据目标类型进行转换
            if (targetType == Integer.class || targetType == int.class) {
                return (T) Integer.valueOf(bigDecimal.intValue());
            }
            else if (targetType == Double.class || targetType == double.class) {
                return (T) Double.valueOf(bigDecimal.doubleValue());
            }
            else if (targetType == Long.class || targetType == long.class) {
                return (T) Long.valueOf(bigDecimal.longValue());
            }
            else if (targetType == Float.class || targetType == float.class) {
                return (T) Float.valueOf(bigDecimal.floatValue());
            }
            else if (targetType == Short.class || targetType == short.class) {
                return (T) Short.valueOf(bigDecimal.shortValue());
            }
            else if (targetType == Byte.class || targetType == byte.class) {
                return (T) Byte.valueOf(bigDecimal.byteValue());
            }
            else if (targetType == BigDecimal.class) {
                return (T) bigDecimal;
            }
            else if (targetType == BigInteger.class) {
                return (T) bigDecimal.toBigInteger();
            }

        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("无法将值 '" + stringValue + "' 转换为数值类型: " + targetType);
        }

        throw new IllegalArgumentException("不支持的目标数值类型: " + targetType);
    }

    /**
     * 转换为布尔值
     */
    private static Boolean convertToBoolean(Object value, String stringValue) {
        if (value instanceof Boolean) {
            return (Boolean) value;
        }

        String lowerValue = stringValue.trim().toLowerCase();

        // 处理常见布尔值表示
        if ("true".equals(lowerValue) || "1".equals(lowerValue) || "yes".equals(lowerValue)
                || "on".equals(lowerValue) || "y".equals(lowerValue)) {
            return true;
        }

        if ("false".equals(lowerValue) || "0".equals(lowerValue) || "no".equals(lowerValue)
                || "off".equals(lowerValue) || "n".equals(lowerValue)) {
            return false;
        }

        // 如果是数值类型
        if (value instanceof Number) {
            return ((Number) value).doubleValue() != 0;
        }

        // 尝试解析为数字
        try {
            double numValue = Double.parseDouble(stringValue);
            return numValue != 0;
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("无法将值 '" + stringValue + "' 转换为布尔值");
        }
    }

    /**
     * 转换为字符
     */
    private static Character convertToCharacter(Object value, String stringValue) {
        if (value instanceof Character) {
            return (Character) value;
        }

        if (stringValue.length() == 1) {
            return stringValue.charAt(0);
        }

        // 如果是数值，转换为对应ASCII字符
        if (value instanceof Number) {
            int intValue = ((Number) value).intValue();
            if (intValue >= 0 && intValue <= 65535) {
                return (char) intValue;
            }
        }

        // 尝试解析为数字
        try {
            int intValue = Integer.parseInt(stringValue.trim());
            if (intValue >= 0 && intValue <= 65535) {
                return (char) intValue;
            }
        } catch (NumberFormatException e) {
            // 忽略，继续其他尝试
        }

        throw new IllegalArgumentException("无法将值 '" + stringValue + "' 转换为字符");
    }

    /**
     * 判断是否为数值类型
     */
    private static boolean isNumericType(Class<?> type) {
        return type == Integer.class || type == int.class ||
                type == Double.class || type == double.class ||
                type == Long.class || type == long.class ||
                type == Float.class || type == float.class ||
                type == Short.class || type == short.class ||
                type == Byte.class || type == byte.class ||
                type == BigDecimal.class || type == BigInteger.class;
    }

    /**
     * 获取类型的默认值
     */
    @SuppressWarnings("unchecked")
    private static <T> T getDefaultValue(Class<T> type) {
        if (type == boolean.class) return (T) Boolean.FALSE;
        if (type == byte.class) return (T) Byte.valueOf((byte) 0);
        if (type == char.class) return (T) Character.valueOf('\0');
        if (type == short.class) return (T) Short.valueOf((short) 0);
        if (type == int.class) return (T) Integer.valueOf(0);
        if (type == long.class) return (T) Long.valueOf(0L);
        if (type == float.class) return (T) Float.valueOf(0.0f);
        if (type == double.class) return (T) Double.valueOf(0.0);

        // 包装类型返回null
        return null;
    }

    /**
     * 便捷方法：获取Integer
     */
    public static Integer getInteger(Map<String, Object> map, String key) {
        return getValue(map, key, Integer.class, 0);
    }

    /**
     * 便捷方法：获取Double
     */
    public static Double getDouble(Map<String, Object> map, String key) {
        return getValue(map, key, Double.class, 0.0);
    }

    /**
     * 便捷方法：获取Long
     */
    public static Long getLong(Map<String, Object> map, String key) {
        return getValue(map, key, Long.class, 0L);
    }

    /**
     * 便捷方法：获取Float
     */
    public static Float getFloat(Map<String, Object> map, String key) {
        return getValue(map, key, Float.class, 0.0f);
    }

    /**
     * 便捷方法：获取Boolean
     */
    public static Boolean getBoolean(Map<String, Object> map, String key) {
        return getValue(map, key, Boolean.class, false);
    }

    /**
     * 便捷方法：获取String
     */
    public static String getString(Map<String, Object> map, String key) {
        return getValue(map, key, String.class, "");
    }
}