package org.example.Utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.NClob;
import java.sql.SQLException;
import java.util.*;

public class BlobUtil {
    private static final Logger log = LoggerFactory.getLogger(BlobUtil.class);

    // ===================== 新增：判断是否包含Blob类型的私有方法 =====================
    /**
     * 检查列表第一个元素是否包含Blob类型字段（避免全量遍历）
     */
    private static boolean hasBlobType(List<Map<String, Object>> dataList) {
        if (Objects.isNull(dataList) || dataList.isEmpty()) {
            return false;
        }
        Map<String, Object> firstMap = dataList.get(0);
        if (Objects.isNull(firstMap) || firstMap.isEmpty()) {
            return false;
        }
        // 遍历首元素的所有字段，判断是否有Blob类型
        for (Object value : firstMap.values()) {
            if (value instanceof Blob) {
                return true; // 发现Blob，立即返回true
            }
        }
        return false; // 无Blob类型
    }

    // ===================== 新增：判断是否包含Text(Clob/NClob)类型的私有方法 =====================
    /**
     * 检查列表第一个元素是否包含Clob/NClob类型字段（避免全量遍历）
     */
    private static boolean hasTextType(List<Map<String, Object>> dataList) {
        if (Objects.isNull(dataList) || dataList.isEmpty()) {
            return false;
        }
        Map<String, Object> firstMap = dataList.get(0);
        if (Objects.isNull(firstMap) || firstMap.isEmpty()) {
            return false;
        }
        // 遍历首元素的所有字段，判断是否有Clob/NClob类型
        for (Object value : firstMap.values()) {
            if (value instanceof Clob || value instanceof NClob) {
                return true; // 发现Text类型，立即返回true
            }
        }
        return false; // 无Text类型
    }

    /**
     * 遍历List<Map>，将所有Blob类型的值转换为byte[]，并释放Blob资源
     *
     * @param dataList 待处理的List<Map>，直接修改原Map（引用传递）
     */
    public static void convertBlobToByteArray(List<Map<String, Object>> dataList) {
        // 1. 空值校验 + 新增：检查首元素是否有Blob类型，无则直接返回
        if (Objects.isNull(dataList) || dataList.isEmpty()) {
            log.info("待处理的List为空，无需转换Blob");
            return;
        }
        if (!hasBlobType(dataList)) {
            log.info("列表首元素无Blob类型字段，跳过Blob转换");
            return;
        }

        // 2. 原有转换逻辑（完全不变）
        for (Map<String, Object> dataMap : dataList) {
            if (Objects.isNull(dataMap) || dataMap.isEmpty()) {
                continue;
            }

            Set<String> keySet = new HashSet<>(dataMap.keySet());
            for (String key : keySet) {
                Object value = dataMap.get(key);
                if (value instanceof Blob) {
                    Blob blob = (Blob) value;
                    try {
                        byte[] byteArray = null;
                        if (blob.length() > 0) {
                            byteArray = blob.getBytes(1, (int) blob.length());
                        }
                        dataMap.put(key, byteArray);
                        blob.free();
                        log.debug("字段[{}]的Blob已成功转换为byte[]，长度：{}", key,
                                byteArray == null ? 0 : byteArray.length);
                    } catch (SQLException e) {
                        log.error("字段[{}]的Blob转换为byte[]失败", key, e);
                        dataMap.put(key, null);
                        try {
                            blob.free();
                        } catch (SQLException ex) {
                            log.error("释放Blob资源失败", ex);
                        }
                    }
                }
            }
        }
    }

    // ===================== 核心修改：TEXT转换为NVARCHAR对应String =====================
    /**
     * 将数据库TEXT类型(NClob/Clob)转换为 适配NVARCHAR规范的Java String
     * 匹配Unicode字符集，支持中文/特殊字符，解决序列化与乱码问题
     * @param dataList 业务数据集
     */
    public static void convertTextToNvarcharString(List<Map<String, Object>> dataList) {
        // 1. 空值校验 + 新增：检查首元素是否有Text类型，无则直接返回
        if (Objects.isNull(dataList) || dataList.isEmpty()) {
            log.info("待处理的List为空，无需转换TEXT类型");
            return;
        }
        if (!hasTextType(dataList)) {
            log.info("列表首元素无Text(Clob/NClob)类型字段，跳过Text转换");
            return;
        }

        // 2. 原有转换逻辑（完全不变）
        for (Map<String, Object> dataMap : dataList) {
            if (Objects.isNull(dataMap) || dataMap.isEmpty()) {
                continue;
            }
            Set<String> keySet = new HashSet<>(dataMap.keySet());
            for (String key : keySet) {
                Object value = dataMap.get(key);
                try {
                    if (value instanceof NClob nclob) {
                        readNclobAsUnicode(key, nclob, dataMap);
                    } else if (value instanceof Clob clob) {
                        readClobAsUnicode(key, clob, dataMap);
                    }
                } catch (Exception e) {
                    log.error("字段[{}] TEXT转NVARCHAR格式字符串失败", key, e);
                    dataMap.put(key, null);
                }
            }
        }
    }

    /**
     * 读取NClob为Unicode字符串，完美匹配数据库NVARCHAR类型
     */
    private static void readNclobAsUnicode(String key, NClob nclob, Map<String, Object> dataMap) throws SQLException, IOException {
        String content = null;
        try (BufferedReader reader = new BufferedReader(nclob.getCharacterStream())) {
            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            content = sb.toString();
            dataMap.put(key, content);
            log.debug("字段[{}] NClob(TEXT)转换为NVARCHAR格式String成功，长度：{}", key, content.length());
        } finally {
            try {
                if (nclob != null) {
                    nclob.free();
                }
            } catch (SQLException e) {
                log.error("字段[{}] 释放NClob资源失败", key, e);
            }
        }
    }

    /**
     * 读取Clob为Unicode字符串，兼容通用场景
     */
    private static void readClobAsUnicode(String key, Clob clob, Map<String, Object> dataMap) throws SQLException, IOException {
        String content = null;
        try (BufferedReader reader = new BufferedReader(clob.getCharacterStream())) {
            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            content = sb.toString();
            dataMap.put(key, content);
            log.debug("字段[{}] Clob(TEXT)转换为NVARCHAR格式String成功，长度：{}", key, content.length());
        } finally {
            try {
                if (clob != null) {
                    clob.free();
                }
            } catch (SQLException e) {
                log.error("字段[{}] 释放Clob资源失败", key, e);
            }
        }
    }

    /**
     * 快捷方法：一键处理所有大对象 Blob + TEXT(NVARCHAR格式)
     */
    public static void convertAllLobToStandard(List<Map<String, Object>> dataList) {
        // 复用新增的判断逻辑，避免重复检查
        boolean needBlobConvert = hasBlobType(dataList);
        boolean needTextConvert = hasTextType(dataList);

        if (needBlobConvert) {
            convertBlobToByteArray(dataList);
        } else {
            log.info("列表首元素无Blob类型字段，跳过Blob转换");
        }

        if (needTextConvert) {
            convertTextToNvarcharString(dataList);
        } else {
            log.info("列表首元素无Text类型字段，跳过Text转换");
        }
    }
}