package com.ycwl.basic.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.databind.type.TypeFactory;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

/**
 * Jackson JSON工具类
 * 提供简单易用的JSON序列化和反序列化功能
 */
public class JacksonUtil {
    
    private static final ObjectMapper objectMapper = new ObjectMapper();
    static {
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        objectMapper.setTimeZone(TimeZone.getTimeZone(ZoneId.of("Asia/Shanghai")));
        objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
        objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);
        objectMapper.configure(SerializationFeature.WRITE_SELF_REFERENCES_AS_NULL, true);
        objectMapper.configure(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY, false);
    }
    
    /**
     * 对象转JSON字符串
     * @param obj 要转换的对象
     * @return JSON字符串
     */
    public static String toJson(Object obj) {
        try {
            return objectMapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("对象转JSON失败", e);
        }
    }
    
    /**
     * JSON字符串转对象
     * @param json JSON字符串
     * @param clazz 目标类型
     * @param <T> 泛型类型
     * @return 转换后的对象
     */
    public static <T> T fromJson(String json, Class<T> clazz) {
        try {
            return objectMapper.readValue(json, clazz);
        } catch (IOException e) {
            throw new RuntimeException("JSON转对象失败", e);
        }
    }
    
    /**
     * JSON字符串转对象（支持复杂类型）
     * @param json JSON字符串
     * @param typeReference 类型引用
     * @param <T> 泛型类型
     * @return 转换后的对象
     */
    public static <T> T fromJson(String json, TypeReference<T> typeReference) {
        try {
            return objectMapper.readValue(json, typeReference);
        } catch (IOException e) {
            throw new RuntimeException("JSON转对象失败", e);
        }
    }
    
    /**
     * JSON字符串转List
     * @param json JSON字符串
     * @param elementClass 列表元素类型
     * @param <T> 泛型类型
     * @return List对象
     */
    public static <T> List<T> fromJsonToList(String json, Class<T> elementClass) {
        try {
            TypeFactory typeFactory = objectMapper.getTypeFactory();
            CollectionType listType = typeFactory.constructCollectionType(List.class, elementClass);
            return objectMapper.readValue(json, listType);
        } catch (IOException e) {
            throw new RuntimeException("JSON转List失败", e);
        }
    }
    
    /**
     * JSON字符串转Map
     * @param json JSON字符串
     * @return Map对象
     */
    public static Map<String, Object> fromJsonToMap(String json) {
        try {
            return objectMapper.readValue(json, new TypeReference<Map<String, Object>>() {});
        } catch (IOException e) {
            throw new RuntimeException("JSON转Map失败", e);
        }
    }
    
    /**
     * 获取JSON节点
     * @param json JSON字符串
     * @return JsonNode对象
     */
    public static JsonNode getJsonNode(String json) {
        try {
            return objectMapper.readTree(json);
        } catch (IOException e) {
            throw new RuntimeException("解析JSON失败", e);
        }
    }
    
    /**
     * 从JSON中获取字符串值
     * @param json JSON字符串
     * @param path 路径（支持嵌套，如："user.name"）
     * @return 字符串值
     */
    public static String getString(String json, String path) {
        JsonNode node = getValueByPath(json, path);
        return node != null && !node.isNull() ? node.asText() : null;
    }
    
    /**
     * 从JSON中获取整数值
     * @param json JSON字符串
     * @param path 路径
     * @return 整数值
     */
    public static Integer getInt(String json, String path) {
        JsonNode node = getValueByPath(json, path);
        return node != null && !node.isNull() ? node.asInt() : null;
    }
    
    /**
     * 从JSON中获取长整数值
     * @param json JSON字符串
     * @param path 路径
     * @return 长整数值
     */
    public static Long getLong(String json, String path) {
        JsonNode node = getValueByPath(json, path);
        return node != null && !node.isNull() ? node.asLong() : null;
    }
    
    /**
     * 从JSON中获取双精度浮点数值
     * @param json JSON字符串
     * @param path 路径
     * @return 双精度浮点数值
     */
    public static Double getDouble(String json, String path) {
        JsonNode node = getValueByPath(json, path);
        return node != null && !node.isNull() ? node.asDouble() : null;
    }
    
    /**
     * 从JSON中获取布尔值
     * @param json JSON字符串
     * @param path 路径
     * @return 布尔值
     */
    public static Boolean getBoolean(String json, String path) {
        JsonNode node = getValueByPath(json, path);
        return node != null && !node.isNull() ? node.asBoolean() : null;
    }
    
    /**
     * 从JSON中获取对象
     * @param json JSON字符串
     * @param path 路径
     * @param clazz 目标类型
     * @param <T> 泛型类型
     * @return 对象
     */
    public static <T> T getObject(String json, String path, Class<T> clazz) {
        JsonNode node = getValueByPath(json, path);
        if (node != null && !node.isNull()) {
            try {
                return objectMapper.treeToValue(node, clazz);
            } catch (JsonProcessingException e) {
                throw new RuntimeException("JSON节点转对象失败", e);
            }
        }
        return null;
    }
    
    /**
     * 从JSON中获取数组
     * @param json JSON字符串
     * @param path 路径
     * @param elementClass 数组元素类型
     * @param <T> 泛型类型
     * @return List对象
     */
    public static <T> List<T> getArray(String json, String path, Class<T> elementClass) {
        JsonNode node = getValueByPath(json, path);
        if (node != null && node.isArray()) {
            try {
                TypeFactory typeFactory = objectMapper.getTypeFactory();
                CollectionType listType = typeFactory.constructCollectionType(List.class, elementClass);
                return objectMapper.treeToValue(node, listType);
            } catch (JsonProcessingException e) {
                throw new RuntimeException("JSON节点转数组失败", e);
            }
        }
        return null;
    }
    
    /**
     * 检查JSON中是否存在指定路径
     * @param json JSON字符串
     * @param path 路径
     * @return 是否存在
     */
    public static boolean hasPath(String json, String path) {
        JsonNode node = getValueByPath(json, path);
        return node != null && !node.isMissingNode();
    }
    
    /**
     * 根据路径获取JSON节点值
     * @param json JSON字符串
     * @param path 路径（支持嵌套，如："user.name"或"users[0].name"）
     * @return JsonNode对象
     */
    private static JsonNode getValueByPath(String json, String path) {
        try {
            JsonNode rootNode = objectMapper.readTree(json);
            String[] pathParts = path.split("\\.");
            JsonNode currentNode = rootNode;
            
            for (String part : pathParts) {
                if (currentNode == null || currentNode.isMissingNode()) {
                    return null;
                }
                
                // 处理数组索引，如：users[0]
                if (part.contains("[") && part.contains("]")) {
                    String fieldName = part.substring(0, part.indexOf("["));
                    String indexStr = part.substring(part.indexOf("[") + 1, part.indexOf("]"));
                    int index = Integer.parseInt(indexStr);
                    
                    currentNode = currentNode.get(fieldName);
                    if (currentNode != null && currentNode.isArray() && index < currentNode.size()) {
                        currentNode = currentNode.get(index);
                    } else {
                        return null;
                    }
                } else {
                    currentNode = currentNode.get(part);
                }
            }
            
            return currentNode;
        } catch (Exception e) {
            throw new RuntimeException("获取JSON路径值失败", e);
        }
    }
    
    /**
     * 美化JSON字符串（格式化输出）
     * @param json JSON字符串
     * @return 格式化后的JSON字符串
     */
    public static String prettyPrint(String json) {
        try {
            JsonNode node = objectMapper.readTree(json);
            return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(node);
        } catch (IOException e) {
            throw new RuntimeException("JSON格式化失败", e);
        }
    }
    
    /**
     * 获取ObjectMapper实例（用于高级用法）
     * @return ObjectMapper实例
     */
    public static ObjectMapper getObjectMapper() {
        return objectMapper;
    }
    
    // ==== FastJSON 兼容性方法 ====
    
    /**
     * 兼容 FastJSON 的 JSON.toJSONString() 方法
     * @param obj 要转换的对象
     * @return JSON字符串
     */
    public static String toJSONString(Object obj) {
        return toJson(obj);
    }
    
    /**
     * 兼容 FastJSON 的 JSON.parseObject() 方法
     * @param json JSON字符串
     * @param clazz 目标类型
     * @param <T> 泛型类型
     * @return 转换后的对象
     */
    public static <T> T parseObject(String json, Class<T> clazz) {
        return fromJson(json, clazz);
    }
    
    /**
     * 兼容 FastJSON 的 JSON.parseArray() 方法
     * @param json JSON字符串
     * @param clazz 数组元素类型
     * @param <T> 泛型类型
     * @return List对象
     */
    public static <T> List<T> parseArray(String json, Class<T> clazz) {
        return fromJsonToList(json, clazz);
    }
    
    /**
     * 带TypeReference的parseObject方法，支持复杂泛型
     * @param json JSON字符串
     * @param typeReference 类型引用
     * @param <T> 泛型类型
     * @return 转换后的对象
     */
    public static <T> T parseObject(String json, TypeReference<T> typeReference) {
        return fromJson(json, typeReference);
    }
    
    /**
     * 将Map或其他对象转换为指定类型，兼容fastjson的toJavaObject方法
     * @param obj 源对象
     * @param clazz 目标类型
     * @param <T> 泛型类型
     * @return 转换后的对象
     */
    public static <T> T toJavaObject(Object obj, Class<T> clazz) {
        if (obj == null) {
            return null;
        }
        try {
            // 如果对象已经是目标类型，直接返回
            if (clazz.isInstance(obj)) {
                return clazz.cast(obj);
            }
            // 先转为JSON字符串，再转为目标对象
            String json = toJson(obj);
            return fromJson(json, clazz);
        } catch (Exception e) {
            throw new RuntimeException("对象转换失败", e);
        }
    }
    
    /**
     * 兼容 FastJSON 的 JSONObject.parseObject() 方法
     * @param json JSON字符串
     * @param clazz 目标类型
     * @param <T> 泛型类型
     * @return 转换后的对象
     */
    public static <T> T parseObjectCompat(String json, Class<T> clazz) {
        return fromJson(json, clazz);
    }
    
    /**
     * 兼容 FastJSON 的 JSONObject.toJSONString() 方法
     * @param obj 要转换的对象
     * @return JSON字符串
     */
    public static String toJSONStringCompat(Object obj) {
        return toJson(obj);
    }
    
    /**
     * 兼容 FastJSON 的 JSONObject.parseArray() 方法
     * @param json JSON字符串
     * @param clazz 数组元素类型
     * @param <T> 泛型类型
     * @return List对象
     */
    public static <T> List<T> parseArrayCompat(String json, Class<T> clazz) {
        return fromJsonToList(json, clazz);
    }
    
    /**
     * 简单的JSON对象包装类，兼容部分JSONObject的用法
     */
    public static class JSONObjectCompat {
        private final JsonNode node;
        
        private JSONObjectCompat(JsonNode node) {
            this.node = node;
        }
        
        /**
         * 解析JSON字符串为JSONObjectCompat
         * @param json JSON字符串
         * @return JSONObjectCompat对象
         */
        public static JSONObjectCompat parseObject(String json) {
            return new JSONObjectCompat(getJsonNode(json));
        }
        
        /**
         * 获取JSON数组
         * @param key 键名
         * @return JSON数组的List表示
         */
        public List<JSONObjectCompat> getJSONArray(String key) {
            JsonNode arrayNode = node.get(key);
            if (arrayNode != null && arrayNode.isArray()) {
                List<JSONObjectCompat> result = new java.util.ArrayList<>();
                for (JsonNode item : arrayNode) {
                    result.add(new JSONObjectCompat(item));
                }
                return result;
            }
            return null;
        }
        
        /**
         * 获取JSON对象
         * @param index 索引
         * @return JSONObjectCompat对象
         */
        public JSONObjectCompat getJSONObject(int index) {
            if (node.isArray() && index < node.size()) {
                return new JSONObjectCompat(node.get(index));
            }
            return null;
        }
        
        /**
         * 获取字符串值
         * @param key 键名
         * @return 字符串值
         */
        public String getString(String key) {
            JsonNode valueNode = node.get(key);
            return valueNode != null && !valueNode.isNull() ? valueNode.asText() : null;
        }
        
        /**
         * 获取整数值
         * @param key 键名
         * @return 整数值
         */
        public Integer getInteger(String key) {
            JsonNode valueNode = node.get(key);
            return valueNode != null && !valueNode.isNull() ? valueNode.asInt() : null;
        }
        
        /**
         * 获取长整数值
         * @param key 键名
         * @return 长整数值
         */
        public Long getLong(String key) {
            JsonNode valueNode = node.get(key);
            return valueNode != null && !valueNode.isNull() ? valueNode.asLong() : null;
        }
        
        /**
         * 获取双精度浮点数值
         * @param key 键名
         * @return 双精度浮点数值
         */
        public Double getDouble(String key) {
            JsonNode valueNode = node.get(key);
            return valueNode != null && !valueNode.isNull() ? valueNode.asDouble() : null;
        }
        
        /**
         * 获取布尔值
         * @param key 键名
         * @return 布尔值
         */
        public Boolean getBoolean(String key) {
            JsonNode valueNode = node.get(key);
            return valueNode != null && !valueNode.isNull() ? valueNode.asBoolean() : null;
        }
        
        /**
         * 获取键集合
         * @return 键的Set集合
         */
        public java.util.Set<String> keySet() {
            if (node.isObject()) {
                java.util.Set<String> keys = new java.util.HashSet<>();
                node.fieldNames().forEachRemaining(keys::add);
                return keys;
            }
            return java.util.Collections.emptySet();
        }
        
        /**
         * 检查是否包含指定键
         * @param key 键名
         * @return 是否包含
         */
        public boolean containsKey(String key) {
            return node.has(key);
        }
        
        /**
         * 转换为Java对象
         * @param clazz 目标类型
         * @param <T> 泛型类型
         * @return Java对象
         */
        public <T> T toJavaObject(Class<T> clazz) {
            try {
                return objectMapper.treeToValue(node, clazz);
            } catch (JsonProcessingException e) {
                throw new RuntimeException("JSON节点转对象失败", e);
            }
        }
    }
}