package com.yeejoin.amos.boot.module.jg.biz.edit.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.Iterator;
import java.util.Map;

public class JsonDiffUtil {

    public static boolean jsonEqualsIgnoreType(String json1, String json2) {
        ObjectMapper mapper = new ObjectMapper();
        // 处理输入的 null 和空字符串视为相等
        if (isNullOrEmpty(json1) && isNullOrEmpty(json2)) return true;
        if (isNullOrEmpty(json1) || isNullOrEmpty(json2)) return false;
        JsonNode node1 = null;
        try {
            node1 = mapper.readTree(json1);
            JsonNode node2 = mapper.readTree(json2);
            return equalsIgnoreType(node1, node2);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    private static boolean equalsIgnoreType(JsonNode node1, JsonNode node2) {
        // 处理输入的 null JsonNode
        if (node1 == null && node2 == null) return true;
        if (node1 == null || node2 == null) return node1 == node2;

        // 处理 JSON null 节点
        if (node1.isNull() && node2.isNull()) return true;
        if (node1.isNull() || node2.isNull()) return false;

        // 节点类型不同时尝试转换为文本比较
        if (!node1.getNodeType().equals(node2.getNodeType())) {
            return node1.asText().equals(node2.asText());
        }
        // 根据不同类型处理
        switch (node1.getNodeType()) {
            case OBJECT:
                if (node1.size() != node2.size()) return false;

                Iterator<Map.Entry<String, JsonNode>> fields = node1.fields();
                while (fields.hasNext()) {
                    Map.Entry<String, JsonNode> entry = fields.next();
                    JsonNode value2 = node2.get(entry.getKey());
                    if (value2 == null && !node2.has(entry.getKey())) {
                        return false; // 键不存在
                    }
                    if (!equalsIgnoreType(entry.getValue(), value2)) {
                        return false;
                    }
                }
                return true;

            case ARRAY:
                if (node1.size() != node2.size()) return false;
                for (int i = 0; i < node1.size(); i++) {
                    if (!equalsIgnoreType(node1.get(i), node2.get(i))) {
                        return false;
                    }
                }
                return true;

            case STRING:
                return node1.asText().equals(node2.asText());

            case NUMBER:
                return node1.decimalValue().compareTo(node2.decimalValue()) == 0;

            case BOOLEAN:
                return node1.asBoolean() == node2.asBoolean();

            case NULL:
                return true; // 前面已经处理过null

            default:
                return false;
        }
    }

    private static boolean isNullOrEmpty(String str) {
        return str == null || str.trim().isEmpty();
    }

}
