package com.chinaweal.aiccs.schedule;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.XML;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.chinaweal.aiccs.aicbizqy.entity.datamove.*;
import com.chinaweal.aiccs.aicbizqy.mapper.datamove.*;
import com.chinaweal.aiccs.crgs.entity.EMoveOut;
import com.chinaweal.aiccs.crgs.mapper.EMoveOutMapper;
import com.chinaweal.aiccs.aiccs.abnormal.mapper.FileUploadRecordMapper;
import com.chinaweal.aiccs.aiccs.abnormal.entity.FileUploadRecord;
import com.chinaweal.aiccs.schedule.FileUploadService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.File;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.sql.Timestamp;
import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.UUID;
import java.util.Objects;

/**
 * 迁出省局数据定时任务
 * 功能：查询需要迁出的企业数据，生成XML文件并压缩成ZIP包
 *
 * @author Claude
 */
@Component
@ConditionalOnProperty(prefix = "scheduling", name = "enable", havingValue = "true")
@Slf4j
public class MoveOutDataSchedule {

    @Autowired
    private EMoveOutMapper eMoveOutMapper;

    @Autowired
    private FileUploadRecordMapper fileUploadRecordMapper;

    @Autowired
    private FileUploadService fileUploadService;

    // 主要企业信息表Mapper
    @Autowired
    private EBaseInfoDataMoveMapper eBaseInfoMapper;
    @Autowired
    private EAlterRecoderDataMoveMapper eAlterRecoderMapper;
    @Autowired
    private EImPermitDataMoveMapper eImPermitMapper;
    @Autowired
    private EOtSpotcheckDataMoveMapper eOtSpotcheckMapper;
    @Autowired
    private EPubSpotcheckDataMoveMapper ePubSpotcheckMapper;
    @Autowired
    private DrRaninsresDataMoveMapper drRaninsresMapper;
    @Autowired
    private AoOpAnomalyDataMoveMapper aoOpAnomalyMapper;
    @Autowired
    private AoOpaDetailDataMoveMapper aoOpaDetailMapper;
    @Autowired
    private AoOpAnomalyInvDataMoveMapper aoOpAnomalyInvMapper;
    @Autowired
    private AnBaseinfoDataMoveMapper anBaseinfoMapper;
    @Autowired
    private EImInvestmentDataMoveMapper eImInvestmentMapper;
    @Autowired
    private EImInvupdateDataMoveMapper eImInvupdateMapper;
    @Autowired
    private CaseCreInformationDataMoveMapper caseCreInformationMapper;
    @Autowired
    private EImIppldgDataMoveMapper eImIppldgMapper;
    @Autowired
    private EImCaseDataMoveMapper eImCaseMapper;
    @Autowired
    private EImInvsraltDataMoveMapper eImInvsraltMapper;
    @Autowired
    private ELiIlldishonestyDataMoveMapper eLiIlldishonestyMapper;
    @Autowired
    private ELiIlldisdetailDataMoveMapper eLiIlldisdetailMapper;
    @Autowired
    private CasePubNbaseinfoDataMoveMapper casePubNbaseinfoMapper;
    @Autowired
    private EOtNpermitDataMoveMapper eOtNpermitMapper;
    @Autowired
    private EOtNcaseDataMoveMapper eOtNcaseMapper;

    // AN相关表Mapper
    @Autowired
    private AnSubcapitalDataMoveMapper anSubcapitalMapper;
    @Autowired
    private AnForinvestmentDataMoveMapper anForinvestmentMapper;
    @Autowired
    private AnWebsiteinfoDataMoveMapper anWebsiteinfoMapper;
    @Autowired
    private AnAlterstockinfoDataMoveMapper anAlterstockinfoMapper;
    @Autowired
    private AnForguaranteeinfoDataMoveMapper anForguaranteeinfoMapper;
    @Autowired
    private AnUpdateinfoDataMoveMapper anUpdateinfoMapper;
    @Autowired
    private AnSupBaseinfoDataMoveMapper anSupBaseinfoMapper;
    @Autowired
    private AnSocsecinfoDataMoveMapper anSocsecinfoMapper;

    // 其他关联表Mapper
    @Autowired
    private EImPrmtaltDataMoveMapper eImPrmtaltMapper;
    @Autowired
    private EOtNprmtaltDataMoveMapper eOtNprmtaltMapper;
    @Autowired
    private EImInvprodetailDataMoveMapper eImInvprodetailMapper;
    @Autowired
    private EImInvactdetailDataMoveMapper eImInvactdetailMapper;
    @Autowired
    private EImIppldgaltDataMoveMapper eImIppldgaltMapper;
    @Autowired
    private EImCasaltDataMoveMapper eImCasaltMapper;
    @Autowired
    private CasePubNdocDataMoveMapper casePubNdocMapper;
    @Autowired
    private CasePubNalterDataMoveMapper casePubNalterMapper;
    @Autowired
    private EOtNcasaltDataMoveMapper eOtNcasaltMapper;

    // 基础数据输出目录  /data/upload
//    private final String BASE_OUTPUT_DIR = "D:\\data";
    private final String BASE_OUTPUT_DIR = "/data/upload";
    @Value("${forest.variables.fileUpload.appform}")
    private String appform;


    /**
     * 构建企业专用的输出目录路径
     * @param uniscid 企业统一社会信用代码
     * @return 企业专用目录路径
     */
    private String buildEnterpriseOutputDir(String uniscid) {
        String currentDate = DateUtil.format(new Date(), "yyyyMMdd");
        return BASE_OUTPUT_DIR + File.separator + currentDate + File.separator + uniscid;
    }

    /**
     * 从 AICRI.E_BASEINFO 表查询企业基本信息
     * @param pripid 主体身份代码
     * @return 企业基本信息
     */
    private FileUploadRecord getEnterpriseBaseInfo(String pripid) {
        try {
            FileUploadRecord record = fileUploadRecordMapper.selectEntBaseInfoByPripid(pripid);
            if (record != null) {
                log.info("从 AICRI.E_BASEINFO 查询到企业信息：PRIPID={}, UNISCID={}, ENTNAME={}",
                    pripid, record.getUniscid(), record.getEntname());
                return record;
            } else {
                log.warn("未从 AICRI.E_BASEINFO 查询到企业信息，PRIPID={}", pripid);
                return null;
            }
        } catch (Exception e) {
            log.error("查询企业基本信息时发生错误，PRIPID={}", pripid, e);
            return null;
        }
    }



    /**
     * 记录文件上传结果（包含三个阶段记录）
     * @param pripid 主体身份代码
     * @param filePath 文件完整路径
     * @param isSuccess 是否成功（Y=成功，N=失败）
     * @param processRecord 流程记录信息
     * @param reconciliationPar 对账参数（JSON字符串形式）
     * @return 记录是否成功
     */
    private boolean recordFileUploadResult(String pripid, String filePath, String isSuccess, String processRecord, String reconciliationPar, String moveOutId) {
        try {
            // 查询企业基本信息

            QueryWrapper<EBaseInfo> eBaseInfoWrapper = new QueryWrapper<>();
            eBaseInfoWrapper.eq("PRIPID", pripid);
            List<EBaseInfo> eBaseInfoList = eBaseInfoMapper.selectList(eBaseInfoWrapper);

//            FileUploadRecord entBaseInfo = getEnterpriseBaseInfo(pripid);
            if (eBaseInfoList == null) {
                log.error("无法查询企业基本信息，无法记录文件上传结果，PRIPID={}, 文件路径={}", pripid, filePath);
                return false;
            }
            EBaseInfo entBaseInfo = eBaseInfoList.get(0);
            // 创建上传记录
            FileUploadRecord uploadRecord = new FileUploadRecord();
            uploadRecord.setId(UUID.randomUUID().toString().replace("-", ""));
            uploadRecord.setPripid(pripid);
            uploadRecord.setUniscid(entBaseInfo.getUniscid());
            uploadRecord.setEntname(entBaseInfo.getEntname());
            uploadRecord.setRegno(entBaseInfo.getRegno());
            uploadRecord.setUploadDir(filePath);
            uploadRecord.setMigrationType(1); // 数据迁出
            uploadRecord.setProcessRecord(processRecord);
            uploadRecord.setReconciliationPar(reconciliationPar);
            uploadRecord.setMoutId(moveOutId);

            Timestamp currentTime = new Timestamp(System.currentTimeMillis());
            uploadRecord.setCreateTime(currentTime);
            uploadRecord.setUpdateTime(currentTime);
            uploadRecord.setIsyn(isSuccess);

            QueryWrapper<FileUploadRecord> eImPermitWrapper = new QueryWrapper<>();
            eImPermitWrapper.eq("MOUT_ID", moveOutId);
            List<FileUploadRecord> fileUploadRecordList = fileUploadRecordMapper.selectList(eImPermitWrapper);

            if (fileUploadRecordList.size() > 0) {
                uploadRecord.setId(fileUploadRecordList.get(0).getId());
                fileUploadRecordMapper.updateById(uploadRecord);
                return true;
            }else {
                int result = fileUploadRecordMapper.insert(uploadRecord);
                if (result > 0) {
                    log.info("记录文件上传{}成功：PRIPID={}, UNISCID={}, 文件路径={}, 流程记录={}",
                            "Y".equals(isSuccess) ? "成功" : "失败", pripid, entBaseInfo.getUniscid(), filePath, processRecord);
                    return true;
                } else {
                    log.error("记录文件上传结果失败：PRIPID={}, 文件路径={}", pripid, filePath);
                    return false;
                }
            }

        } catch (Exception e) {
            log.error("记录文件上传结果时发生错误，PRIPID={}, 文件路径={}", pripid, filePath, e);
            return false;
        }
    }

    /**
     * 定时任务方法 - 每天凌晨1点执行
     */
    @Scheduled(cron = "${scheduling.cron.moveOutData}")
    public void executeMoveOutData() {
        log.info("开始执行迁出省局数据定时任务...");

        try {
            // 第一步：查询需要迁出的企业
            List<EMoveOut> moveOutList = queryMoveOutEnterprises();
            log.info("查询到{}条需要迁出的企业记录", moveOutList.size());

            if (CollUtil.isEmpty(moveOutList)) {
                log.info("没有需要迁出的企业数据，任务结束");
                return;
            }

            // 第二步：遍历企业查询所有相关数据
            int successCount = 0;
            int failureCount = 0;

            for (EMoveOut moveOut : moveOutList) {
                try {
                    // 检查企业是否已经迁出成功
                    int movedOutSuccessCount = fileUploadRecordMapper.countMoveOutSuccessByPripid(moveOut.getPripid(),moveOut.getMoutId());
                    if (movedOutSuccessCount > 0) {
                        log.info("企业PRIPID={}已经迁出成功，跳过此次迁出处理", moveOut.getPripid());
                        continue;
                    }

                    // 为每个企业创建独立的数据处理
                    Map<String, List<?>> enterpriseDataMap = new HashMap<>();
                    Map<String, Integer> enterpriseRecordCountMap = new HashMap<>();
                    //迁入地编号
                    String minareregorg = moveOut.getMinareregorg();

                    // 处理单个企业的所有数据
                    processSingleEnterprise(moveOut, enterpriseDataMap, enterpriseRecordCountMap);

                    // 如果该企业有数据，生成XML和ZIP文件
                    if (!enterpriseDataMap.isEmpty()) {
                        String uniscid = getUniscidFromEBaseInfo(enterpriseDataMap);
                        String entName = getEntNameFromEBaseInfo(enterpriseDataMap);
                        String currentDate = DateUtil.format(new Date(), "yyyyMMdd");
                        int retrySeq = 0; // 重试序号（0=无序号，1=第一次重试，以此类推）
                        int maxRetry = 10; // 最大重试次数（避免无限循环）
                        FileUploadService.FileUploadResult uploadResult = null;
                        File zipFile = null;
                        List<File> xmlFiles = null;
                        String finalZipFileName = null;

                        // 生成XML文件（仅生成一次，重复上传时复用）
                        xmlFiles = generateXmlFiles(enterpriseDataMap, uniscid);

                        // 循环重试：直到上传成功、非401错误或达到最大重试次数
                        while (retrySeq < maxRetry) {
                            // 生成带序号的文件名（0=原文件名，1=加1，以此类推）
                            finalZipFileName = uniscid + "-QYXYXX-" + currentDate + (retrySeq > 0 ? retrySeq : "") + ".zip";

                            // 生成当前序号的ZIP文件
                            zipFile = createZipFile(xmlFiles, finalZipFileName, uniscid);

                            // 校验ZIP文件是否生成成功
                            if (zipFile == null || !zipFile.exists()) {
                                log.error("企业{}生成ZIP文件失败，序号：{}，文件名：{}", uniscid, retrySeq, finalZipFileName);
                                break; // 生成失败，终止重试
                            }

                            // 上传文件到第三方
                            uploadResult = fileUploadService.uploadFile(zipFile, uniscid,minareregorg);

                            // 处理上传结果
                            if (uploadResult == null) {
                                // 接口调用异常，终止重试
                                log.error("企业{}上传接口异常，序号：{}，文件名：{}", uniscid, retrySeq, finalZipFileName);
                                break;
                            } else if ("200".equals(uploadResult.getResultCode())) {
                                // 上传成功，退出循环
                                log.info("企业{}上传成功，序号：{}，文件名：{}", uniscid, retrySeq, finalZipFileName);
                                break;
                            } else if ("401".equals(uploadResult.getResultCode())) {
                                // 401=文件名重复，删除当前ZIP文件并递增序号重试
                                log.warn("企业{}文件名重复（401），序号：{}，将重试序号：{}，文件名：{}",
                                        uniscid, retrySeq, retrySeq + 1, finalZipFileName);
                                // 删除当前重复的ZIP文件，避免占用空间
                                if (zipFile.exists()) {
                                    zipFile.delete();
                                }
                                retrySeq++; // 递增序号
                            } else {
                                // 其他错误（非401），终止重试
                                log.error("企业{}上传失败（非重复），返回码：{}，序号：{}，文件名：{}",
                                        uniscid, uploadResult.getResultCode(), retrySeq, finalZipFileName);
                                break;
                            }
                        }

                        // 上传流程结束后，处理最终结果
                        if (uploadResult != null && "200".equals(uploadResult.getResultCode()) && zipFile != null && zipFile.exists()) {
                            // 第一阶段：压缩+上传成功
                            String stage1SuccessMsg = String.format("企业%s数据压缩+上传成功，生成ZIP文件：%s", uniscid, zipFile.getAbsolutePath());
                            String processRecord1 = "压缩文件成功+上传成功：" + stage1SuccessMsg;
                            recordFileUploadResult(moveOut.getPripid(), zipFile.getAbsolutePath(), "Y", processRecord1, null, moveOut.getMoutId());
                            log.info(stage1SuccessMsg);

                            // 清理临时XML文件（上传成功后XML已无用）
                            cleanupXmlFiles(xmlFiles);

                            // 2.1阶段：调用企业上传路径接口（使用最终成功的文件名）
                            FileUploadService.RegisterInfoResult registerResult = fileUploadService.callRegisterInfoApi(uniscid, entName, minareregorg, finalZipFileName);

                            // 处理注册接口结果（保持原有逻辑）
                            if (registerResult != null && "2000".equals(registerResult.getResultCode())) {
                                String stage21SuccessMsg = String.format("企业%s上传路径注册成功：%s", uniscid, registerResult.getData());
                                String processRecord21 = "上传路径注册成功：" + stage21SuccessMsg;
                                log.info(stage21SuccessMsg);
                            } else {
                                String resultCode21 = registerResult != null ? registerResult.getResultCode() : "null";
                                String resultMsg21 = registerResult != null ? registerResult.getResultMsg() : "null";
                                String errorMsg21 = String.format("上传路径注册失败，返回码：%s，返回消息：%s", resultCode21, resultMsg21);
                                log.error("企业{}上传路径注册失败：{}", uniscid, errorMsg21);
                            }

                            // 构建对账参数
                            String reconciliationPar = buildReconciliationParams(uniscid, entName, enterpriseRecordCountMap, minareregorg);

                            // 第三阶段：调用对账接口（保持原有逻辑）
                            FileUploadService.RecordInfoResult recordResult = fileUploadService.callRecordInfoApi(uniscid, entName, enterpriseRecordCountMap, minareregorg);

                            if (recordResult != null && "2000".equals(recordResult.getResultCode())) {
                                String finalSuccessMsg = String.format("企业%s数据迁出完成：①压缩+上传成功 ②注册成功 ③对账成功", uniscid);
                                recordFileUploadResult(moveOut.getPripid(), zipFile.getAbsolutePath(), "Y", finalSuccessMsg, reconciliationPar, moveOut.getMoutId());
                                log.info("企业{}数据迁出全部完成", uniscid);
                                successCount++;
                            } else {
                                String resultCode = recordResult != null ? recordResult.getResultCode() : "null";
                                String resultMsg = recordResult != null ? recordResult.getResultMsg() : "null";
                                String errorMsg = String.format("对账失败，返回码：%s，消息：%s", resultCode, resultMsg);
                                recordFileUploadResult(moveOut.getPripid(), zipFile.getAbsolutePath(), "N", errorMsg, reconciliationPar, moveOut.getMoutId());
                                log.error("企业{}对账失败：{}", uniscid, errorMsg);
                                failureCount++;
                                continue;
                            }

                        } else {
                            // 上传失败（包括生成ZIP失败、达到最大重试次数、非401错误）
                            String failedMsg;
                            String failedPath;
                            if (zipFile != null) {
                                failedPath = zipFile.getAbsolutePath();
                                failedMsg = String.format("企业%s上传失败，最大重试次数：%d，最终文件名：%s", uniscid, maxRetry, finalZipFileName);
                            } else {
                                failedPath = buildEnterpriseOutputDir(uniscid) + File.separator + uniscid + "-QYXYXX-" + currentDate + ".zip";
                                failedMsg = String.format("企业%s压缩或上传失败，未生成有效ZIP文件", uniscid);
                            }
                            // 记录失败状态
                            recordFileUploadResult(moveOut.getPripid(), failedPath, "N", failedMsg, null, moveOut.getMoutId());
                            log.error(failedMsg);
                            // 清理临时文件（无论成功失败，最终都删除XML）
                            cleanupXmlFiles(xmlFiles);
                            // 删除最终生成的ZIP文件（如果失败且存在）
//                            if (zipFile != null && zipFile.exists()) {
//                                zipFile.delete();
//                            }
                            failureCount++;
                            continue;
                        }
                    } else {
                        log.warn("企业{}未查询到任何相关数据", moveOut.getPripid());
                    }

                } catch (Exception e) {
                    // 记录上传失败 - 在异常处理时无法直接访问enterpriseDataMap，使用UNKNOWN
                    String uniscid = "UNKNOWN";
                    try {
                        // 在异常情况下，尝试从当前企业数据中获取uniscid
                        // 由于在异常处理中，我们只能访问到当前moveOut对象，无法访问到enterpriseDataMap
                        log.debug("在异常处理中无法访问enterpriseDataMap，使用UNKNOWN作为uniscid");
                    } catch (Exception ex) {
                        log.debug("获取企业uniscid失败，使用UNKNOWN", ex);
                    }

                    String failedPath = buildEnterpriseOutputDir(uniscid) + File.separator + uniscid + "-QYXYXX-" + DateUtil.format(new Date(), "yyyyMMdd") + ".zip";

                    // 错误信息处理，限制2000字符
                    String errorMsg = e.getMessage() != null && e.getMessage().length() <= 2000 ?
                        e.getMessage() : "数据处理失败，具体错误信息超过2000字符限制";
                    String processRecord = String.format("异常处理失败：企业%s数据处理失败，错误：%s", uniscid, errorMsg);

                    // 记录异常失败状态
                    recordFileUploadResult(moveOut.getPripid(), failedPath, "N", processRecord, null,moveOut.getMoutId());

                    failureCount++;
                    log.error("处理企业{}时发生错误", moveOut.getPripid(), e);
                }
            }

            log.info("迁出数据任务执行完成，成功处理{}家企业，失败{}家", successCount, failureCount);


        } catch (Exception e) {
            log.error("迁出省局数据定时任务执行失败", e);
        }
    }

    /**
     * 查询需要迁出的企业（一周内的数据）
     */
    private List<EMoveOut> queryMoveOutEnterprises() {
        QueryWrapper<EMoveOut> queryWrapper = new QueryWrapper<>();

        // 设置日期为今年的10月30日 MOVE_TYPE
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.MONTH, Calendar.OCTOBER); // 10月（Calendar.OCTOBER = 9）
        cal.set(Calendar.DAY_OF_MONTH, 30);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);

        Date october30 = cal.getTime();
        Timestamp october30Timestamp = new Timestamp(october30.getTime());

//        queryWrapper.ge("MOUTDATE", october30Timestamp);
        queryWrapper.eq("MOVE_TYPE", 7);
//        queryWrapper.eq("PRIPID", "440112112012024101200080");

        return eMoveOutMapper.selectList(queryWrapper);
    }
    /**
     * 处理单个企业的所有相关数据
     */
    private void processSingleEnterprise(EMoveOut moveOut, Map<String, List<?>> allDataMap, Map<String, Integer> recordCountMap) {
        String pripid = moveOut.getPripid();
        log.debug("开始处理企业数据，PRIPID：{}", pripid);

        // 按pripid查询主要企业信息表
        queryDataByPripid(pripid, allDataMap, recordCountMap);

        // 查询E_BASEINFO表获取ANCHEID，然后查询AN相关表
        List<AnBaseinfo> anBaseinfoList = (List<AnBaseinfo>) allDataMap.getOrDefault("AN_BASEINFO", new ArrayList<>());
        if (!anBaseinfoList.isEmpty()) {
            for (AnBaseinfo anBaseinfo : anBaseinfoList) {
                String ancheid = anBaseinfo.getAncheid(); // 假设ANCHEID使用PRIPID
                queryAnRelatedData(ancheid, allDataMap, recordCountMap);
            }

        }

        // 按LICID查询相关表
        queryDataByLicid(allDataMap, recordCountMap);

        // 按INVID查询相关表
        queryDataByInvid(allDataMap, recordCountMap);

        // 按PLEID查询相关表
        queryDataByPleid(allDataMap, recordCountMap);

        // 按CASEID查询相关表
        queryDataByCaseid(allDataMap, recordCountMap);
    }

    /**
     * 按pripid查询主要企业信息表
     */
    private void queryDataByPripid(String pripid, Map<String, List<?>> allDataMap, Map<String, Integer> recordCountMap) {
        log.debug("按PRIPID {} 查询主要企业信息表", pripid);

        QueryWrapper<EBaseInfo> eBaseInfoWrapper = new QueryWrapper<>();
        eBaseInfoWrapper.eq("PRIPID", pripid);
        List<EBaseInfo> eBaseInfoList = eBaseInfoMapper.selectList(eBaseInfoWrapper);
        addDataToMap("E_BASEINFO", eBaseInfoList, allDataMap, recordCountMap);

        QueryWrapper<EAlterRecoder> eAlterRecoderWrapper = new QueryWrapper<>();
        eAlterRecoderWrapper.eq("PRIPID", pripid);
        List<EAlterRecoder> eAlterRecoderList = eAlterRecoderMapper.selectList(eAlterRecoderWrapper);
        addDataToMap("E_ALTER_RECODER", eAlterRecoderList, allDataMap, recordCountMap);

        QueryWrapper<EImPermit> eImPermitWrapper = new QueryWrapper<>();
        eImPermitWrapper.eq("PRIPID", pripid);
        List<EImPermit> eImPermitList = eImPermitMapper.selectList(eImPermitWrapper);
        addDataToMap("E_IM_PERMIT", eImPermitList, allDataMap, recordCountMap);

        QueryWrapper<EOtSpotcheck> eOtSpotcheckWrapper = new QueryWrapper<>();
        eOtSpotcheckWrapper.eq("PRIPID", pripid);
        List<EOtSpotcheck> eOtSpotcheckList = eOtSpotcheckMapper.selectList(eOtSpotcheckWrapper);
        addDataToMap("E_OT_SPOTCHECK", eOtSpotcheckList, allDataMap, recordCountMap);

        QueryWrapper<EPubSpotcheck> ePubSpotcheckWrapper = new QueryWrapper<>();
        ePubSpotcheckWrapper.eq("PRIPID", pripid);
        List<EPubSpotcheck> ePubSpotcheckList = ePubSpotcheckMapper.selectList(ePubSpotcheckWrapper);
        addDataToMap("E_PUB_SPOTCHECK", ePubSpotcheckList, allDataMap, recordCountMap);

        QueryWrapper<DrRaninsres> drRaninsresWrapper = new QueryWrapper<>();
        drRaninsresWrapper.eq("PRIPID", pripid);
        List<DrRaninsres> drRaninsresList = drRaninsresMapper.selectList(drRaninsresWrapper);
        addDataToMap("DR_RANINSRES", drRaninsresList, allDataMap, recordCountMap);

        QueryWrapper<AoOpAnomaly> aoOpAnomalyWrapper = new QueryWrapper<>();
        aoOpAnomalyWrapper.eq("PRIPID", pripid);
        List<AoOpAnomaly> aoOpAnomalyList = aoOpAnomalyMapper.selectList(aoOpAnomalyWrapper);
        addDataToMap("AO_OPANOMALY", aoOpAnomalyList, allDataMap, recordCountMap);

        QueryWrapper<AoOpaDetail> aoOpaDetailWrapper = new QueryWrapper<>();
        aoOpaDetailWrapper.eq("PRIPID", pripid);
        List<AoOpaDetail> aoOpaDetailList = aoOpaDetailMapper.selectList(aoOpaDetailWrapper);
        addDataToMap("AO_OPA_DETAIL", aoOpaDetailList, allDataMap, recordCountMap);

        QueryWrapper<AoOpAnomalyInv> aoOpAnomalyInvWrapper = new QueryWrapper<>();
        aoOpAnomalyInvWrapper.eq("PRIPID", pripid);
        List<AoOpAnomalyInv> aoOpAnomalyInvList = aoOpAnomalyInvMapper.selectList(aoOpAnomalyInvWrapper);
        addDataToMap("AO_OPANOMALY_INV", aoOpAnomalyInvList, allDataMap, recordCountMap);

        QueryWrapper<AnBaseinfo> anBaseinfoWrapper = new QueryWrapper<>();
        anBaseinfoWrapper.eq("PRIPID", pripid);
        List<AnBaseinfo> anBaseinfoList = anBaseinfoMapper.selectList(anBaseinfoWrapper);
        addDataToMap("AN_BASEINFO", anBaseinfoList, allDataMap, recordCountMap);

        QueryWrapper<EImInvestment> eImInvestmentWrapper = new QueryWrapper<>();
        eImInvestmentWrapper.eq("PRIPID", pripid);
        List<EImInvestment> eImInvestmentList = eImInvestmentMapper.selectList(eImInvestmentWrapper);
        addDataToMap("E_IM_INVESTMENT", eImInvestmentList, allDataMap, recordCountMap);

        QueryWrapper<EImInvupdate> eImInvupdateWrapper = new QueryWrapper<>();
        eImInvupdateWrapper.eq("PRIPID", pripid);
        List<EImInvupdate> eImInvupdateList = eImInvupdateMapper.selectList(eImInvupdateWrapper);
        addDataToMap("E_IM_INVUPDATE", eImInvupdateList, allDataMap, recordCountMap);

        QueryWrapper<CaseCreInformation> caseCreInformationWrapper = new QueryWrapper<>();
        caseCreInformationWrapper.eq("PRIPID", pripid);
        List<CaseCreInformation> caseCreInformationList = caseCreInformationMapper.selectList(caseCreInformationWrapper);
        addDataToMap("CASE_CRE_INFORMATION", caseCreInformationList, allDataMap, recordCountMap);

        QueryWrapper<EImIppldg> eImIppldgWrapper = new QueryWrapper<>();
        eImIppldgWrapper.eq("PRIPID", pripid);
        List<EImIppldg> eImIppldgList = eImIppldgMapper.selectList(eImIppldgWrapper);
        addDataToMap("E_IM_IPPLDG", eImIppldgList, allDataMap, recordCountMap);

        QueryWrapper<EImCase> eImCaseWrapper = new QueryWrapper<>();
        eImCaseWrapper.eq("PRIPID", pripid);
        List<EImCase> eImCaseList = eImCaseMapper.selectList(eImCaseWrapper);
        addDataToMap("E_IM_CASE", eImCaseList, allDataMap, recordCountMap);

        QueryWrapper<EImInvsralt> eImInvsraltWrapper = new QueryWrapper<>();
        eImInvsraltWrapper.eq("PRIPID", pripid);
        List<EImInvsralt> eImInvsraltList = eImInvsraltMapper.selectList(eImInvsraltWrapper);
        addDataToMap("E_IM_INVSRALT", eImInvsraltList, allDataMap, recordCountMap);

        QueryWrapper<ELiIlldishonesty> eLiIlldishonestyWrapper = new QueryWrapper<>();
        eLiIlldishonestyWrapper.eq("PRIPID", pripid);
        List<ELiIlldishonesty> eLiIlldishonestyList = eLiIlldishonestyMapper.selectList(eLiIlldishonestyWrapper);
        addDataToMap("E_LI_ILLDISHONESTY", eLiIlldishonestyList, allDataMap, recordCountMap);

        QueryWrapper<ELiIlldisdetail> eLiIlldisdetailWrapper = new QueryWrapper<>();
        eLiIlldisdetailWrapper.eq("PRIPID", pripid);
        List<ELiIlldisdetail> eLiIlldisdetailList = eLiIlldisdetailMapper.selectList(eLiIlldisdetailWrapper);
        addDataToMap("E_LI_ILLDISDETAIL", eLiIlldisdetailList, allDataMap, recordCountMap);

        QueryWrapper<CasePubNbaseinfo> casePubNbaseinfoWrapper = new QueryWrapper<>();
        casePubNbaseinfoWrapper.eq("PRIPID", pripid);
        List<CasePubNbaseinfo> casePubNbaseinfoList = casePubNbaseinfoMapper.selectList(casePubNbaseinfoWrapper);
        addDataToMap("CASE_PUB_NBASEINFO", casePubNbaseinfoList, allDataMap, recordCountMap);

        QueryWrapper<EOtNpermit> eOtNpermitWrapper = new QueryWrapper<>();
        eOtNpermitWrapper.eq("PRIPID", pripid);
        List<EOtNpermit> eOtNpermitList = eOtNpermitMapper.selectList(eOtNpermitWrapper);
        addDataToMap("E_OT_NPERMIT", eOtNpermitList, allDataMap, recordCountMap);

        QueryWrapper<EOtNcase> eOtNcaseWrapper = new QueryWrapper<>();
        eOtNcaseWrapper.eq("PRIPID", pripid);
        try {
            List<EOtNcase> eOtNcaseList = eOtNcaseMapper.selectList(eOtNcaseWrapper);
            addDataToMap("E_OT_NCASE", eOtNcaseList, allDataMap, recordCountMap);
        } catch (Exception e) {
            log.error("查询表 E_OT_NCASE 时发生错误", e);
        }
    }

    /**
     * 将数据添加到Map中（包含空表）
     */
    private <T> void addDataToMap(String tableName, List<T> dataList, Map<String, List<?>> allDataMap, Map<String, Integer> recordCountMap) {
        // 确保表名被添加到Map中，即使数据为空
        List<Object> existingData = (List<Object>) allDataMap.getOrDefault(tableName, new ArrayList<>());

        if (CollUtil.isNotEmpty(dataList)) {
            // 创建新的数据列表并添加到现有数据中
            List<Object> newDataList = new ArrayList<>(dataList);
            existingData.addAll(newDataList);
            allDataMap.put(tableName, existingData);

            int currentCount = recordCountMap.getOrDefault(tableName, 0);
            recordCountMap.put(tableName, currentCount + dataList.size());

            log.debug("表 {} 添加 {} 条记录，累计 {} 条", tableName, dataList.size(), recordCountMap.get(tableName));
        } else {
            // 确保空表也被记录
            if (!allDataMap.containsKey(tableName)) {
                allDataMap.put(tableName, existingData);
                recordCountMap.put(tableName, 0);
                log.debug("表 {} 无数据，但仍记录为空表", tableName);
            }
        }
    }

    /**
     * 按ANCHEID查询AN相关表
     */
    private void queryAnRelatedData(String ancheid, Map<String, List<?>> allDataMap, Map<String, Integer> recordCountMap) {
        log.debug("按ANCHEID {} 查询AN相关表", ancheid);

        QueryWrapper<AnSubcapital> anSubcapitalWrapper = new QueryWrapper<>();
        anSubcapitalWrapper.eq("ANCHEID", ancheid);
        List<AnSubcapital> anSubcapitalList = anSubcapitalMapper.selectList(anSubcapitalWrapper);
        addDataToMap("AN_SUBCAPITAL", anSubcapitalList, allDataMap, recordCountMap);

        QueryWrapper<AnForinvestment> anForinvestmentWrapper = new QueryWrapper<>();
        anForinvestmentWrapper.eq("ANCHEID", ancheid);
        List<AnForinvestment> anForinvestmentList = anForinvestmentMapper.selectList(anForinvestmentWrapper);
        addDataToMap("AN_FORINVESTMENT", anForinvestmentList, allDataMap, recordCountMap);

        QueryWrapper<AnWebsiteinfo> anWebsiteinfoWrapper = new QueryWrapper<>();
        anWebsiteinfoWrapper.eq("ANCHEID", ancheid);
        List<AnWebsiteinfo> anWebsiteinfoList = anWebsiteinfoMapper.selectList(anWebsiteinfoWrapper);
        addDataToMap("AN_WEBSITEINFO", anWebsiteinfoList, allDataMap, recordCountMap);

        QueryWrapper<AnAlterstockinfo> anAlterstockinfoWrapper = new QueryWrapper<>();
        anAlterstockinfoWrapper.eq("ANCHEID", ancheid);
        List<AnAlterstockinfo> anAlterstockinfoList = anAlterstockinfoMapper.selectList(anAlterstockinfoWrapper);
        addDataToMap("AN_ALTERSTOCKINFO", anAlterstockinfoList, allDataMap, recordCountMap);

        QueryWrapper<AnForguaranteeinfo> anForguaranteeinfoWrapper = new QueryWrapper<>();
        anForguaranteeinfoWrapper.eq("ANCHEID", ancheid);
        List<AnForguaranteeinfo> anForguaranteeinfoList = anForguaranteeinfoMapper.selectList(anForguaranteeinfoWrapper);
        addDataToMap("AN_FORGUARANTEEINFO", anForguaranteeinfoList, allDataMap, recordCountMap);

        QueryWrapper<AnUpdateinfo> anUpdateinfoWrapper = new QueryWrapper<>();
        anUpdateinfoWrapper.eq("ANCHEID", ancheid);
        List<AnUpdateinfo> anUpdateinfoList = anUpdateinfoMapper.selectList(anUpdateinfoWrapper);
        addDataToMap("AN_UPDATEINFO", anUpdateinfoList, allDataMap, recordCountMap);

        QueryWrapper<AnSupBaseinfo> anSupBaseinfoWrapper = new QueryWrapper<>();
        anSupBaseinfoWrapper.eq("ANCHEID", ancheid);
        List<AnSupBaseinfo> anSupBaseinfoList = anSupBaseinfoMapper.selectList(anSupBaseinfoWrapper);
        addDataToMap("AN_SUP_BASEINFO", anSupBaseinfoList, allDataMap, recordCountMap);

        QueryWrapper<AnSocsecinfo> anSocsecinfoWrapper = new QueryWrapper<>();
        anSocsecinfoWrapper.eq("ANCHEID", ancheid);
        List<AnSocsecinfo> anSocsecinfoList = anSocsecinfoMapper.selectList(anSocsecinfoWrapper);
        addDataToMap("AN_SOCSECINFO", anSocsecinfoList, allDataMap, recordCountMap);
    }

    /**
     * 按LICID查询相关表
     */
    private void queryDataByLicid(Map<String, List<?>> allDataMap, Map<String, Integer> recordCountMap) {
        // 从E_IM_PERMIT获取LICID查询E_IM_PRMTALT
        List<EImPermit> eImPermitList = (List<EImPermit>) allDataMap.getOrDefault("E_IM_PERMIT", new ArrayList<>());
        for (EImPermit permit : eImPermitList) {
            String licid = permit.getLicid();
            if (StrUtil.isNotBlank(licid)) {
                QueryWrapper<EImPrmtalt> eImPrmtaltWrapper = new QueryWrapper<>();
                eImPrmtaltWrapper.eq("LICID", licid);
                List<EImPrmtalt> eImPrmtaltList = eImPrmtaltMapper.selectList(eImPrmtaltWrapper);
                addDataToMap("E_IM_PRMTALT", eImPrmtaltList, allDataMap, recordCountMap);
            }
        }

        // 从E_OT_NPERMIT获取LICID查询E_OT_NPRMTALT
        List<EOtNpermit> eOtNpermitList = (List<EOtNpermit>) allDataMap.getOrDefault("E_OT_NPERMIT", new ArrayList<>());
        for (EOtNpermit permit : eOtNpermitList) {
            String licid = permit.getLicid();
            if (StrUtil.isNotBlank(licid)) {
                QueryWrapper<EOtNprmtalt> eOtNprmtaltWrapper = new QueryWrapper<>();
                eOtNprmtaltWrapper.eq("LICID", licid);
                List<EOtNprmtalt> eOtNprmtaltList = eOtNprmtaltMapper.selectList(eOtNprmtaltWrapper);
                addDataToMap("E_OT_NPRMTALT", eOtNprmtaltList, allDataMap, recordCountMap);
            }
        }
    }

    /**
     * 按INVID查询相关表
     */
    private void queryDataByInvid(Map<String, List<?>> allDataMap, Map<String, Integer> recordCountMap) {
        // 从E_IM_INVESTMENT获取INVID查询相关表
        List<EImInvestment> eImInvestmentList = (List<EImInvestment>) allDataMap.getOrDefault("E_IM_INVESTMENT", new ArrayList<>());
        for (EImInvestment investment : eImInvestmentList) {
            String invid = investment.getInvid();
            if (StrUtil.isNotBlank(invid)) {
                QueryWrapper<EImInvprodetail> eImInvprodetailWrapper = new QueryWrapper<>();
                eImInvprodetailWrapper.eq("INVID", invid);
                List<EImInvprodetail> eImInvprodetailList = eImInvprodetailMapper.selectList(eImInvprodetailWrapper);
                addDataToMap("E_IM_INVPRODETAIL", eImInvprodetailList, allDataMap, recordCountMap);

                QueryWrapper<EImInvactdetail> eImInvactdetailWrapper = new QueryWrapper<>();
                eImInvactdetailWrapper.eq("INVID", invid);
                List<EImInvactdetail> eImInvactdetailList = eImInvactdetailMapper.selectList(eImInvactdetailWrapper);
                addDataToMap("E_IM_INVACTDETAIL", eImInvactdetailList, allDataMap, recordCountMap);
            }
        }
    }

    /**
     * 按PLEID查询相关表
     */
    private void queryDataByPleid(Map<String, List<?>> allDataMap, Map<String, Integer> recordCountMap) {
        // 从E_IM_IPPLDG获取PLEID查询E_IM_IPPLDGALT
        List<EImIppldg> eImIppldgList = (List<EImIppldg>) allDataMap.getOrDefault("E_IM_IPPLDG", new ArrayList<>());
        for (EImIppldg ippldg : eImIppldgList) {
            String pleid = ippldg.getPleid();
            if (StrUtil.isNotBlank(pleid)) {
                QueryWrapper<EImIppldgalt> eImIppldgaltWrapper = new QueryWrapper<>();
                eImIppldgaltWrapper.eq("PLEID", pleid);
                List<EImIppldgalt> eImIppldgaltList = eImIppldgaltMapper.selectList(eImIppldgaltWrapper);
                addDataToMap("E_IM_IPPLDGALT", eImIppldgaltList, allDataMap, recordCountMap);
            }
        }
    }

    /**
     * 按CASEID查询相关表
     */
    private void queryDataByCaseid(Map<String, List<?>> allDataMap, Map<String, Integer> recordCountMap) {
        // 从E_IM_CASE获取CASEID查询E_IM_CASALT
        List<EImCase> eImCaseList = (List<EImCase>) allDataMap.getOrDefault("E_IM_CASE", new ArrayList<>());
        for (EImCase caseInfo : eImCaseList) {
            String caseid = caseInfo.getCaseid();
            if (StrUtil.isNotBlank(caseid)) {
                QueryWrapper<EImCasalt> eImCasaltWrapper = new QueryWrapper<>();
                eImCasaltWrapper.eq("CASEID", caseid);
                List<EImCasalt> eImCasaltList = eImCasaltMapper.selectList(eImCasaltWrapper);
                addDataToMap("E_IM_CASALT", eImCasaltList, allDataMap, recordCountMap);
            }
        }

        // 从CASE_PUB_NBASEINFO获取CASEID查询相关表
        List<CasePubNbaseinfo> casePubNbaseinfoList = (List<CasePubNbaseinfo>) allDataMap.getOrDefault("CASE_PUB_NBASEINFO", new ArrayList<>());
        for (CasePubNbaseinfo caseInfo : casePubNbaseinfoList) {
            String caseid = caseInfo.getCaseid();
            if (StrUtil.isNotBlank(caseid)) {
                QueryWrapper<CasePubNdoc> casePubNdocWrapper = new QueryWrapper<>();
                casePubNdocWrapper.eq("CASEID", caseid);
                List<CasePubNdoc> casePubNdocList = casePubNdocMapper.selectList(casePubNdocWrapper);
                addDataToMap("CASE_PUB_NDOC", casePubNdocList, allDataMap, recordCountMap);

                QueryWrapper<CasePubNalter> casePubNalterWrapper = new QueryWrapper<>();
                casePubNalterWrapper.eq("CASEID", caseid);
                List<CasePubNalter> casePubNalterList = casePubNalterMapper.selectList(casePubNalterWrapper);
                addDataToMap("CASE_PUB_NALTER", casePubNalterList, allDataMap, recordCountMap);
            }
        }

        // 从E_OT_NCASE获取CASEID查询E_OT_NCASALT
        List<EOtNcase> eOtNcaseList = (List<EOtNcase>) allDataMap.getOrDefault("E_OT_NCASE", new ArrayList<>());
        for (EOtNcase caseInfo : eOtNcaseList) {
            String caseid = caseInfo.getCaseid();
            if (StrUtil.isNotBlank(caseid)) {
                QueryWrapper<EOtNcasalt> eOtNcasaltWrapper = new QueryWrapper<>();
                eOtNcasaltWrapper.eq("CASEID", caseid);
                List<EOtNcasalt> eOtNcasaltList = eOtNcasaltMapper.selectList(eOtNcasaltWrapper);
                addDataToMap("E_OT_NCASALT", eOtNcasaltList, allDataMap, recordCountMap);
            }
        }
    }

    /**
     * 安全执行查询，异常时继续执行
     */
    private <T> void safeQuery(String tableName, Supplier<List<T>> querySupplier, Map<String, List<?>> allDataMap, Map<String, Integer> recordCountMap) {
        try {
            List<T> result = querySupplier.get();
            if (CollUtil.isNotEmpty(result)) {
                addDataToMap(tableName, result, allDataMap, recordCountMap);
            }
        } catch (Exception e) {
            log.error("查询表 {} 时发生错误", tableName, e);
        }
    }

    /**
     * 从E_BASEINFO获取UNISCID
     */
    private String getUniscidFromEBaseInfo(Map<String, List<?>> allDataMap) {
        List<EBaseInfo> eBaseInfoList = (List<EBaseInfo>) allDataMap.get("E_BASEINFO");
        if (CollUtil.isNotEmpty(eBaseInfoList)) {
            return eBaseInfoList.get(0).getUniscid();
        }
        return "UNKNOWN";
    }

    /**
     * 从E_BASEINFO获取企业名称
     */
    private String getEntNameFromEBaseInfo(Map<String, List<?>> allDataMap) {
        List<EBaseInfo> eBaseInfoList = (List<EBaseInfo>) allDataMap.get("E_BASEINFO");
        if (CollUtil.isNotEmpty(eBaseInfoList)) {
            return eBaseInfoList.get(0).getEntname();
        }
        return "UNKNOWN";
    }

    /**
     * 获取所有38张表的名称列表
     */
    private Set<String> getAllTableNames() {
        Set<String> tableNames = new HashSet<>();

        // 主要企业信息表（按PRIPID查询）
        tableNames.add("E_BASEINFO");
        tableNames.add("E_ALTER_RECODER");
        tableNames.add("E_IM_PERMIT");
        tableNames.add("E_OT_SPOTCHECK");
        tableNames.add("E_PUB_SPOTCHECK");
        tableNames.add("DR_RANINSRES");
        tableNames.add("AO_OPANOMALY");
        tableNames.add("AO_OPA_DETAIL");
        tableNames.add("AO_OPANOMALY_INV");
        tableNames.add("AN_BASEINFO");
        tableNames.add("E_IM_INVESTMENT");
        tableNames.add("E_IM_INVUPDATE");
        tableNames.add("CASE_CRE_INFORMATION");
        tableNames.add("E_IM_IPPLDG");
        tableNames.add("E_IM_CASE");
        tableNames.add("E_IM_INVSRALT");
        tableNames.add("E_LI_ILLDISHONESTY");
        tableNames.add("E_LI_ILLDISDETAIL");
        tableNames.add("CASE_PUB_NBASEINFO");
        tableNames.add("E_OT_NPERMIT");
        tableNames.add("E_OT_NCASE");

        // AN相关表（按ANCHEID查询）
        tableNames.add("AN_SUBCAPITAL");
        tableNames.add("AN_FORINVESTMENT");
        tableNames.add("AN_WEBSITEINFO");
        tableNames.add("AN_ALTERSTOCKINFO");
        tableNames.add("AN_FORGUARANTEEINFO");
        tableNames.add("AN_UPDATEINFO");
        tableNames.add("AN_SUP_BASEINFO");
        tableNames.add("AN_SOCSECINFO");

        // 按LICID查询的相关表
        tableNames.add("E_IM_PRMTALT");
        tableNames.add("E_OT_NPRMTALT");

        // 按INVID查询的相关表
        tableNames.add("E_IM_INVPRODETAIL");
        tableNames.add("E_IM_INVACTDETAIL");

        // 按PLEID查询的相关表
        tableNames.add("E_IM_IPPLDGALT");

        // 按CASEID查询的相关表
        tableNames.add("E_IM_CASALT");
        tableNames.add("CASE_PUB_NDOC");
        tableNames.add("CASE_PUB_NALTER");
        tableNames.add("E_OT_NCASALT");

        return tableNames;
    }

    /**
     * 生成XML文件（包含空表）
     */
    private List<File> generateXmlFiles(Map<String, List<?>> allDataMap, String uniscid) {
        List<File> xmlFiles = new ArrayList<>();

        // 构建38张表的完整列表，确保所有表都被处理
        Set<String> allTables = getAllTableNames();

        // 构建企业专用的输出目录
        String outputDir = buildEnterpriseOutputDir(uniscid);
        File enterpriseDir = new File(outputDir);
        if (!enterpriseDir.exists()) {
            enterpriseDir.mkdirs();
        }

        log.info("为企业{}创建输出目录：{}", uniscid, outputDir);

        // 处理所有38张表
        for (String tableName : allTables) {
            List<?> dataList = allDataMap.getOrDefault(tableName, new ArrayList<>());

            File xmlFile = generateXmlFile(tableName, dataList, outputDir);
            if (xmlFile != null) {
                xmlFiles.add(xmlFile);
            }
        }

        log.info("为企业{}生成{}个XML文件", uniscid, xmlFiles.size());
        return xmlFiles;
    }

    /**
     * 生成单个XML文件（包含空表处理）
     */
    private File generateXmlFile(String tableName, List<?> dataList, String outputDir) {
        try {
            StringBuilder xmlBuilder = new StringBuilder();

            // 调试：记录数据列表状态
            log.debug("生成XML文件表{}，数据列表大小: {}, 是否为空: {}",
                     tableName, dataList.size(), CollUtil.isEmpty(dataList));

            // XML声明和根元素
            xmlBuilder.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
            xmlBuilder.append("<rows>\n");

            // 如果有数据，生成row元素
            if (CollUtil.isNotEmpty(dataList)) {
                log.debug("表{}包含{}条数据，开始生成row元素", tableName, dataList.size());
                for (Object data : dataList) {
                    // 使用反射获取对象的所有字段
                    Map<String, Object> fieldMap = convertObjectToMap(data);

                    // 检查对象是否有任何非null字段
                    boolean hasNonNullFields = fieldMap.values().stream()
                        .anyMatch(Objects::nonNull);

                    // 只有当对象有非null字段时才生成row
                    if (hasNonNullFields) {
                        xmlBuilder.append("  <row>\n");

                        for (Map.Entry<String, Object> entry : fieldMap.entrySet()) {
                            String fieldName = entry.getKey();
                            Object value = entry.getValue();

                            if (value != null) {
                                // 有值的情况：完整的XML标签
                                xmlBuilder.append("    <")
                                       .append(fieldName)
                                       .append(">")
                                       .append(escapeXml(value.toString()))
                                       .append("</")
                                       .append(fieldName)
                                       .append(">\n");
                            } else {
                                // 空值的情况：自闭合标签格式 <字段名称/>
                                xmlBuilder.append("    <")
                                       .append(fieldName)
                                       .append("/>\n");
                            }
                        }

                        xmlBuilder.append("  </row>\n");
                    } else {
                        log.debug("表{}的某个对象所有字段都为null，跳过生成row", tableName);
                    }
                }
            }
            // 如果没有数据，直接关闭根元素（生成空表XML）

            // 关闭根元素
            xmlBuilder.append("</rows>");

            // 保存到文件
            String fileName = tableName + ".xml";
            File xmlFile = new File(outputDir, fileName);
            FileUtil.writeString(xmlBuilder.toString(), xmlFile, StandardCharsets.UTF_8);

            log.info("生成XML文件：{}，包含{}条记录", xmlFile.getAbsolutePath(), dataList.size());

            // 调试：打印XML内容的前500字符用于验证格式
            if (log.isDebugEnabled() && dataList.size() > 0) {
                String xmlPreview = xmlBuilder.length() > 500 ?
                    xmlBuilder.substring(0, 500) + "..." : xmlBuilder.toString();
                log.debug("XML内容预览（表{}）: {}", tableName, xmlPreview);
            }

            return xmlFile;

        } catch (Exception e) {
            log.error("生成XML文件 {} 时发生错误", tableName, e);
            return null;
        }
    }

    /**
     * XML特殊字符转义
     */
    private String escapeXml(String input) {
        if (input == null) {
            return "";
        }
        return input.replace("&", "&amp;")
                   .replace("<", "&lt;")
                   .replace(">", "&gt;")
                   .replace("\"", "&quot;")
                   .replace("'", "&apos;");
    }

    /**
     * 对象转换为Map（使用反射机制）
     */
    private Map<String, Object> convertObjectToMap(Object obj) {
        Map<String, Object> map = new HashMap<>();
        if (obj == null) {
            return map;
        }

        try {
            Class<?> clazz = obj.getClass();
            Field[] fields = clazz.getDeclaredFields();

            for (Field field : fields) {
                field.setAccessible(true);
                String fieldName = field.getName();

                // 跳过serialVersionUID字段
                if ("serialVersionUID".equals(fieldName)) {
                    continue;
                }

                Object value = field.get(obj);

                // 处理日期类型
                if (value != null && (value instanceof Date || value instanceof java.sql.Date ||
                    value instanceof Timestamp)) {
                    value = DateUtil.format((Date) value, "yyyy-MM-dd HH:mm:ss");
                }
                // 处理BigDecimal类型
                else if (value != null && value instanceof java.math.BigDecimal) {
                    value = value.toString();
                }

                // 获取字段上的TableField注解的值作为key
                String key = fieldName.toUpperCase();
                try {
                    com.baomidou.mybatisplus.annotation.TableField tableField =
                        field.getAnnotation(com.baomidou.mybatisplus.annotation.TableField.class);
                    if (tableField != null && StrUtil.isNotBlank(tableField.value())) {
                        key = tableField.value();
                    }
                } catch (Exception e) {
                    // 忽略注解读取异常，使用字段名
                }

                map.put(key, value);
            }
        } catch (Exception e) {
            log.error("对象转换Map时发生错误：{}", e.getMessage(), e);
        }
        return map;
    }

    /**
     * 创建ZIP文件
     */
    private File createZipFile(List<File> xmlFiles, String zipFileName, String uniscid) {
        try {
            // 构建企业专用的输出目录
            String outputDir = buildEnterpriseOutputDir(uniscid);

            // 创建ZIP文件
            File zipFile = new File(outputDir, zipFileName);

            // 使用Java原生ZIP功能创建压缩文件
            createZipWithJavaNative(zipFile, xmlFiles);

            log.info("为企业{}创建ZIP文件：{}，包含{}个XML文件", uniscid, zipFile.getAbsolutePath(), xmlFiles.size());
            return zipFile;

        } catch (Exception e) {
            log.error("为企业{}创建ZIP文件时发生错误", uniscid, e);
            return null;
        }
    }

    /**
     * 使用Java原生ZIP功能创建压缩文件
     */
    private void createZipWithJavaNative(File zipFile, List<File> filesToZip) throws Exception {
        try (java.util.zip.ZipOutputStream zos = new java.util.zip.ZipOutputStream(
                new java.io.FileOutputStream(zipFile))) {

            byte[] buffer = new byte[1024];

            for (File file : filesToZip) {
                if (file.exists()) {
                    try (java.io.FileInputStream fis = new java.io.FileInputStream(file)) {
                        java.util.zip.ZipEntry zipEntry = new java.util.zip.ZipEntry(file.getName());
                        zos.putNextEntry(zipEntry);

                        int length;
                        while ((length = fis.read(buffer)) > 0) {
                            zos.write(buffer, 0, length);
                        }

                        zos.closeEntry();
                    }
                }
            }
        }
    }

    /**
     * 清理临时XML文件
     */
    private void cleanupXmlFiles(List<File> xmlFiles) {
        for (File xmlFile : xmlFiles) {
            if (xmlFile.exists()) {
                boolean deleted = xmlFile.delete();
                if (deleted) {
                    log.debug("删除临时XML文件：{}", xmlFile.getAbsolutePath());
                } else {
                    log.warn("删除临时XML文件失败：{}", xmlFile.getAbsolutePath());
                }
            }
        }
    }

    /**
     * 构建对账参数JSON字符串
     * @param uniscid 企业统一社会信用代码
     * @param entname 企业名称
     * @param enterpriseRecordCountMap 各表数据统计Map
     * @return JSON字符串形式的对账参数
     */
    private String buildReconciliationParams(String uniscid, String entname, Map<String, Integer> enterpriseRecordCountMap,String minareregorg) {
        try {
            // 构建对账接口参数Map
            Map<String, Object> recordData = new HashMap<>();
            recordData.put("appform", appform); // 从配置文件中获取，这里暂时固定值
            recordData.put("uniscid", uniscid);

            String minOrg = "";
            if (minareregorg != null && minareregorg.length() >= 2) {
                String moveInProvince = minareregorg.substring(0, 2) + "0000";
                minOrg = moveInProvince;
            }

            recordData.put("moveInProvince", minOrg);
            recordData.put("moveOutProvince", "440000"); // 迁出省份固定值
            recordData.put("entname", entname);

            // 设置各表的数量，如果表中没有数据则设置为0
            recordData.put("eBaseinfo", enterpriseRecordCountMap.getOrDefault("E_BASEINFO", 0));
            recordData.put("eAlterRecoder", enterpriseRecordCountMap.getOrDefault("E_ALTER_RECODER", 0));
            recordData.put("ePubSpotcheck", enterpriseRecordCountMap.getOrDefault("E_PUB_SPOTCHECK", 0));
            recordData.put("drRaninsres", enterpriseRecordCountMap.getOrDefault("DR_RANINSRES", 0));
            recordData.put("aoOpAnomaly", enterpriseRecordCountMap.getOrDefault("AO_OPANOMALY", 0));
            recordData.put("aoOpaDetail", enterpriseRecordCountMap.getOrDefault("AO_OPA_DETAIL", 0));
            recordData.put("aoOpAnomalyInv", enterpriseRecordCountMap.getOrDefault("AO_OPANOMALY_INV", 0));
            recordData.put("anBaseinfo", enterpriseRecordCountMap.getOrDefault("AN_BASEINFO", 0));
            recordData.put("anSubcapital", enterpriseRecordCountMap.getOrDefault("AN_SUBCAPITAL", 0));
            recordData.put("anForinvestment", enterpriseRecordCountMap.getOrDefault("AN_FORINVESTMENT", 0));
            recordData.put("anWebsiteinfo", enterpriseRecordCountMap.getOrDefault("AN_WEBSITEINFO", 0));
            recordData.put("anAlterstockinfo", enterpriseRecordCountMap.getOrDefault("AN_ALTERSTOCKINFO", 0));
            recordData.put("anForguaranteeinfo", enterpriseRecordCountMap.getOrDefault("AN_FORGUARANTEEINFO", 0));
            recordData.put("anUpdateinfo", enterpriseRecordCountMap.getOrDefault("AN_UPDATEINFO", 0));
            recordData.put("anSupBaseinfo", enterpriseRecordCountMap.getOrDefault("AN_SUP_BASEINFO", 0));
            recordData.put("anSocsecinfo", enterpriseRecordCountMap.getOrDefault("AN_SOCSECINFO", 0));
            recordData.put("eImPermit", enterpriseRecordCountMap.getOrDefault("E_IM_PERMIT", 0));
            recordData.put("eImPrmtalt", enterpriseRecordCountMap.getOrDefault("E_IM_PRMTALT", 0));
            recordData.put("eImInvestment", enterpriseRecordCountMap.getOrDefault("E_IM_INVESTMENT", 0));
            recordData.put("eImInvprodetail", enterpriseRecordCountMap.getOrDefault("E_IM_INVPRODETAIL", 0));
            recordData.put("eImInvactdetail", enterpriseRecordCountMap.getOrDefault("E_IM_INVACTDETAIL", 0));
            recordData.put("eImInvupdate", enterpriseRecordCountMap.getOrDefault("E_IM_INVUPDATE", 0));
            recordData.put("eImIppldg", enterpriseRecordCountMap.getOrDefault("E_IM_IPPLDG", 0));
            recordData.put("eImIppldgalt", enterpriseRecordCountMap.getOrDefault("E_IM_IPPLDGALT", 0));
            recordData.put("eImCase", enterpriseRecordCountMap.getOrDefault("E_IM_CASE", 0));
            recordData.put("eImCasalt", enterpriseRecordCountMap.getOrDefault("E_IM_CASALT", 0));
            recordData.put("eImInvsralt", enterpriseRecordCountMap.getOrDefault("E_IM_INVSRALT", 0));
            recordData.put("eLiIlldishonesty", enterpriseRecordCountMap.getOrDefault("E_LI_ILLDISHONESTY", 0));
            recordData.put("eLiIlldisdetail", enterpriseRecordCountMap.getOrDefault("E_LI_ILLDISDETAIL", 0));
            recordData.put("casePubNbaseinfo", enterpriseRecordCountMap.getOrDefault("CASE_PUB_NBASEINFO", 0));
            recordData.put("casePubNdoc", enterpriseRecordCountMap.getOrDefault("CASE_PUB_NDOC", 0));
            recordData.put("casePubNalter", enterpriseRecordCountMap.getOrDefault("CASE_PUB_NALTER", 0));
            recordData.put("eOtNpermit", enterpriseRecordCountMap.getOrDefault("E_OT_NPERMIT", 0));
            recordData.put("eOtNprmtalt", enterpriseRecordCountMap.getOrDefault("E_OT_NPRMTALT", 0));
            recordData.put("eOtNcase", enterpriseRecordCountMap.getOrDefault("E_OT_NCASE", 0));
            recordData.put("eOtNcasalt", enterpriseRecordCountMap.getOrDefault("E_OT_NCASALT", 0));
            recordData.put("eOtSpotcheck", enterpriseRecordCountMap.getOrDefault("E_OT_SPOTCHECK", 0));
            recordData.put("caseCreInformation", enterpriseRecordCountMap.getOrDefault("CASE_CRE_INFORMATION", 0));

            // 使用hutool的JSONObject转换为JSON字符串
            return new JSONObject(recordData).toString();
        } catch (Exception e) {
            log.error("构建对账参数JSON时发生错误：{}", e.getMessage(), e);
            return "{}";
        }
    }

    /**
     * 生成带序号的不重复文件名
     * @param uniscid 企业唯一标识
     * @param currentDate 当前日期（格式：yyyyMMdd）
     * @param seq 序号（从0开始，0表示无序号）
     * @return 带序号的文件名
     */
    private String generateSeqZipFileName(String uniscid, String currentDate, int seq) {
        if (seq == 0) {
            // 序号为0时，使用原文件名格式
            return uniscid + "-QYXYXX-" + currentDate + ".zip";
        }
        // 序号≥1时，在日期后拼接序号
        return uniscid + "-QYXYXX-" + currentDate + seq + ".zip";
    }
}
