package com.ruoyi.business.controller;

import cn.cttic.crypto.bean.DecryptCodeBean;
import cn.cttic.crypto.bean.EncryptCodeBean;
import cn.cttic.crypto.bean.EncryptCrcBean;
import cn.cttic.crypto.service.SMCryptoService;
import cn.cttic.crypto.service.impl.SMCryptoServiceImpl;
import com.alibaba.druid.pool.DruidPooledPreparedStatement;
import com.alibaba.druid.proxy.jdbc.JdbcParameter;
import com.alibaba.druid.proxy.jdbc.PreparedStatementProxyImpl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.ruoyi.business.constant.BusinessServiceEnum;
import com.ruoyi.business.constant.FieldTypeEnum;
import com.ruoyi.business.domain.Adapter;
import com.ruoyi.business.domain.ServiceBusiness;
import com.ruoyi.business.domain.vo.OutQueryType;
import com.ruoyi.business.service.IAdapterService;
import com.ruoyi.business.service.IDatabaseService;
import com.ruoyi.business.service.IServiceBusinessService;
import com.ruoyi.business.service.IServiceGrantService;
import com.ruoyi.business.utils.FileZipUtils;
import com.ruoyi.common.auth.entity.OauthClientDetails;
import com.ruoyi.common.auth.service.OauthClientDetailsService;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.vo.TransportRequest;
import com.ruoyi.common.core.domain.vo.TransportRequestInfo;
import com.ruoyi.common.core.domain.vo.TransportResponse;
import com.ruoyi.common.core.exception.BusinessException;
import com.ruoyi.common.core.utils.FebsUtil;
import com.ruoyi.common.core.utils.ServletUtils;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.system.api.RemoteFileService;
import com.ruoyi.system.api.domain.SysFile;
import com.ruoyi.system.api.model.LoginUser;
import com.ruoyi.system.service.ISysDictDataService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.sql.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.*;

import static com.ruoyi.common.core.constant.Constants.DELETE_NO;
import static com.ruoyi.common.core.web.domain.AjaxResult.success;

/**
 * 外部查询接口调用返回结果
 */
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/outBusiness")
public class OutBusinessController {

    private final IDatabaseService databaseService;
    private final IServiceBusinessService serviceBusinessService;
    private final IAdapterService adapterService;
    private final ISysDictDataService sysDictDataService;
    private final IServiceGrantService serviceGrantService;
    private final DataSource dataSource;
    private final RemoteFileService remoteFileService;
    private final Gson gson = new Gson();
    private final SMCryptoService smCryptoService = new SMCryptoServiceImpl();
    private static final String encrypt_key = "8iot1blDJgNK36Do"; // 行政区划代码
    private static final String decrypt_key = "QLdQIASYMlT9SUUg";
    @Autowired
    private RedisService redisService;
    @Autowired
    private OauthClientDetailsService oauthClientDetailsService;

    @PostMapping
    public String outInsert(HttpServletRequest request, HttpServletResponse response) throws Exception {
//        if(files != null && files.length > 0 && !Objects.equals(files[0].getOriginalFilename(), "")) {
//            return outInsert2(request,files, jsonData);
//        } else {
//            return outInsert1(request,jsonData);
//        }
        log.info("==================================外部调用begin================================");
        String requestBody = IOUtils.toString(request.getInputStream(), "UTF-8");
        log.info("请求体信息requestBody（加密）: {}", requestBody);
        // 获取请求体内容（新增部分）
        TransportRequest transportRequest = gson.fromJson(requestBody, TransportRequest.class);
        String body = transportRequest.getBody();
        log.info("请求体信息body: {}", body);
        String token = transportRequest.getHeader().getToken();
        log.info("请求体信息token: {}", body);
        Map<String,Object>  crcBodyMap = new HashMap<>();
        Boolean tokenFlag = false;
        String user = "cq12328";
        if (redisService.hasKey(user)) {
            crcBodyMap = redisService.getCacheMap(user);
            for (Map.Entry<String, Object> entry : crcBodyMap.entrySet()) {
                String key = entry.getKey();   // 获取键（"header"或"body"）
                String value = String.valueOf(entry.getValue()); // 获取对应值
                if (token.equals(value)) {
                    tokenFlag = true;
                    break;
                } else {
                    tokenFlag = false;
                }
            }
        }  else {
            OauthClientDetails client = this.oauthClientDetailsService.findById(user);
            if (StringUtils.isNotEmpty(client.getAccessTokenInfo())) {
                if (token.equals(client.getAccessTokenInfo())) {
                    log.info("==================================token验证成功================================");
                    tokenFlag = true;
                } else {
                    log.info("==================================token验证失败1================================");
                    tokenFlag = false;
                }
            } else {
                log.info("==================================token验证失败2================================");
                transportRequest.getHeader().setReqType("1");
                transportRequest.getHeader().setCode("9999");
                transportRequest.getHeader().setMessage("token不存在");
                String transportResponse = gson.toJson(transportRequest);
                return transportResponse;
            }
        }
        if (!tokenFlag) {
            transportRequest.getHeader().setReqType("1");
            transportRequest.getHeader().setCode("9999");
            transportRequest.getHeader().setMessage("token验证失败");
            String transportResponse = gson.toJson(transportRequest);
            return transportResponse;
        }

        String ipcType = transportRequest.getHeader().getIpcType();
        AjaxResult ajaxResult = AjaxResult.success();
        if(ipcType == null || "".equals(ipcType)) {
            ajaxResult = AjaxResult.error("ipcType不能为空");
            transportRequest.getHeader().setReqType("1");
            transportRequest.getHeader().setCode("9999");
            transportRequest.getHeader().setMessage(ajaxResult.get("msg").toString());
            String transportResponse = gson.toJson(transportRequest);
            return transportResponse;
        }
        if ("GL1001".equals(ipcType)) {
            ajaxResult = AjaxResult.success("心跳检测成功");
            transportRequest.getHeader().setReqType("1");
            transportRequest.getHeader().setCode("9999");
            transportRequest.getHeader().setMessage(ajaxResult.get("msg").toString());
            String transportResponse = gson.toJson(transportRequest);
            return transportResponse;
        }
        String decryptBodyStr = "";
        if (!org.springframework.util.StringUtils.isEmpty(body)) {
            try {
                decryptBodyStr = decryptBody(body);
                log.info("请求体信息Body（解密后）: {}", decryptBodyStr);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        if ("GL1004".equals(ipcType)) {
            outFiles(decryptBodyStr,response);
            return "附件获取成功";
        }
        ajaxResult = outInsert1(transportRequest,decryptBodyStr,response);
        if (ajaxResult.isSuccess() ||  Integer.valueOf(200).equals(ajaxResult.get("code"))) {
            transportRequest.getHeader().setReqType("1");
            transportRequest.getHeader().setCode("0000");
            transportRequest.getHeader().setMessage(ajaxResult.get("msg").toString());
            transportRequest.setBody("");
        } else {
            transportRequest.getHeader().setReqType("1");
            transportRequest.getHeader().setCode("9999");
            transportRequest.getHeader().setMessage(ajaxResult.get("msg").toString());
        }
        String transportResponse = gson.toJson(transportRequest);
        return transportResponse;
    }

    private AjaxResult outInsert1(TransportRequest transportRequest,  String jsonData, HttpServletResponse response) throws Exception{

        String ipcType = transportRequest.getHeader().getIpcType();
        ServiceBusiness serviceBusiness = serviceBusinessService.selectServiceBusinessByOutName(ipcType+"_OUT");
        // validGrant(String.valueOf(serviceBusiness.getId()));
        if(!BusinessServiceEnum.insert.getCode().equals(serviceBusiness.getType())) {
            throw new BusinessException("接口类型异常，请检查接口文档");
        }
        // 获取remark信息
        String reqBody = "";
        JSONObject remarkJson = null;
        if (StringUtils.isNotEmpty(serviceBusiness.getRemark())) {
            try {
                // 解析 JSON 字符串
                remarkJson = JSONObject.parseObject(serviceBusiness.getRemark());
                // 提取 url 字段
                reqBody = remarkJson.getString("body");
                if (StringUtils.isEmpty(reqBody)) {
                    reqBody = "recordInfo";
                }
            } catch (Exception e) {
                log.error("解析 remark 字段失败", e);
                return AjaxResult.error("解析 remark 字段失败");
            }
        } else {
            reqBody = "recordInfo";
        }
        // 新增final副本用于lambda
        final String finalReqBody = reqBody;
        TransportRequestInfo transportRequestInfo = JSONObject.parseObject(jsonData, TransportRequestInfo.class);
        Map<String,Object> transportMap = (Map<String, Object>) transportRequestInfo.getReqInfo();

        //JSONArray jsonArray = (JSONArray.parseArray(String.valueOf(transportMap.get(finalReqBody))));
        //log.info(jsonArray.toString());
        // 增加JSON类型判断逻辑
        Object data = transportMap.get(finalReqBody);
        String jsonStr = String.valueOf(data);
        JSONArray jsonArray;

        if (StringUtils.isNotEmpty(jsonStr)) {
            if (jsonStr.trim().startsWith("[")) {
                jsonArray = JSONArray.parseArray(jsonStr);
            } else if (jsonStr.trim().startsWith("{")) {
                // 如果字段要求数组但收到对象，可以按需处理：
                // 1. 返回错误：return AjaxResult.error(finalReqBody + "字段应为数组格式");
                // 2. 包装成数组
                jsonArray = new JSONArray();
                jsonArray.add(JSONObject.parseObject(jsonStr));
            } else {
                return AjaxResult.error(finalReqBody + "字段格式异常，应为JSON数组或对象");
            }
        } else {
            return AjaxResult.error(finalReqBody + "字段不能为空");
        }

        log.info("插入的jsonArray.toString数组："+jsonArray.toString());

        int batchSize = 50;
        if (jsonArray.size() > batchSize) {
            return AjaxResult.error("超过50条数据");
        }

        int coreCount = Runtime.getRuntime().availableProcessors();
        ExecutorService executor = Executors.newFixedThreadPool(coreCount * 2);
        List<CompletableFuture<Void>> futures = new ArrayList<>();

        try {
            // 循环处理JSONArray中的每个JSONObject
            for (int i = 0; i < jsonArray.size(); i++) {
                final int idx = i; // 创建final副本解决lambda表达式变量捕获问题
                futures.add(CompletableFuture.runAsync(() -> {
                    try {
                        JSONObject jsonObject = jsonArray.getJSONObject(idx);
                        insertData(jsonObject, serviceBusiness);
                    } catch (SQLException e) {
                        // 异常处理逻辑需要重构，此处仅记录日志
                        log.error("插入数据失败: {}", e.getMessage());
                        throw new CompletionException(e); // 包装异常
                    }
                }, executor)); // 使用统一的线程池
            }

            // 等待所有任务完成
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        } catch (CompletionException e) {
            Throwable rootCause = e.getCause();
            if (rootCause instanceof SQLException) {
                // 提取并处理SQL异常信息
                SQLException sqlEx = (SQLException) rootCause;
                if (sqlEx.getMessage().contains("doesn't have a default value")) {
                    String message = sqlEx.getMessage();
                    int startIndex = message.indexOf("Field") + "Field".length();
                    int endIndex = message.indexOf("doesn't");
                    String fieldName = message.substring(startIndex, endIndex).trim();
                    return AjaxResult.error(fieldName + "必填字段未填写");
                }
            }
            return AjaxResult.error("批量插入失败: " + rootCause.getMessage());
        } finally {
            executor.shutdown();
        }
        return AjaxResult.success("插入成功");
    }

    private AjaxResult outInsert2(TransportRequest transportRequest,
                                MultipartFile[] files,
                                String jsonData) {
        String ipcType = transportRequest.getHeader().getIpcType();
        ServiceBusiness serviceBusiness = serviceBusinessService.selectServiceBusinessByOutName(ipcType);
        // validGrant(String.valueOf(serviceBusiness.getId()));
        if(!BusinessServiceEnum.insert.getCode().equals(serviceBusiness.getType())) {
            throw new BusinessException("接口类型异常，请检查接口文档");
        }
        JSONObject json = JSONObject.parseObject(jsonData);
        //校验附件的数量是否与json字段中附件数量、附件名称不一致直接抛出错误
//        if(files != null && files.length > 0) {
            String queryField = serviceBusiness.getQueryField();
            JSONArray jsonArray = JSON.parseArray(queryField);
            Set<String> jsonFileSet = new HashSet<>();

            // 从 JSON 中获取符合条件的字段并构建文件名集合
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                if ("4".equals(jsonObject.getString("type"))) {
                    String fieldValue = json.getString(jsonObject.getString("field"));
                    if (StringUtils.isNotEmpty(fieldValue)) {
                        jsonFileSet.addAll(Arrays.asList(fieldValue.split(",")));
                    }
                }
            }

            // 将 MultipartFile 文件名转换为集合
            Set<String> uploadedFileSet = new HashSet<>();
            for (MultipartFile file : files) {
                uploadedFileSet.add(file.getOriginalFilename());
            }

            // 比较两个集合
            if (!jsonFileSet.equals(uploadedFileSet)) {
                return AjaxResult.error("文件数量或名称不同");
            }
//        }
        //判断MultipartFile[] files不为空且长度大于0时
//        if(files != null && files.length > 0) {
            //遍历files
            for (MultipartFile file : files) {
                R<SysFile> upload = remoteFileService.upload(file);
                String fileName =  file.getOriginalFilename();
                String updateFileName = upload.getData().getName();
                for (String key : json.keySet()) {
                    if (json.get(key) instanceof String) {
                        String value = json.getString(key);
                        // 将当前值拆分成数组
                        String[] currentFileNames = value.split(",");
                        // 创建一个新的集合来存储更新后的文件名
                        StringBuilder updatedFileNames = new StringBuilder();

                        // 遍历当前文件名数组
                        for (String currentFileName : currentFileNames) {
                            // 检查当前文件名是否在要查找的文件名数组中
                            if (currentFileName.trim().equals(fileName.trim())) {
                                // 如果找到匹配的文件名，使用新文件名替换
                                updatedFileNames.append(updateFileName).append(",");
                            } else {
                                updatedFileNames.append(currentFileName).append(",");
                            }
                        }

                        // 移除最后一个逗号
                        if (updatedFileNames.length() > 0) {
                            updatedFileNames.deleteCharAt(updatedFileNames.length() - 1);
                        }
                        // 将更新后的文件名设置回 JSON 对象
                        json.put(key, updatedFileNames.toString());
                    }
                }

            }
//        }

        try {
            insertData(json, serviceBusiness);
        } catch (SQLException e) {
            // 判断SQLException的具体信息
            if (e.getMessage().contains("doesn't have a default value")) {
                //截取e.getMessage()中Field和doesn't之间的字符
                // 获取异常消息
                String message = e.getMessage();
                // 找到 "Field" 和 "doesn't" 的位置
                int startIndex = message.indexOf("Field") + "Field".length(); // "Field" 后的起始位置
                int endIndex = message.indexOf("doesn't"); // "doesn't" 的起始位置
                // 截取 "Field" 和 "doesn't" 之间的字符
                String fieldName = message.substring(startIndex, endIndex).trim(); // trim() 去除前后的空格

                return AjaxResult.error(fieldName+"必填字段未填写");
            }
        }
        return AjaxResult.success("插入成功");
    }

    private void outFiles(String jsonData, HttpServletResponse response) throws Exception{
        String finalReqBody = "recordInfo";
        // 新增final副本用于lambda
        TransportRequestInfo transportRequestInfo = JSONObject.parseObject(jsonData, TransportRequestInfo.class);
        Map<String,Object> transportMap = (Map<String, Object>) transportRequestInfo.getReqInfo();

        Object data = transportMap.get(finalReqBody);
        String jsonStr = String.valueOf(data);
        JSONArray jsonArray = new JSONArray();

        if (StringUtils.isNotEmpty(jsonStr)) {
            if (jsonStr.trim().startsWith("[")) {
                jsonArray = JSONArray.parseArray(jsonStr);
            } else if (jsonStr.trim().startsWith("{")) {
                // 如果字段要求数组但收到对象，可以按需处理：
                // 1. 返回错误：return AjaxResult.error(finalReqBody + "字段应为数组格式");
                // 2. 包装成数组
                jsonArray = new JSONArray();
                jsonArray.add(JSONObject.parseObject(jsonStr));
            }
        }

        log.info("jsonArray.toString数组："+jsonArray.toString());

        Map<String,String> fileInfo = new HashMap<>();
        // 循环处理JSONArray中的每个JSONObject
        for (int i = 0; i < jsonArray.size(); i++) {
            final int idx = i; // 创建final副本解决lambda表达式变量捕获问题
            JSONObject jsonObject = jsonArray.getJSONObject(idx);
            for (String key : jsonObject.keySet()) {
                Object value = jsonObject.get(key);
                if (key.contains("Id")) {
                    fileInfo.put("Id", String.valueOf(value));
                }
                if (key.contains("Name")) {
                    fileInfo.put("Name", String.valueOf(value));
                }
                if (key.contains("Type")) {
                    fileInfo.put("Type", String.valueOf(value));
                }
            }
        }
        FileZipUtils.getEncryptZip(response,fileInfo);
    }

    /**
     * 接口权限
     * @param businessId 业务id
     */
    public void validGrant(String businessId) {
        //接口权限校验
        LoginUser loginUser = SecurityUtils.getLoginUser();
        assert loginUser != null;
        List<String> grants = serviceGrantService.selectServiceBusinessIdByClientId(loginUser.getUsername(), null);
        if(!grants.contains(businessId)) {
            throw new BusinessException("您暂无该接口查询权限，请联系平台运营方授权");
        }
    }

    /**
     * 获取业务id
     * @param request 请求
     * @return 业务id
     */
    private String getBusinessId(HttpServletRequest request) {
        Map<String, String> paramMap = ServletUtils.getParamMap(request);
        String businessId;
        if(StringUtils.isNotEmpty(paramMap.get("businessId"))) {
            businessId = paramMap.get("businessId");
        } else {
            businessId = ServletUtils.getHeader("businessId");
        }
        return businessId;
    }

    /**
      * 查询数据
      * <p>json格式</p>
      * @param request 请求
      * @return AjaxResult
      * @throws SQLException, IOException
      */
    @PostMapping("query")
    public AjaxResult outQuery(HttpServletRequest request) throws SQLException, IOException {
        JSONObject jsonObject = getJson(request);
        String businessId = getBusinessId(request);
        validGrant(businessId);
        ServiceBusiness serviceBusiness = serviceBusinessService.selectServiceBusinessById(Long.parseLong(businessId));
        Map<String, Object> res = new HashMap<>();
        List<Map<String, Object>> list;

        if(BusinessServiceEnum.custom.getCode().equals(serviceBusiness.getType())) {
            String queryField = serviceBusiness.getResultSql();
            StringBuilder sb = new StringBuilder();
            sb.append(queryField);
            String sbCount = "select count(1) from" + queryField.toLowerCase().split("from")[1];

            //默认排序
            if(!queryField.toLowerCase().contains("order by")) {
                sb.append(" order by id desc");
            }
            //分页
            sb.append(" limit ?,?");
            log.debug("sb=" + sb);
            // ps：目前写死从mybatis-plus多数据源master取，后续匹配对应数据源
//            Connection conn = databaseService.getConnection(serviceBusiness.getDatabaseId(), null);
            Connection conn = dataSource.getConnection();
            PreparedStatement ps = conn.prepareStatement(sb.toString());
            PreparedStatement psCount = conn.prepareStatement(sbCount);
            list = queryData(ps, 1, serviceBusiness, jsonObject);
            res.put("rows", list);
            int total = queryCount(psCount);
            res.put("total", total);
            ps.close();
            conn.close();
        } else if(BusinessServiceEnum.select.getCode().equals(serviceBusiness.getType())) {
            String queryField = serviceBusiness.getQueryField();
            ObjectMapper objectMapper = new ObjectMapper();
            List<OutQueryType> queryFieldList = objectMapper.readValue(queryField, new TypeReference<List<OutQueryType>>() {});
            Map<String, OutQueryType> queryFieldMap = new HashMap<>();
            for (OutQueryType queryType: queryFieldList) {
                queryFieldMap.put(queryType.getField(), queryType);
            }
            String resultField = serviceBusiness.getResultField();
            String[] split = resultField.split(",");
            Set<String> resFieldSet = new HashSet<>(Arrays.asList(split));
            StringBuilder sb = new StringBuilder();
            StringBuilder sbCount = new StringBuilder();
            sb.append("select ");
            sbCount.append("select count(1) from ");
            for (String resField: resFieldSet) {
                sb.append(resField);
                sb.append(",");
            }
            sb.deleteCharAt(sb.length() -1);
            sb.append(" from ");
            sb.append(serviceBusiness.getTableName());
            sbCount.append(serviceBusiness.getTableName());
            boolean hasWhere = false;
            for (Map.Entry<String, OutQueryType> entry : queryFieldMap.entrySet()) {
                if(jsonObject != null && StringUtils.isNotEmpty(jsonObject.getString(entry.getKey()))) {
                    if(hasWhere) {
                        sb.append(" and ");
                        sbCount.append(" and ");
                    } else {
                        sb.append(" where ");
                        sbCount.append(" where ");
                        hasWhere = true;
                    }
                    sb.append(entry.getKey());
                    sbCount.append(entry.getKey());
                    if(FieldTypeEnum.eq.getCode().equals(entry.getValue().getType())) {
                        sb.append(" = ?");
                        sbCount.append(" = ?");
                    } else if(FieldTypeEnum.like.getCode().equals(entry.getValue().getType())) {
                        sb.append(" like ?");
                        sbCount.append(" like ?");
                    } else if(FieldTypeEnum.dataRange.getCode().equals(entry.getValue().getType())) {
                        sb.append(" between ? and ?");
                        sbCount.append(" between ? and ?");
                    }
                }
            }
            sb.append(" order by id desc limit ?,?");
            log.debug("sb=" + sb);
            // ps：目前写死从mybatis-plus多数据源master取，后续匹配对应数据源
//            Connection conn = databaseService.getConnection(serviceBusiness.getDatabaseId(), null);
            Connection conn = dataSource.getConnection();
            PreparedStatement ps = conn.prepareStatement(sb.toString());
            PreparedStatement psCount = conn.prepareStatement(sbCount.toString());
            int index = 1;
            for (Map.Entry<String, OutQueryType> entry : queryFieldMap.entrySet()) {
                if(jsonObject != null && StringUtils.isNotEmpty(jsonObject.getString(entry.getKey()))) {
                    if(FieldTypeEnum.eq.getCode().equals(entry.getValue().getType())) {
                        ps.setObject(index, jsonObject.get(entry.getKey()));
                        psCount.setObject(index, jsonObject.get(entry.getKey()));
                        index++;
                    } else if(FieldTypeEnum.like.getCode().equals(entry.getValue().getType())) {
                        ps.setObject(index, "%" + jsonObject.get(entry.getKey()) + "%");
                        psCount.setObject(index, "%" + jsonObject.get(entry.getKey()) + "%");
                        index++;
                    } else if(FieldTypeEnum.dataRange.getCode().equals(entry.getValue().getType())) {
                        String[] dateRangeSplit = jsonObject.getString(entry.getKey()).split(",");
                        ps.setObject(index, dateRangeSplit[0] + " 00:00:00");
                        psCount.setObject(index, dateRangeSplit[0] + " 00:00:00");
                        index++;
                        ps.setObject(index, dateRangeSplit[1] + " 23:59:59");
                        psCount.setObject(index, dateRangeSplit[1] + " 23:59:59");
                        index++;
                    }
                }
            }
            list = queryData(ps, index, serviceBusiness, jsonObject);
            res.put("rows", list);
            int total = queryCount(psCount);
            res.put("total", total);
            ps.close();
            conn.close();
        }
        return success(res);
    }

    /**
     * 调用查询，返回数据
     * @param ps PreparedStatement
     * @param index ps顺序
     * @param serviceBusiness 业务服务
     * @return List
     */
    private List<Map<String, Object>> queryData(PreparedStatement ps, int index, ServiceBusiness serviceBusiness, JSONObject jsonObject) throws SQLException {
        List<Map<String, Object>> list = new ArrayList<>();
        DateTimeFormatter dfClock = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        convertSqlToPage(ps, index, jsonObject);
//        System.out.println("ps=" + transSql(ps));

        ResultSet rs = ps.executeQuery();
        Adapter queryAdapter = new Adapter();
        queryAdapter.setServiceBusinessId(serviceBusiness.getId());
        queryAdapter.setStatus(DELETE_NO);
        List<Adapter> adapters = adapterService.selectAdapterList(queryAdapter);
        while (rs.next()) {
            int columnCount = rs.getMetaData().getColumnCount();
            Map<String, Object> rowData = new HashMap<>();
            for (int i = 1; i <= columnCount; i++) {
                String columnName = rs.getMetaData().getColumnLabel(i);
                if (columnName != null && !columnName.isEmpty()) {
                    Object value = rs.getObject(i);
                    if (value instanceof LocalDateTime) {
                        LocalDateTime timeTmp = (LocalDateTime) value;
                        value = timeTmp.format(dfClock);
                    }
                    value = dealAdapter(adapters, columnName, value);
                    rowData.put(columnName, value);
                }
            }
            list.add(rowData);
        }
        return list;
    }

    /**
     * 调用查询，返回数据
     * @param ps PreparedStatement
     * @return List
     */
    private int queryCount(PreparedStatement ps) throws SQLException {
//        System.out.println("ps=" + transSql(ps));
        int total = 0;
        ResultSet rs = ps.executeQuery();
        while (rs.next()) {
            total = rs.getInt(1);
        }
        return total;
    }

    /**
     * 解析druid的sql，替换？，生成真正的sql
     * @param ps DruidPooledPreparedStatement
     * @return sql
     */
    private String transSql(PreparedStatement ps) {
        DruidPooledPreparedStatement psLog = (DruidPooledPreparedStatement)ps;
        String sql = psLog.getSql();
        PreparedStatementProxyImpl rawStatement = (PreparedStatementProxyImpl)psLog.getRawStatement();
        if (!sql.contains("?")) {
            return sql;
        }
        int size = rawStatement.getParameters().size();
        for (int i = 0; i < size; i++) {
            sql = sql.replaceFirst("\\?", getParamValue(rawStatement.getParameter(i)));
        }
        return sql;
    }

    private String getParamValue(JdbcParameter jdbcParameter) {
        if(jdbcParameter == null) {
            return "NULL";
        }
        Object val = jdbcParameter.getValue();
        int type = jdbcParameter.getSqlType();
        if (type == Types.INTEGER) {
            return String.valueOf(val);
        }
        return "'" + val + "'";
    }

    /**
     * 处理适配器
     * @param adapters 适配器
     * @param columnName 字段名
     * @param o 字段值
     * @return 结果
     */
    private Object dealAdapter(List<Adapter> adapters, String columnName, Object o) {
        if(!adapters.isEmpty()) {
            for (Adapter a : adapters) {
                if(columnName.equals(a.getServiceBusinessField())) {
                    if(a.getType().equals("1")) {
                        //系统字典
                        o = sysDictDataService.selectDictLabel(a.getContent(), (String) o);
                    }
                }
            }
        }
        return o;
    }

    /**
     * 设置分页
     * <p>以每页10条举例。第一页: limit 0,10;第二页: limit 10,10;第三页: limit 20,10;</p>
     * @param ps PreparedStatement
     * @param index PreparedStatement的当前变量序号
     * @param jsonObject 包含pageSize 每页条数、pageNum 第几页
     * @throws SQLException 异常
     */
    public void convertSqlToPage(PreparedStatement ps, int index, JSONObject jsonObject) throws SQLException {
        Integer pageSize;
        Integer pageNum;
        if(jsonObject == null) {
            pageNum = 1;
            pageSize = 10;
        } else {
            pageSize = jsonObject.getInteger("pageSize");
            pageNum = jsonObject.getInteger("pageNum");
            if (ObjectUtils.isEmpty(pageNum)) {
                pageNum = 1;
            }
            if (ObjectUtils.isEmpty(pageSize)) {
                pageSize = 10;
            }
            if(pageSize > 50) {
                pageSize = 50;
            }
        }
        pageNum = (pageNum - 1) * pageSize;
        ps.setInt(index++, pageNum);
        ps.setInt(index, pageSize);
    }

    /**
     * 从Servlet中的HttpServletRequest参数中获取json
     * @param request 请求
     * @return JSONObject
     * @throws IOException IOException
     */
    public static JSONObject getJson(HttpServletRequest request) throws IOException {
        //从前端获取输入字节流
        ServletInputStream requestInputStream = request.getInputStream();
        //将字节流转换为字符流,并设置字符编码为utf-8
        InputStreamReader ir = new InputStreamReader(requestInputStream, StandardCharsets.UTF_8);
        //使用字符缓冲流进行读取
        BufferedReader br = new BufferedReader(ir);
        //开始拼装json字符串
        String line;
        StringBuilder sb = new StringBuilder();
        while((line = br.readLine())!=null) {
            sb.append(line);
        }
        JSONObject json = JSONObject.parseObject(sb.toString());
        return (JSONObject) JSONObject.parse(String.valueOf(json));
    }

    /**
     * 插入数据
     * @param json 数据
     * @param serviceBusiness 业务信息
     * @throws SQLException SQLException
     */
    private void insertData(JSONObject json, ServiceBusiness serviceBusiness) throws SQLException {
        String resultField = serviceBusiness.getResultField();
        String[] split = resultField.split(",");
        Set<String> resFieldSet = new HashSet<>(Arrays.asList(split));
        StringBuilder sb = new StringBuilder("INSERT INTO ");
        sb.append(serviceBusiness.getTableName());
//        sb.append(" (client_id,");
        sb.append(" (");
        // 构建字段部分
        for (String key : json.keySet()) {
            if (resFieldSet.contains(FebsUtil.camelToUnderscore(key))) {
                sb.append(FebsUtil.camelToUnderscore(key));
                sb.append(",");
            }
        }
        sb.deleteCharAt(sb.length() - 1); // 删除最后一个逗号
        sb.append(") VALUES (");
//        sb.append(") VALUES ('");
//        sb.append(SecurityUtils.getUsername());
//        sb.append("',");
        // 构建值部分
        for (String key : json.keySet()) {
            if (resFieldSet.contains(FebsUtil.camelToUnderscore(key))) {
                sb.append("?,");
            }
        }
        sb.deleteCharAt(sb.length() - 1); // 删除最后一个逗号
        sb.append(")");

        String sqlInsert = sb.toString();
        log.info("生成的插入语句：sqlInsert=" + sqlInsert);
        // ps：目前写死从mybatis-plus多数据源master取，后续匹配对应数据源
//        Connection conn = databaseService.getConnection(serviceBusiness.getDatabaseId(), null);
        Connection conn = dataSource.getConnection();
        PreparedStatement ps = conn.prepareStatement(sqlInsert);
        int index = 1;

        // 设置参数
        for (String key : json.keySet()) {
            if (resFieldSet.contains(FebsUtil.camelToUnderscore(key))) {
                Object value = json.get(key);
                if (value instanceof JSONArray) {
                    ps.setString(index++, ((JSONArray) value).toJSONString());
                } else if (value instanceof JSONObject) {
                    ps.setString(index++, ((JSONObject) value).toJSONString());
                } else if (value != null) {
                    ps.setString(index++, value.toString());
                } else {
                    ps.setNull(index++, Types.VARCHAR);
                }
            }
        }
        // 执行插入
        ps.execute();
        ps.close();
        conn.close();
    }

    // SM3哈希计算
    private String calculateSM3(String data) {
        EncryptCrcBean encryptCrcBean = new EncryptCrcBean();
        encryptCrcBean.setPass(data);
        String cipherText_crc = smCryptoService.encryptCrc(encryptCrcBean);
        return cipherText_crc;
    }

    // SM4加密（ECB模式）
    private String encryptBody(String plainText) throws Exception {
        EncryptCodeBean encryptCodeBean = new EncryptCodeBean();
        encryptCodeBean.setSecretKey(encrypt_key);
        encryptCodeBean.setPass(plainText);
        String cipherText = smCryptoService.encrypt_Body(encryptCodeBean);
        return cipherText;
    }

    // SM4解密（ECB模式）
    private String decryptBody(String plainText) throws Exception {
        DecryptCodeBean encrypt2 = new DecryptCodeBean();
        encrypt2.setSecretKey(decrypt_key);
        encrypt2.setPass(plainText);
        String cipherText = smCryptoService.decrypt_Body(encrypt2);
        return cipherText;
    }
}
