package com.backendsys.utils;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import org.springframework.cglib.beans.BeanMap;

import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.*;

@SuppressWarnings({"rawtypes", "unchecked"})
public class MapUtil {

    /**
     * 将 UTC 时间字符串转换为 Asia/Shanghai 时区的时间字符串
     * MapUtil.convertUtcToAsiaShanghai(item.get("create_time_utc"))
     */
    public static String convertUtcToAsiaShanghai(Object utcTime) {
        String utcTimeStr = Convert.toStr(utcTime);
        // 解析 UTC 时间字符串为 LocalDateTime
        LocalDateTime utcDateTime = cn.hutool.core.date.DateUtil.parse(utcTimeStr).toLocalDateTime();
        // 转换为 Asia/Shanghai 时区的时间
        ZonedDateTime asiaShanghaiDateTime = utcDateTime.atZone(ZoneId.of("UTC")).withZoneSameInstant(ZoneId.of("Asia/Shanghai"));
        // 格式化转换后的时间为字符串
        String asiaShanghaiTimeStr = DateUtil.format(asiaShanghaiDateTime.toLocalDateTime(), "yyyy-MM-dd HH:mm:ss");
        // 将转换后的时间放入 item 中
        return asiaShanghaiTimeStr;
    }

    /**
     * 获取多层 Map 中指定路径的值。
     * MapUtil.get(response, "Header.Code")
     */
    public static Object get(Map<String, Object> map, String keyPath) {
        String[] keys = keyPath.split("\\.");
        Map<String, Object> currentMap = map;
        for (String key : keys) {
            Object obj = currentMap.get(key);
            if (obj instanceof Map) {
                currentMap = (Map<String, Object>) obj;
            } else {
                return obj;
            }
        }
        return null;
    }

    /**
     * 将大驼峰命名转换为下划线命名 (单个Key值)
     */
    public static String convertKeyToUnderscoreCase(String input) {
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < input.length(); i++) {
            char currentChar = input.charAt(i);
            if (Character.isUpperCase(currentChar) && i > 0) {
                result.append("_").append(Character.toLowerCase(currentChar));
            } else {
                result.append(Character.toLowerCase(currentChar));
            }
        }
        return result.toString();
    }
    /**
     * 将大驼峰命名转换为下划线命名 (单条记录)
     */
    public static Map<String, Object> convertToUnderscoreCase(Map<String, Object> map) {
        Map<String, Object> newMap = new HashMap<>();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            // 检查值是否为Map，如果是，则递归调用convertToUnderscoreCase
            if (entry.getValue() instanceof Map) {
                Map<String, Object> value = (Map<String, Object>) entry.getValue();
                String newKey = convertKeyToUnderscoreCase(entry.getKey());
                newMap.put(newKey, convertToUnderscoreCase(value));
            } else {
                // 如果不是Map，则直接复制键值对
                newMap.put(convertKeyToUnderscoreCase(entry.getKey()), entry.getValue());
            }
        }
        return newMap;
    }



    /**
     * 将 实体类字段命名 转换为 首字母小写的 小驼峰命名
     */
    public static JSONObject convertEntityToJson(Object entity) throws IllegalAccessException {
        JSONObject json = new JSONObject();
        Class<?> clazz = entity.getClass();
        // 遍历实体类的所有字段
        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true); // 确保可以访问私有字段
            // 获取字段名，并转换为小驼峰命名法
            String fieldName = convertToCamelCase(field.getName());
            Object fieldValue = field.get(entity);
            if (fieldValue != null) {
                if (List.class.isAssignableFrom(field.getType())) {
                    // 字段是List类型
                    List<?> list = (List<?>) fieldValue;
                    JSONArray jsonArray = new JSONArray();
                    for (Object item : list) {
                        if (item instanceof Object) {
                            // 如果列表项是实体类对象，则递归转换
                            jsonArray.put(convertEntityToJson(item));
                        } else {
                            // 否则直接添加到数组中
                            jsonArray.put(item);
                        }
                    }
                    json.set(fieldName, jsonArray);
//                    json.put(fieldName, jsonArray);
                } else if (Map.class.isAssignableFrom(field.getType())) {
                    // 字段是Map类型
                    Map<?, ?> map = (Map<?, ?>) fieldValue;
                    JSONObject jsonMap = new JSONObject();
                    for (Map.Entry<?, ?> entry : map.entrySet()) {
                        Object key = entry.getKey();
                        Object value = entry.getValue();
                        if (value instanceof Object) {
                            // 如果Map的值是实体类对象，则递归转换
                            jsonMap.set(key.toString(), convertEntityToJson(value));
//                            jsonMap.put(key.toString(), convertEntityToJson(value));
                        } else {
                            // 否则直接添加到Map中
                            jsonMap.set(key.toString(), value);
//                            jsonMap.put(key.toString(), value);
                        }
                    }
                    json.set(fieldName, jsonMap);
//                    json.put(fieldName, jsonMap);
                } else if (
                        String.class.isAssignableFrom(field.getType()) ||
                                Integer.class.isAssignableFrom(field.getType()) ||
                                Double.class.isAssignableFrom(field.getType()) ||
                                Float.class.isAssignableFrom(field.getType()) ||
                                Long.class.isAssignableFrom(field.getType()) ||
                                Short.class.isAssignableFrom(field.getType()) ||
                                Byte.class.isAssignableFrom(field.getType()) ||
                                Boolean.class.isAssignableFrom(field.getType()) ||
                                Character.class.isAssignableFrom(field.getType()) ||
                                field.getType().isArray()
                ) {
                    // 判断不了实体类，只能判断上面的通用类型，适合类型的直接输出
                    json.set(fieldName, fieldValue);
//                    json.put(fieldName, fieldValue);
                } else {
                    // 无法识别实体类类型 else if (field.getType().isAssignableFrom(Entity.class)
                    // 字段是实体类的实例，递归转换
                    json.set(fieldName, convertEntityToJson(fieldValue));
//                    json.put(fieldName, convertEntityToJson(fieldValue));
                }
            }
        }
        return json;
    }
    // 将下划线命名法转换为小驼峰命名法
    public static String convertToCamelCase(String name) {
        if (name == null || name.isEmpty()) {
            return name;
        }
        StringBuilder result = new StringBuilder();
        boolean nextUpper = false;
        for (int i = 0; i < name.length(); i++) {
            char c = name.charAt(i);
            if (c == '_') {
                nextUpper = true;
            } else {
                if (nextUpper) {
                    result.append(Character.toUpperCase(c));
                    nextUpper = false;
                } else {
                    result.append(Character.toLowerCase(c));
                }
            }
        }
        return result.toString();
    }



    /**
     * 将对象装换为map
     * @param bean
     * @return
     */
    public static <T> Map<String, Object> beanToMap(T bean) {
        Map<String, Object> map = new HashMap();
        if (bean != null) {
            BeanMap beanMap = BeanMap.create(bean);
            for (Object key : beanMap.keySet()) {
                map.put(key + "", beanMap.get(key));
            }
        }
        return map;
    }

    /**
     * 合并两个map数据(建议使用)
     * @param mergedMap
     * @param newMap
     * @return
     * @author zero 2019/04/17
     */
    public static Map<String, String> mergeMap(Map<String, String> mergedMap, Map<String, String> newMap) {
        if (mergedMap.isEmpty() || mergedMap == null)
            return newMap;
        if (newMap.isEmpty() || newMap == null)
            return newMap;
        for (String key : newMap.keySet()) {
            if (mergedMap.containsKey(key)) {
                mergedMap.put(key, mergedMap.get(key) + newMap.get(key));
            } else {
                mergedMap.put(key, newMap.get(key));
            }
        }
        return mergedMap;
    }

}
