package com.chinaweal.aiccs.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.lang3.time.DateUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Time;
import java.sql.Timestamp;
import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 通用类型转换工具类
 * 基于Apache Commons Lang3，提供健壮的类型转换
 */
@Slf4j
public class TypeConversionUtils {

    // 支持的日期格式
    private static final String[] DATE_FORMATS = {
        "yyyy-MM-dd HH:mm:ss.S",
        "yyyy-MM-dd HH:mm:ss",
        "yyyy-MM-dd HH:mm",
        "yyyy-MM-dd",
        "yyyy/MM/dd HH:mm:ss",
        "yyyy/MM/dd HH:mm",
        "yyyy/MM/dd",
        "yyyy.MM.dd HH:mm:ss",
        "yyyy.MM.dd",
        "yyyy年MM月dd日",
        "yyyyMMdd",
        "yyyyMMddHHmmss"
    };

    // 时间格式
    private static final String[] TIME_FORMATS = {
        "HH:mm:ss",
        "HH:mm",
        "HHmmss"
    };

    // 默认值映射
    private static final Map<Class<?>, Object> DEFAULT_VALUES = new HashMap<>();

    static {
        // 初始化默认值
        DEFAULT_VALUES.put(Integer.class, null);
        DEFAULT_VALUES.put(int.class, 0);
        DEFAULT_VALUES.put(Long.class, null);
        DEFAULT_VALUES.put(long.class, 0L);
        DEFAULT_VALUES.put(Double.class, null);
        DEFAULT_VALUES.put(double.class, 0.0);
        DEFAULT_VALUES.put(Float.class, null);
        DEFAULT_VALUES.put(float.class, 0.0f);
        DEFAULT_VALUES.put(Short.class, null);
        DEFAULT_VALUES.put(short.class, (short)0);
        DEFAULT_VALUES.put(Byte.class, null);
        DEFAULT_VALUES.put(byte.class, (byte)0);
        DEFAULT_VALUES.put(Boolean.class, null);
        DEFAULT_VALUES.put(boolean.class, false);
        DEFAULT_VALUES.put(Character.class, null);
        DEFAULT_VALUES.put(char.class, '\u0000');
        DEFAULT_VALUES.put(BigDecimal.class, null);
        DEFAULT_VALUES.put(BigInteger.class, null);
        DEFAULT_VALUES.put(Date.class, null);
        DEFAULT_VALUES.put(java.sql.Date.class, null);
        DEFAULT_VALUES.put(Timestamp.class, null);
        DEFAULT_VALUES.put(Time.class, null);
        DEFAULT_VALUES.put(String.class, "");
    }

    /**
     * 安全类型转换
     * @param value 源值
     * @param targetType 目标类型
     * @param <T> 泛型类型
     * @return 转换后的值，失败时返回默认值
     */
    @SuppressWarnings("unchecked")
    public static <T> T convertValue(Object value, Class<T> targetType) {
        if (value == null) {
            return (T) getDefaultValue(targetType);
        }

        // 如果类型匹配，直接返回
        if (targetType.isInstance(value)) {
            return (T) value;
        }

        // 转换为字符串作为中间格式
        String strValue = value.toString().trim();

        try {
            if (StringUtils.isEmpty(strValue) && !targetType.equals(String.class)) {
                return (T) getDefaultValue(targetType);
            }

            if (targetType.equals(String.class)) {
                return (T) strValue;
            }

            // 数字类型处理
            if (ClassUtils.isAssignable(targetType, Number.class) || targetType.isPrimitive()) {
                return convertToNumber(strValue, targetType);
            }

            // 布尔类型处理
            if (ClassUtils.isAssignable(targetType, Boolean.class) || targetType.equals(boolean.class)) {
                return convertToBoolean(strValue, targetType);
            }

            // 字符类型处理
            if (ClassUtils.isAssignable(targetType, Character.class) || targetType.equals(char.class)) {
                return convertToCharacter(strValue, targetType);
            }

            // 日期类型处理
            if (ClassUtils.isAssignable(targetType, Date.class)) {
                return convertToDate(strValue, targetType);
            }

            // 其他情况尝试直接转换
            return (T) targetType.cast(value);

        } catch (Exception e) {
            log.debug("类型转换失败: {} -> {}, 值: '{}', 原因: {}",
                    value.getClass().getSimpleName(),
                    targetType.getSimpleName(),
                    strValue,
                    e.getMessage());
            return (T) getDefaultValue(targetType);
        }
    }

    /**
     * 获取类型的默认值
     */
    private static Object getDefaultValue(Class<?> targetType) {
        return DEFAULT_VALUES.getOrDefault(targetType, null);
    }

    /**
     * 转换为数字类型
     */
    @SuppressWarnings("unchecked")
    private static <T> T convertToNumber(String strValue, Class<T> targetType) {
        if (StringUtils.isEmpty(strValue)) {
            return (T) getDefaultValue(targetType);
        }

        try {
            if (ClassUtils.isAssignable(targetType, Integer.class) || targetType.equals(int.class)) {
                return (T) Integer.valueOf(strValue);
            }
            if (ClassUtils.isAssignable(targetType, Long.class) || targetType.equals(long.class)) {
                return (T) Long.valueOf(strValue);
            }
            if (ClassUtils.isAssignable(targetType, Double.class) || targetType.equals(double.class)) {
                return (T) Double.valueOf(strValue);
            }
            if (ClassUtils.isAssignable(targetType, Float.class) || targetType.equals(float.class)) {
                return (T) Float.valueOf(strValue);
            }
            if (ClassUtils.isAssignable(targetType, Short.class) || targetType.equals(short.class)) {
                return (T) Short.valueOf(strValue);
            }
            if (ClassUtils.isAssignable(targetType, Byte.class) || targetType.equals(byte.class)) {
                return (T) Byte.valueOf(strValue);
            }
            if (ClassUtils.isAssignable(targetType, BigDecimal.class)) {
                return (T) new BigDecimal(strValue);
            }
            if (ClassUtils.isAssignable(targetType, BigInteger.class)) {
                return (T) new BigInteger(strValue);
            }
        } catch (NumberFormatException e) {
            log.warn("数字转换失败: '{}' -> {}", strValue, targetType.getSimpleName());
        }

        return (T) getDefaultValue(targetType);
    }

    /**
     * 转换为布尔类型
     */
    @SuppressWarnings("unchecked")
    private static <T> T convertToBoolean(String strValue, Class<T> targetType) {
        if (StringUtils.isEmpty(strValue)) {
            return (T) getDefaultValue(targetType);
        }

        // 支持多种布尔值表示
        String normalized = strValue.toLowerCase();
        if (NumberUtils.isParsable(normalized)) {
            int num = Integer.parseInt(normalized);
            return (T) Boolean.valueOf(num != 0);
        }

        return (T) Boolean.valueOf(
            "true".equals(normalized) ||
            "yes".equals(normalized) ||
            "y".equals(normalized) ||
            "1".equals(normalized)
        );
    }

    /**
     * 转换为字符类型
     */
    @SuppressWarnings("unchecked")
    private static <T> T convertToCharacter(String strValue, Class<T> targetType) {
        if (StringUtils.isEmpty(strValue)) {
            return (T) getDefaultValue(targetType);
        }

        if (strValue.length() == 1) {
            return (T) Character.valueOf(strValue.charAt(0));
        }

        log.warn("无法将 '{}' 转换为Character，长度不为1", strValue);
        return (T) getDefaultValue(targetType);
    }

    /**
     * 转换为日期类型
     */
    @SuppressWarnings("unchecked")
    private static <T> T convertToDate(String strValue, Class<T> targetType) {
        if (StringUtils.isEmpty(strValue)) {
            return (T) getDefaultValue(targetType);
        }

        try {
            Date date;

            if (ClassUtils.isAssignable(targetType, java.sql.Date.class)) {
                if (NumberUtils.isParsable(strValue)) {
                    // 时间戳格式
                    long timestamp = Long.parseLong(strValue);
                    date = new Date(timestamp);
                } else {
                    date = DateUtils.parseDateStrictly(strValue, DATE_FORMATS);
                }
                return (T) new java.sql.Date(date.getTime());
            }

            if (ClassUtils.isAssignable(targetType, Timestamp.class)) {
                if (NumberUtils.isParsable(strValue)) {
                    long timestamp = Long.parseLong(strValue);
                    return (T) new Timestamp(timestamp);
                } else {
                    date = DateUtils.parseDateStrictly(strValue, DATE_FORMATS);
                    return (T) new Timestamp(date.getTime());
                }
            }

            if (ClassUtils.isAssignable(targetType, Time.class)) {
                if (NumberUtils.isParsable(strValue)) {
                    long timestamp = Long.parseLong(strValue);
                    return (T) new Time(timestamp);
                } else {
                    // 尝试解析时间格式
                    try {
                        date = DateUtils.parseDateStrictly(strValue, TIME_FORMATS);
                        return (T) new Time(date.getTime());
                    } catch (ParseException e) {
                        // 如果不是时间格式，尝试标准时间解析
                        date = DateUtils.parseDateStrictly(strValue, DATE_FORMATS);
                        return (T) new Time(date.getTime());
                    }
                }
            }

            // 默认返回 java.util.Date
            date = DateUtils.parseDateStrictly(strValue, DATE_FORMATS);
            return (T) date;

        } catch (ParseException e) {
            log.warn("日期解析失败: '{}', 支持的格式: {}", strValue, DATE_FORMATS);
        } catch (NumberFormatException e) {
            log.warn("时间戳转换失败: '{}'", strValue);
        }

        return (T) getDefaultValue(targetType);
    }

    /**
     * 批量转换Map中的所有值
     */
    public static Map<String, Object> convertMapValues(Map<String, Object> sourceMap,
                                                      Map<String, Class<?>> fieldTypes) {
        Map<String, Object> result = new HashMap<>();

        for (Map.Entry<String, Object> entry : sourceMap.entrySet()) {
            String fieldName = entry.getKey();
            Object value = entry.getValue();

            Class<?> targetType = fieldTypes.get(fieldName);
            if (targetType != null) {
                Object convertedValue = convertValue(value, targetType);
                result.put(fieldName, convertedValue);
            } else {
                result.put(fieldName, value); // 未知类型保持原值
            }
        }

        return result;
    }

    /**
     * 检查是否为空值
     */
    public static boolean isEmpty(Object value) {
        if (value == null) {
            return true;
        }
        if (value instanceof String) {
            return StringUtils.isEmpty((String) value);
        }
        if (value instanceof Number) {
            return ((Number) value).doubleValue() == 0;
        }
        if (value instanceof Boolean) {
            return !((Boolean) value);
        }
        return false;
    }
}