package com.hotent.project.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hotent.base.util.StringUtil;
import com.hotent.config.EipConfig;
import com.hotent.project.manager.*;
import com.hotent.project.model.*;
import com.hotent.surveyinfo.manager.CostSurveyTemplateUploadManager;
import com.hotent.surveyinfo.model.CostSurveyTemplateUpload;
import com.hotent.uc.manager.OrgManager;
import com.hotent.uc.manager.UserManager;
import com.hotent.uc.model.Org;
import com.hotent.uc.model.User;
import com.hotent.uc.util.ContextUtil;
import com.hotent.util.FileUploadUtil;
import com.hotent.util.wordexcelutils.CompleteTemplateProcessor;
import com.hotent.util.wordexcelutils.SmartTemplateWriter;
import org.apache.poi.xwpf.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.FileOutputStream;
import java.time.LocalDateTime;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 异步资料归纳服务
 *
 * @company 山西清众科技股份有限公司
 * @author 超级管理员
 * @since 2025-12-02
 */
@Service
public class AsyncMaterialSummaryService {

    private static final Logger logger = LoggerFactory.getLogger(AsyncMaterialSummaryService.class);

    @Autowired
    private CostProjectTaskMaterialSummaryManager costProjectTaskMaterialSummaryManager;

    @Autowired
    private CostProjectTaskMaterialSummaryDetailManager costProjectTaskMaterialSummaryDetailManager;

    @Autowired
    private CostProjectDocumentManager costProjectDocumentManager;

    @Autowired
    private CostProjectTaskManager costProjectTaskManager;

    @Autowired
    private CostSurveyTemplateUploadManager costSurveyTemplateUploadManager;

    @Autowired
    private CostProjectTaskMaterialManager costProjectTaskMaterialManager;

    @Autowired
    private CostProjectDeliberateManager costProjectDeliberateManager;

    @Autowired
    private CostProjectTaskAdjustmentRecordManager adjustmentRecordManager;

    @Autowired
    private CostProjectTaskEvidenceManager costProjectTaskEvidenceManager;

    @Autowired
    private CostProjectTaskPreliminaryOpinionManager preliminaryOpinionManager;

    @Autowired
    private CostProjectApprovalManager costProjectApprovalManager;


    @Autowired
    private OrgManager orgManager;

    @Autowired
    private UserManager userManager;

    // 从配置文件读取模板路径
    @org.springframework.beans.factory.annotation.Value("${archive.template.coverPath:}")
    private String coverTemplatePath;

    @org.springframework.beans.factory.annotation.Value("${archive.template.catalogPath:}")
    private String catalogTemplatePath;

    @org.springframework.beans.factory.annotation.Value("${archive.template.backCoverPath:}")
    private String backCoverTemplatePath;


    /**
     * 生成资料归纳主表（14个基础资料类别）- 核心逻辑
     *
     * @param mainTask 主任务
     * @param childTasks 子任务列表
     */
    public void generateMaterialSummary(CostProjectTask mainTask, List<CostProjectTask> childTasks) {
        try {
            // 定义14个基础资料类别
            String[] materialNames = {
                    "成本监审报告（含成本监审报告签发稿、送达回证）",
                    "被监审单位申请定（调）价报告（复印件）",
                    "成本监审通知书（含送达回证）",
                    "经营者需提供成本资料清单",
                    "《政府定价成本监审调查表》",
                    "成本监审补充资料通知书（含送达回证）",
                    "成本审核初步意见告知书（含送达回证）",
                    "经营者书面反馈的材料",
                    "成本审核初步意见表（集体审议用）",
                    "成本监审集体审议记录",
                    "成本监审工作底稿",
                    "成本监审提取资料登记表",
                    "提取的成本资料和会计凭证等复印件",
                    "中止定价成本监审料通知书（含送达回证）"
            };

            // 为主任务生成14个资料归纳主表记录
            for (int i = 0; i < materialNames.length; i++) {
                CostProjectTaskMaterialSummary summary = new CostProjectTaskMaterialSummary();
                summary.setTaskId(mainTask.getId());
                summary.setMaterialName(materialNames[i]);
                summary.setMaterialOrderNum(i + 1);
                summary.setIsDeleted("0");
                costProjectTaskMaterialSummaryManager.createOrUpdate(summary);

                // 根据不同的资料类别生成对应的明细记录
                generateDetailsByMaterialType(summary, mainTask, childTasks, i + 1);
            }
        } catch (Exception e) {
            // 记录异常日志，但不影响主流程
            logger.error("生成资料归纳失败", e);
        }
    }

    /**
     * 根据资料类别生成对应的明细记录
     *
     * @param summary 资料归纳主表
     * @param mainTask 主任务
     * @param childTasks 子任务列表
     * @param materialType 资料类别序号（1-13）
     */
    private void generateDetailsByMaterialType(CostProjectTaskMaterialSummary summary,
                                               CostProjectTask mainTask,
                                               List<CostProjectTask> childTasks,
                                               int materialType) {
        try {
            // 查询项目下的所有文书
            List<CostProjectDocument> documents = costProjectDocumentManager.getListByProjectId(mainTask.getProjectId());
            if (documents == null) {
                documents = new java.util.ArrayList<>();
            }

            switch (materialType) {
                case 1:
                    // 成本监审报告（含成本监审报告签发稿、送达回证）
                    generateType1Details(summary, mainTask, documents);
                    break;
                case 2:
                    // 被监审单位申请定（调）价报告（复印件）
                    generateType2Details(summary, mainTask, childTasks, documents);
                    break;
                case 3:
                    // 成本监审通知书（含送达回证）
                    generateType3Details(summary, mainTask, childTasks, documents);
                    break;
                case 4:
                    // 经营者需提供成本资料清单
                    generateType4Details(summary, mainTask, childTasks, documents);
                    break;
                case 5:
                    // 《政府定价成本监审调查表》
                    generateType5Details(summary, mainTask, childTasks, documents);
                    break;
                case 6:
                    // 成本监审补充资料通知书（含送达回证）
                    generateType6Details(summary, mainTask, childTasks, documents);
                    break;
                case 7:
                    // 成本审核初步意见告知书（含送达回证）
                    generateType7Details(summary, mainTask, childTasks, documents);
                    break;
                case 8:
                    // 经营者书面反馈的材料
                    generateType8Details(summary, mainTask, childTasks, documents);
                    break;
                case 9:
                    // 成本审核初步意见表（集体审议用）
                    generateType9Details(summary, mainTask, childTasks, documents);
                    break;
                case 10:
                    // 成本监审集体审议记录
                    generateType10Details(summary, mainTask, documents);
                    break;
                case 11:
                    // 成本监审工作底稿
                    generateType11Details(summary, mainTask, childTasks, documents);
                    break;
                case 12:
                    // 成本监审提取资料登记表
                    generateType12Details(summary, mainTask, childTasks, documents);
                    break;
                case 13:
                    // 提取的成本资料和会计凭证等复印件
                    generateType13Details(summary, mainTask, childTasks, documents);
                    break;
                case 14:
                    // 中止定价成本监审料通知书（含送达回证）
                    generateType14Details(summary, mainTask, childTasks, documents);
                    break;
                default:
                    throw new RuntimeException("未知的资料类型");
            }
        } catch (Exception e) {
            logger.error("生成资料类型 {} 的明细时出错：{}", materialType, e.getMessage(), e);
            // 继续执行，不中断整个流程
        }
    }

    // ==================== 类型1：成本监审报告（含成本监审报告签发稿、送达回证） ====================
    // A.成本监审报告（含成本监审报告签发稿）
    //  包括成本监审报告、报告签发稿等文书。
    private void generateType1Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectDocument> documents) {
        int orderNum = 1;
        // 获取"成本监审报告"、"成本监审报告签发稿"、"送达回证"
        List<CostProjectDocument> matchedDocuments = documents.stream()
                .filter(doc -> "政府定价成本监审结论报告".equals(doc.getDocumentName())
                        || "政府定价成本监审结论报告-送达回证".equals(doc.getDocumentName())
                )
                .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
                .collect(Collectors.toList());

        for (CostProjectDocument document : matchedDocuments) {
            CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
            detail.setMasterId(summary.getId());
            detail.setTaskId(mainTask.getId());
            detail.setDocumentName(document.getDocumentName());
            detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
            detail.setAuditedUnitName("");
            detail.setFileSource("系统生成电子文书");
            detail.setPageCount(0);
            detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
            detail.setOrderNum(orderNum++);
            detail.setIsDeleted("0");
            costProjectTaskMaterialSummaryDetailManager.save(detail);
        }
    }

    // ==================== 类型2：被监审单位申请定（调）价报告（复印件） ====================
    // 被监审单位申请定（调）价报告等。
    //来源：从“监审立项”附件获取。
    private void generateType2Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
        int orderNum = 1;
        // 获取"申请定（调）价报告"
        List<CostProjectDocument> matchedDocuments = documents.stream()
                .filter(doc -> "申请定（调）价报告".equals(doc.getDocumentName()))
                .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
                .collect(Collectors.toList());

        for (CostProjectDocument document : matchedDocuments) {
            CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
            detail.setMasterId(summary.getId());
            detail.setTaskId(mainTask.getId());
            detail.setDocumentName(document.getDocumentName());
            detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
            detail.setAuditedUnitName("");
            detail.setFileSource("监审主体上传文件");
            detail.setPageCount(0);
            detail.setAttachmentUrl(document.getScanDocumentUrl() != null ? document.getScanDocumentUrl() : "");
            detail.setOrderNum(orderNum++);
            detail.setIsDeleted("0");
            costProjectTaskMaterialSummaryDetailManager.save(detail);
        }
        CostProjectApproval approval = costProjectApprovalManager.getById(mainTask.getProjectId());
        if (approval != null && StringUtil.isNotEmpty(approval.getAccordingFileUrl())) {
            CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
            detail.setMasterId(summary.getId());
            detail.setTaskId(mainTask.getId());
            detail.setDocumentName("成本项目定（调）价依据");
            detail.setDocumentNumber("");
            detail.setAuditedUnitName("");
            detail.setFileSource("系统生成电子文书");
            detail.setPageCount(0);
            detail.setAttachmentUrl(approval.getAccordingFileUrl());
            detail.setOrderNum(orderNum++);
            detail.setIsDeleted("0");
            costProjectTaskMaterialSummaryDetailManager.save(detail);
        }
    }

    // ==================== 类型3：成本监审通知书（含送达回证） ====================
    // 包括成本监审通知书、送达回证等文书。
    //来源：从“监审文书”中获取。
    private void generateType3Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
        int orderNum = 1;
        // "成本监审通知书"和"送达回证"
        List<CostProjectDocument> matchedDocuments = documents.stream()
                .filter(doc -> "成本监审通知书".equals(doc.getDocumentName())
                        || "成本监审通知书-送达回证".equals(doc.getDocumentName()))
                .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
                .collect(Collectors.toList());

        for (CostProjectDocument document : matchedDocuments) {
            CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
            detail.setMasterId(summary.getId());
            detail.setTaskId(mainTask.getId());
            detail.setDocumentName(document.getDocumentName());
            detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
            detail.setAuditedUnitName("");
            detail.setFileSource("系统生成电子文书");
            detail.setPageCount(0);
            detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
            detail.setOrderNum(orderNum++);
            detail.setIsDeleted("0");
            costProjectTaskMaterialSummaryDetailManager.save(detail);
        }
    }

    // ==================== 类型4：经营者需提供成本资料清单(提取资料) ====================
    // 成本监审任务中的资料报送要求。
    //来源：从“监审任务部署”中获取。
    private void generateType4Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
        int orderNum = 1;
        // 获取"成本资料清单"
        List<CostProjectDocument> matchedDocuments = documents.stream()
                .filter(doc -> "成本监审资料提取资料登记表".equals(doc.getDocumentName()))
                .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
                .collect(Collectors.toList());

        for (CostProjectDocument document : matchedDocuments) {
            CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
            detail.setMasterId(summary.getId());
            detail.setTaskId(mainTask.getId());
            detail.setDocumentName(document.getDocumentName());
            detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
            detail.setAuditedUnitName("");
            detail.setFileSource("系统生成电子文书");
            detail.setPageCount(0);
            detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
            detail.setOrderNum(orderNum++);
            detail.setIsDeleted("0");
            costProjectTaskMaterialSummaryDetailManager.save(detail);
        }
        for (CostProjectTask childTask : childTasks) {
            List<CostProjectTaskEvidence> list = costProjectTaskEvidenceManager.list(
                    new LambdaQueryWrapper<CostProjectTaskEvidence>().eq(CostProjectTaskEvidence::getTaskId, childTask.getId())
            );
            for (CostProjectTaskEvidence evidence : list) {
                // 只处理有附件的资料登记
                if (StringUtil.isNotEmpty(evidence.getAttachmentUrl())) {
                    CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
                    detail.setMasterId(summary.getId());
                    detail.setTaskId(mainTask.getId());
                    detail.setDocumentName(evidence.getMaterialName() != null ? evidence.getMaterialName() : "提取资料登记");
                    detail.setDocumentNumber("");
                    detail.setAuditedUnitName(childTask.getAuditedUnitName() != null ? childTask.getAuditedUnitName() : "");
                    detail.setFileSource("系统生成电子文书");
                    detail.setPageCount(evidence.getPageCount() != null ? evidence.getPageCount() : 0);
                    detail.setAttachmentUrl(evidence.getAttachmentUrl());
                    detail.setOrderNum(orderNum++);
                    detail.setIsDeleted("0");
                    costProjectTaskMaterialSummaryDetailManager.save(detail);
                }
            }

        }
    }

    // ==================== 类型5：《政府定价成本监审调查表》 ====================
    // 各被监审单位的“成本监审调查表”文档。
    //来源：从“监审任务”中获取各被监审单位填报的成本监审调查表。
    private void generateType5Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
        int orderNum = 1;
        for (CostProjectTask childTask : childTasks) {
            List<CostSurveyTemplateUpload> costSurveyTemplateUploads = costSurveyTemplateUploadManager.listByTaskId(childTask.getId());
            for (CostSurveyTemplateUpload upload : costSurveyTemplateUploads) {
                if ("1".equals(upload.getIsUpload()) && StringUtil.isNotEmpty(upload.getFileUrl())) {
                    CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
                    detail.setMasterId(summary.getId());
                    detail.setTaskId(mainTask.getId());
                    detail.setDocumentName(upload.getSurveyTemplateName() != null ? upload.getSurveyTemplateName() : "政府定价成本监审调查表");
                    detail.setDocumentNumber("");
                    detail.setAuditedUnitName(childTask.getAuditedUnitName() != null ? childTask.getAuditedUnitName() : "");
                    detail.setFileSource("监审单位反馈文件");
                    detail.setPageCount(0);
                    detail.setAttachmentUrl(upload.getFileUrl());
                    detail.setOrderNum(orderNum++);
                    detail.setIsDeleted("0");
                    costProjectTaskMaterialSummaryDetailManager.save(detail);
                }
            }
        }
        // 成本调查表（kkkk）
    }

    // ==================== 类型6：成本监审补充资料通知书（含送达回证） ====================
    // 监审主体发送给各被监审单位的补充资料通知书、送达回证等文书。
    //来源：从“监审文书”中获取。
    private void generateType6Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
        int orderNum = 1;
        List<CostProjectDocument> matchedDocuments = documents.stream()
                .filter(doc -> "成本监审补充资料通知书".equals(doc.getDocumentName())
                        || "成本监审补充资料通知书-送达回证".equals(doc.getDocumentName()))
                .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
                .collect(Collectors.toList());

        for (CostProjectDocument document : matchedDocuments) {
            CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
            detail.setMasterId(summary.getId());
            detail.setTaskId(mainTask.getId());
            detail.setDocumentName(document.getDocumentName());
            detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
            detail.setAuditedUnitName("");
            detail.setFileSource("系统生成电子文书");
            detail.setPageCount(0);
            detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
            detail.setOrderNum(orderNum++);
            detail.setIsDeleted("0");
            costProjectTaskMaterialSummaryDetailManager.save(detail);
        }
    }

    // ==================== 类型7：成本审核初步意见告知书（含送达回证） ====================
    // 监审主体发送给各被监审单位的初步意见告知书、送达回证等文书。
    // 来源：从“监审文书”中获取。
    private void generateType7Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
        int orderNum = 1;
        // 获取"成本审核初步意见告知书"和"送达回证"
        List<CostProjectDocument> matchedDocuments = documents.stream()
                .filter(doc -> "成本审核初步意见告知书".equals(doc.getDocumentName())
                        || "成本审核初步意见告知书-送达回证".equals(doc.getDocumentName()))
                .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
                .collect(Collectors.toList());

        for (CostProjectDocument document : matchedDocuments) {
            CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
            detail.setMasterId(summary.getId());
            detail.setTaskId(mainTask.getId());
            detail.setDocumentName(document.getDocumentName());
            detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
            detail.setAuditedUnitName("");
            detail.setFileSource("系统生成电子文书");
            detail.setPageCount(0);
            detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
            detail.setOrderNum(orderNum++);
            detail.setIsDeleted("0");
            costProjectTaskMaterialSummaryDetailManager.save(detail);
        }
    }

    // ==================== 类型8：经营者书面反馈的材料 ====================
    // 各被监审单位对初步意见告知书的意见反馈资料。
    //来源：从“监审任务”中获取反馈意见。
    private void generateType8Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
        int orderNum = 1;
        // 获取"书面反馈材料"（来源：监审单位反馈文件）
        List<CostProjectDocument> matchedDocuments = documents.stream()
                .filter(doc -> "书面反馈材料".equals(doc.getDocumentName()))
                .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
                .collect(Collectors.toList());

        for (CostProjectDocument document : matchedDocuments) {
            CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
            detail.setMasterId(summary.getId());
            detail.setTaskId(mainTask.getId());
            detail.setDocumentName(document.getDocumentName());
            detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
            detail.setAuditedUnitName("");
            detail.setFileSource("监审单位反馈文件");
            detail.setPageCount(0);
            detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
            detail.setOrderNum(orderNum++);
            detail.setIsDeleted("0");
            costProjectTaskMaterialSummaryDetailManager.save(detail);
        }
        // 获取被监审单位的反馈意见和反馈资料
        for (CostProjectTask childTask : childTasks) {
            List<CostProjectTaskPreliminaryOpinion> list = preliminaryOpinionManager.list(
                    new LambdaQueryWrapper<>(CostProjectTaskPreliminaryOpinion.class)
                            .eq(CostProjectTaskPreliminaryOpinion::getTaskId, childTask.getId())
            );
            for (CostProjectTaskPreliminaryOpinion opinion : list) {
                // 只处理有反馈资料的记录
                if (StringUtil.isNotEmpty(opinion.getFeedbackMaterials())) {
                    CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
                    detail.setMasterId(summary.getId());
                    detail.setTaskId(mainTask.getId());
                    detail.setDocumentName("书面反馈材料");
                    detail.setDocumentNumber("");
                    detail.setAuditedUnitName(childTask.getAuditedUnitName() != null ? childTask.getAuditedUnitName() : "");
                    detail.setFileSource("监审单位反馈文件");
                    detail.setPageCount(0);
                    detail.setAttachmentUrl(opinion.getFeedbackMaterials());
                    detail.setOrderNum(orderNum++);
                    detail.setIsDeleted("0");
                    costProjectTaskMaterialSummaryDetailManager.save(detail);
                }
            }
        }
    }

    // ==================== 类型9：成本审核初步意见表（集体审议用） ====================
    // 来源：从“监审文书”中获取
    private void generateType9Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
        int orderNum = 1;
        // 获取"成本审核初步意见表"
        List<CostProjectDocument> matchedDocuments = documents.stream()
                .filter(doc -> "成本审核初步意见表".equals(doc.getDocumentName()))
                .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
                .collect(Collectors.toList());

        for (CostProjectDocument document : matchedDocuments) {
            CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
            detail.setMasterId(summary.getId());
            detail.setTaskId(mainTask.getId());
            detail.setDocumentName(document.getDocumentName());
            detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
            detail.setAuditedUnitName("");
            detail.setFileSource("系统生成电子文书");
            detail.setPageCount(0);
            detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
            detail.setOrderNum(orderNum++);
            detail.setIsDeleted("0");
            costProjectTaskMaterialSummaryDetailManager.save(detail);
        }
    }

    // ==================== 类型10：成本监审集体审议记录 ====================
    // 来源：从“监审文书”中获取。
    private void generateType10Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectDocument> documents) {
        int orderNum = 1;
        // 获取"成本监审集体审议记录"
        List<CostProjectDocument> matchedDocuments = documents.stream()
                .filter(doc -> "成本监审集体审议记录".equals(doc.getDocumentName()))
                .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
                .collect(Collectors.toList());

        for (CostProjectDocument document : matchedDocuments) {
            CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
            detail.setMasterId(summary.getId());
            detail.setTaskId(mainTask.getId());
            detail.setDocumentName(document.getDocumentName());
            detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
            detail.setAuditedUnitName("");
            detail.setFileSource("系统生成电子文书");
            detail.setPageCount(0);
            detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
            detail.setOrderNum(orderNum++);
            detail.setIsDeleted("0");
            costProjectTaskMaterialSummaryDetailManager.save(detail);
        }
        // 获取集体审议记录
        List<CostProjectDeliberate> list = costProjectDeliberateManager.list(
                new LambdaQueryWrapper<CostProjectDeliberate>().eq(CostProjectDeliberate::getTaskId, mainTask.getId())
        );
        for (CostProjectDeliberate deliberate : list) {
            // 只处理有附件的审议记录
            if (StringUtil.isNotEmpty(deliberate.getAttachmentIds())) {
                CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
                detail.setMasterId(summary.getId());
                detail.setTaskId(mainTask.getId());
                detail.setDocumentName("成本监审集体审议记录");
                detail.setDocumentNumber("");
                detail.setAuditedUnitName("");
                detail.setFileSource("系统生成电子文书");
                detail.setPageCount(0);
                detail.setAttachmentUrl(deliberate.getAttachmentIds());
                detail.setOrderNum(orderNum++);
                detail.setIsDeleted("0");
                costProjectTaskMaterialSummaryDetailManager.save(detail);
            }
        }
    }

    // ==================== 类型11：成本监审工作底稿 ====================
    // 来源：从“监审文书”中获取。
    private void generateType11Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
        int orderNum = 1;
        // 获取"成本监审工作底稿"
        List<CostProjectDocument> matchedDocuments = documents.stream()
                .filter(doc -> "成本监审工作底稿".equals(doc.getDocumentName()))
                .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
                .collect(Collectors.toList());

        for (CostProjectDocument document : matchedDocuments) {
            CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
            detail.setMasterId(summary.getId());
            detail.setTaskId(mainTask.getId());
            detail.setDocumentName(document.getDocumentName());
            detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
            detail.setAuditedUnitName("");
            detail.setFileSource("系统生成电子文书");
            detail.setPageCount(0);
            detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
            detail.setOrderNum(orderNum++);
            detail.setIsDeleted("0");
            costProjectTaskMaterialSummaryDetailManager.save(detail);
        }
        // 获取核增核减记录（工作底稿的一部分）
        for (CostProjectTask childTask : childTasks) {
            List<CostProjectTaskAdjustmentRecord> costProjectTaskAdjustmentRecords = adjustmentRecordManager.listByTaskId(childTask.getId());
            for (CostProjectTaskAdjustmentRecord record : costProjectTaskAdjustmentRecords) {
                // 只处理有附件的记录
                if (StringUtil.isNotEmpty(record.getAttachmentUrl())) {
                    CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
                    detail.setMasterId(summary.getId());
                    detail.setTaskId(mainTask.getId());
                    detail.setDocumentName(record.getSubject() != null ? record.getSubject() + "-工作底稿" : "成本监审工作底稿");
                    detail.setDocumentNumber("");
                    detail.setAuditedUnitName(childTask.getAuditedUnitName() != null ? childTask.getAuditedUnitName() : "");
                    detail.setFileSource("系统生成电子文书");
                    detail.setPageCount(0);
                    detail.setAttachmentUrl(record.getAttachmentUrl());
                    detail.setOrderNum(orderNum++);
                    detail.setIsDeleted("0");
                    costProjectTaskMaterialSummaryDetailManager.save(detail);
                }
            }
        }
    }

    // ==================== 类型12：成本监审提取资料登记表 ====================
    // 来源：从“监审文书”中获取。
    private void generateType12Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
        int orderNum = 1;
        // 获取"成本监审提取资料登记表"
        List<CostProjectDocument> matchedDocuments = documents.stream()
                .filter(doc -> "成本监审提取资料登记表".equals(doc.getDocumentName()))
                .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
                .collect(Collectors.toList());

        for (CostProjectDocument document : matchedDocuments) {
            CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
            detail.setMasterId(summary.getId());
            detail.setTaskId(mainTask.getId());
            detail.setDocumentName(document.getDocumentName());
            detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
            detail.setAuditedUnitName("");
            detail.setFileSource("系统生成电子文书");
            detail.setPageCount(0);
            detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
            detail.setOrderNum(orderNum++);
            detail.setIsDeleted("0");
            costProjectTaskMaterialSummaryDetailManager.save(detail);
        }
        // 获取子任务的资料登记表
        for (CostProjectTask childTask : childTasks) {
            List<CostProjectTaskEvidence> list = costProjectTaskEvidenceManager.list(
                    new LambdaQueryWrapper<CostProjectTaskEvidence>().eq(CostProjectTaskEvidence::getTaskId, childTask.getId())
            );
            for (CostProjectTaskEvidence evidence : list) {
                // 只处理有附件的资料登记
                if (StringUtil.isNotEmpty(evidence.getAttachmentUrl())) {
                    CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
                    detail.setMasterId(summary.getId());
                    detail.setTaskId(mainTask.getId());
                    detail.setDocumentName(evidence.getMaterialName() != null ? evidence.getMaterialName() : "提取资料登记");
                    detail.setDocumentNumber("");
                    detail.setAuditedUnitName(childTask.getAuditedUnitName() != null ? childTask.getAuditedUnitName() : "");
                    detail.setFileSource("系统生成电子文书");
                    detail.setPageCount(evidence.getPageCount() != null ? evidence.getPageCount() : 0);
                    detail.setAttachmentUrl(evidence.getAttachmentUrl());
                    detail.setOrderNum(orderNum++);
                    detail.setIsDeleted("0");
                    costProjectTaskMaterialSummaryDetailManager.save(detail);
                }
            }
        }
    }

    // ==================== 类型13：提取的成本资料和会计凭证等复印件 ====================
    // 来源：各被监审单位首次及补充材料时提交的资料，包括综合性材料、财会资料等。
    private void generateType13Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
        int orderNum = 1;
        // 获取"成本资料和会计凭证"（来源：被监审单位提交的资料）
        List<CostProjectDocument> matchedDocuments = documents.stream()
                .filter(doc -> "成本资料和会计凭证".equals(doc.getDocumentName()))
                .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
                .collect(Collectors.toList());

        for (CostProjectDocument document : matchedDocuments) {
            CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
            detail.setMasterId(summary.getId());
            detail.setTaskId(mainTask.getId());
            detail.setDocumentName(document.getDocumentName());
            detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
            detail.setAuditedUnitName("");
            detail.setFileSource("监审单位反馈文件");
            detail.setPageCount(0);
            detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
            detail.setOrderNum(orderNum++);
            detail.setIsDeleted("0");
            costProjectTaskMaterialSummaryDetailManager.save(detail);
        }
        // 获取子任务的资料登记表
        for (CostProjectTask childTask : childTasks) {
            // 获取任务的报送资料要求（被监审单位提交的补充资料）
            List<CostProjectTaskMaterial> list = costProjectTaskMaterialManager.list(
                    new LambdaQueryWrapper<>(CostProjectTaskMaterial.class)
                            .eq(CostProjectTaskMaterial::getTaskId, childTask.getId())
            );
            for (CostProjectTaskMaterial material : list) {
                // 只处理已上传的资料
                if ("1".equals(material.getIsUpload()) && StringUtil.isNotEmpty(material.getFileUrl())) {
                    CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
                    detail.setMasterId(summary.getId());
                    detail.setTaskId(mainTask.getId());
                    detail.setDocumentName(material.getInformationName() != null ? material.getInformationName() : "补充资料");
                    detail.setDocumentNumber("");
                    detail.setAuditedUnitName("");
                    detail.setFileSource("监审单位反馈文件");
                    detail.setPageCount(0);
                    detail.setAttachmentUrl(material.getFileUrl());
                    detail.setOrderNum(orderNum++);
                    detail.setIsDeleted("0");
                    costProjectTaskMaterialSummaryDetailManager.save(detail);
                }
            }
        }
    }

    // ==================== 类型14：中止定价成本监审料通知书（含送达回证） ====================
    // 来源：从“监审文书”中获取。
    private void generateType14Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
        int orderNum = 1;
        // 获取"成本资料和会计凭证"（来源：被监审单位提交的资料）
        List<CostProjectDocument> matchedDocuments = documents.stream()
                .filter(doc -> "中止定价成本监审通知书".equals(doc.getDocumentName())
                        || "中止定价成本监审通知书-送达回证".equals(doc.getDocumentName()))
                .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
                .collect(Collectors.toList());

        for (CostProjectDocument document : matchedDocuments) {
            CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
            detail.setMasterId(summary.getId());
            detail.setTaskId(mainTask.getId());
            detail.setDocumentName(document.getDocumentName());
            detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
            detail.setAuditedUnitName("");
            detail.setFileSource("监审单位反馈文件");
            detail.setPageCount(0);
            detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
            detail.setOrderNum(orderNum++);
            detail.setIsDeleted("0");
            costProjectTaskMaterialSummaryDetailManager.save(detail);
        }
    }

    /**
     * 档案校对通过后，异步生成Word卷宗
     * 顺序：封面(-1) -> 目录(-2) -> 14个资料(1-13) -> 封底(-3)
     *
     * @param taskId 任务ID
     */
    @Async
    public void generateWordArchiveAsync(String taskId) {
        CostProjectTask task = costProjectTaskManager.getById(taskId);
        try {
            logger.info("开始生成Word卷宗，任务ID：{}", taskId);

            // 查询任务的所有资料归纳主表（包含封面、目录、封底）
            List<CostProjectTaskMaterialSummary> allSummaryList =
                costProjectTaskMaterialSummaryManager.listAllByTaskId(taskId);

            // 创建Word文档
            XWPFDocument document = new XWPFDocument();
            boolean isFirstDocument = true;

            // 按顺序合并：封面(-1) -> 目录(-2) -> 14个资料(1-13) -> 封底(-3)
            // 排序：-1, -2, 1, 2, ..., 13, -3
            allSummaryList.sort((a, b) -> {
                int orderA = a.getMaterialOrderNum() != null ? a.getMaterialOrderNum() : 0;
                int orderB = b.getMaterialOrderNum() != null ? b.getMaterialOrderNum() : 0;
                // -1(封面) < -2(目录) < 1-13(资料) < -3(封底)
                int sortA = orderA == -1 ? -100 : (orderA == -2 ? -99 : (orderA == -3 ? 100 : orderA));
                int sortB = orderB == -1 ? -100 : (orderB == -2 ? -99 : (orderB == -3 ? 100 : orderB));
                return Integer.compare(sortA, sortB);
            });

            // 遍历所有主表，从明细表获取附件URL进行合并
            for (CostProjectTaskMaterialSummary summary : allSummaryList) {
                logger.info("合并资料：{}", summary.getMaterialName());
                List<CostProjectTaskMaterialSummaryDetail> detailList = summary.getDetailList();
                if (detailList != null && !detailList.isEmpty()) {
                    detailList.sort(Comparator.comparing(d -> d.getOrderNum() != null ? d.getOrderNum() : 0));
                    for (CostProjectTaskMaterialSummaryDetail detail : detailList) {
                        if (StringUtil.isNotEmpty(detail.getAttachmentUrl())) {
                            isFirstDocument = mergeDocumentFile(document, detail.getAttachmentUrl(), isFirstDocument);
                        }
                    }
                }
            }

            // 生成输出文件路径
            String fileName = FileUploadUtil.generateFileName("卷宗_" + taskId + ".docx");
            String outputPath = FileUploadUtil.generateSavePath(
                EipConfig.getUploadPath(), fileName, "docx");

            // 确保目录存在
            java.io.File outputFile = new java.io.File(outputPath);
            if (!outputFile.getParentFile().exists()) {
                outputFile.getParentFile().mkdirs();
            }

            // 保存Word文档
            FileOutputStream out = new FileOutputStream(outputPath);
            document.write(out);
            out.close();
            document.close();

            // 生成访问URL
            String archiveUrl = FileUploadUtil.getPathFileName(outputPath, fileName);

            logger.info("Word卷宗生成完成，任务ID：{}，URL：{}", taskId, archiveUrl);

            // 更新任务的卷宗URL
            if (task != null) {
                task.setArchiveUrl(archiveUrl);
                task.setArchiveStatus("2");
                task.setArchiveTime(LocalDateTime.now());
                costProjectTaskManager.updateById(task);
                logger.info("卷宗URL已更新，任务ID：{}", taskId);
            }

        } catch (Exception e) {
            if (task != null) {
                task.setArchiveStatus("3");
                costProjectTaskManager.updateById(task);
            }
            logger.error("生成Word卷宗失败，任务ID：，错误：{}", taskId, e.getMessage(), e);
        }
    }

    /**
     * 合并单个文档文件到主文档（保持原始样式）
     *
     * @param document 主文档
     * @param fileUrl 文件URL（如：/profile/upload/20251116/xxx.docx）
     * @param isFirstDocument 是否是第一个文档
     * @return 是否是第一个文档（用于下次调用）
     */
    private boolean mergeDocumentFile(XWPFDocument document, String fileUrl, boolean isFirstDocument) {
        try {
            String filePath = fileUrl;
            // 处理路径：/profile 开头的路径需要替换为实际路径
            if (filePath.startsWith("/profile")) {
                filePath = EipConfig.getProfile() + filePath.substring(8);
            }

            java.io.File file = new java.io.File(filePath);
            if (!file.exists()) {
                logger.warn("文件不存在：{}（原始路径：{}）", filePath, fileUrl);
                return isFirstDocument;
            }

            // 添加分页符（非第一个文档）
            if (!isFirstDocument) {
                XWPFParagraph pageBreakPara = document.createParagraph();
                XWPFRun pageBreakRun = pageBreakPara.createRun();
                pageBreakRun.addBreak(BreakType.PAGE);
            }

            // 读取Word文件
            java.io.FileInputStream fis = new java.io.FileInputStream(filePath);
            XWPFDocument sourceDoc = new XWPFDocument(fis);

            // 使用XML级别复制，保持原始样式
            org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody srcBody = sourceDoc.getDocument().getBody();
            org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody destBody = document.getDocument().getBody();

            // 复制所有元素（段落、表格等）
            for (org.apache.xmlbeans.XmlObject obj : srcBody.selectPath("./*")) {
                if (obj instanceof org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP) {
                    // 复制段落
                    org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP newP = destBody.addNewP();
                    newP.set(obj.copy());
                } else if (obj instanceof org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl) {
                    // 复制表格
                    org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl newTbl = destBody.addNewTbl();
                    newTbl.set(obj.copy());
                }
            }

            sourceDoc.close();
            fis.close();

            return false;

        } catch (Exception e) {
            logger.error("合并文件失败：{}，错误：{}", fileUrl, e.getMessage(), e);
            return isFirstDocument;
        }
    }

    /**
     * 更新单个资料归纳主表的总页数
     *
     * @param masterId 主表ID
     */
    public void updateMasterTotalPageCount(String masterId) {
        try {
            CostProjectTaskMaterialSummary summary = costProjectTaskMaterialSummaryManager.getById(masterId);
            if (summary == null) {
                logger.warn("资料归纳主表不存在，ID：{}", masterId);
                return;
            }

            int totalPageCount = 0;

            // 查询该主表的所有明细
            List<CostProjectTaskMaterialSummaryDetail> detailList = costProjectTaskMaterialSummaryDetailManager.list(
                    new LambdaQueryWrapper<CostProjectTaskMaterialSummaryDetail>()
                            .eq(CostProjectTaskMaterialSummaryDetail::getMasterId, masterId)
                            .eq(CostProjectTaskMaterialSummaryDetail::getIsDeleted, "0")
            );

            // 累加所有明细的页数
            for (CostProjectTaskMaterialSummaryDetail detail : detailList) {
                if (detail.getPageCount() != null) {
                    totalPageCount += detail.getPageCount();
                }
            }

            // 更新主表的总页数
            summary.setTotalPageCount(String.valueOf(totalPageCount));
            costProjectTaskMaterialSummaryManager.updateById(summary);

            logger.info("资料归纳【{}】总页数已更新：{}", summary.getMaterialName(), totalPageCount);

        } catch (Exception e) {
            logger.error("更新主表总页数失败，主表ID：{}，错误：{}", masterId, e.getMessage(), e);
        }
    }

    /**
     * 统计每个资料归纳主表的总页数（所有明细的页数之和）
     *
     * @param taskId 任务ID
     */
    public void calculatePageCountAsync(String taskId) {
        try {
            logger.info("开始异步统计页数，任务ID：{}", taskId);

            // 查询任务的所有资料归纳主表
            List<CostProjectTaskMaterialSummary> summaryList = costProjectTaskMaterialSummaryManager.listByTaskId(taskId);

            for (CostProjectTaskMaterialSummary summary : summaryList) {
                int totalPageCount = 0;

                // 获取该主表的所有明细
                if (summary.getDetailList() != null && !summary.getDetailList().isEmpty()) {
                    for (CostProjectTaskMaterialSummaryDetail detail : summary.getDetailList()) {
                        if (StringUtil.isNotEmpty(detail.getAttachmentUrl())) {
                            // 统计该明细的页数
                            int pageCount = calculateFilePageCount(detail.getAttachmentUrl());
                            detail.setPageCount(pageCount);
                            costProjectTaskMaterialSummaryDetailManager.updateById(detail);
                            // 累加到总页数
                            totalPageCount += pageCount;
                        }
                    }
                }

                // 更新主表的总页数
                summary.setTotalPageCount(String.valueOf(totalPageCount));
                costProjectTaskMaterialSummaryManager.updateById(summary);

                logger.info("资料归纳【{}】统计完成，总页数：{}", summary.getMaterialName(), totalPageCount);
            }

            logger.info("页数统计完成，任务ID：{}", taskId);

        } catch (Exception e) {
            logger.error("统计页数失败，任务ID：{}，错误：{}", taskId, e.getMessage(), e);
        }
    }

    /**
     * 计算文件页数（公共方法，可被外部调用）
     *
     * @param fileUrl 文件URL或路径
     * @return 页数
     */
    public int calculateFilePageCount(String fileUrl) {
        try {
            if (StringUtil.isEmpty(fileUrl)) {
                return 0;
            }

            // 判断文件类型
            String lowerCaseUrl = fileUrl.toLowerCase();

            if (lowerCaseUrl.endsWith(".xls") || lowerCaseUrl.endsWith(".xlsx")) {
                // Excel文件算1页
                return 1;
            } else if (lowerCaseUrl.endsWith(".doc") || lowerCaseUrl.endsWith(".docx")) {
                // Word文件需要读取实际页数
                return getWordPageCount(fileUrl);
            } else {
                // 其他格式默认1页
                return 1;
            }

        } catch (Exception e) {
            logger.error("计算文件页数失败，文件：{}，错误：{}", fileUrl, e.getMessage(), e);
            return 0;
        }
    }

    /**
     * 获取Word文档的页数
     *
     * @param fileUrl 文件URL或路径（如：/profile/upload/20251116/xxx.docx）
     * @return 页数
     */
    private int getWordPageCount(String fileUrl) {
        java.io.FileInputStream fis = null;
        XWPFDocument document = null;

        try {
            String filePath = fileUrl;
            if (filePath.startsWith("/profile")) {
                filePath = EipConfig.getProfile() + filePath.substring(8);
            }

            fis = new java.io.FileInputStream(filePath);
            document = new XWPFDocument(fis);

            // 获取页数
            int pageCount = document.getProperties().getExtendedProperties().getUnderlyingProperties().getPages();

            return pageCount > 0 ? pageCount : 1;

        } catch (Exception e) {
            logger.error("读取Word页数失败，文件：{}，错误：{}", fileUrl, e.getMessage(), e);
            // 读取失败默认返回1页
            return 1;
        } finally {
            // 关闭资源
            try {
                if (document != null) {
                    document.close();
                }
                if (fis != null) {
                    fis.close();
                }
            } catch (Exception e) {
                logger.warn("关闭文件流失败：{}", e.getMessage());
            }
        }
    }

    // ==================== 卷宗校对文书生成功能 ====================


    /**
     * 生成卷宗文书（封面/目录/封底）
     * id为空是新增，id不为空是编辑
     *
     * @param req 生成请求
     * @return 生成的文书URL
     */
    public String generateArchiveDocument(com.hotent.project.req.ArchiveProofreadReq req) throws Exception {
        Integer documentType = req.getDocumentType();
        String existingId = req.getRelatedId();

        // 如果id不为空，从数据库获取已有记录的documentType（id是主表ID）
        if (StringUtil.isNotEmpty(existingId)) {
            CostProjectTaskMaterialSummary existing = costProjectTaskMaterialSummaryManager.getById(existingId);
            if (existing == null) {
                throw new RuntimeException("主表记录不存在：" + existingId);
            }
            Integer orderNum = existing.getMaterialOrderNum();
            if (orderNum != null && orderNum == -1) {
                documentType = 1;
            } else if (orderNum != null && orderNum == -2) {
                documentType = 2;
            } else if (orderNum != null && orderNum == -3) {
                documentType = 3;
            } else {
                throw new RuntimeException("无效的文书记录");
            }
        }

        String templatePath;
        String documentName;

        switch (documentType) {
            case 1:
                templatePath = coverTemplatePath;
                documentName = "案卷封面";
                if (StringUtil.isEmpty(templatePath)) {
                    throw new RuntimeException("案卷封面模板路径未配置");
                }
                break;
            case 2:
                templatePath = catalogTemplatePath;
                documentName = "卷内目录";
                if (StringUtil.isEmpty(templatePath)) {
                    throw new RuntimeException("卷内目录模板路径未配置");
                }
                break;
            case 3:
                templatePath = backCoverTemplatePath;
                documentName = "案卷封底";
                if (StringUtil.isEmpty(templatePath)) {
                    throw new RuntimeException("案卷封底模板路径未配置");
                }
                break;
            default:
                throw new RuntimeException("不支持的文书类型：" + documentType);
        }

        // 检查模板文件是否存在
        java.io.File templateFile = new java.io.File(templatePath);
        if (!templateFile.exists()) {
            throw new RuntimeException("模板文件不存在：" + templatePath);
        }

        // 生成文书
        String outputUrl = generateDocumentFromTemplate(templatePath, documentName, req);

        // 保存到数据库（主表+明细表）
        int orderNum = -documentType; // -1封面、-2目录、-3封底
        String masterId;

        if (StringUtil.isNotEmpty(existingId)) {
            // 编辑：existingId是主表ID，查找对应的明细记录
            masterId = existingId;
            CostProjectTaskMaterialSummary existingSummary = costProjectTaskMaterialSummaryManager.getById(masterId);
            if (existingSummary != null) {
                // 更新task的卷宗号和归档人
                CostProjectTask task = costProjectTaskManager.getById(existingSummary.getTaskId());
                if (task != null) {
                    task.setArchiveNo(req.getArchiveNo());
                    task.setArchiveUser(ContextUtil.getCurrentUser().getAccount());
                    costProjectTaskManager.updateById(task);
                }
            }
            CostProjectTaskMaterialSummaryDetail existingDetail = costProjectTaskMaterialSummaryDetailManager.getOne(
                new LambdaQueryWrapper<CostProjectTaskMaterialSummaryDetail>()
                    .eq(CostProjectTaskMaterialSummaryDetail::getMasterId, masterId)
                    .eq(CostProjectTaskMaterialSummaryDetail::getIsDeleted, "0")
            );
            if (existingDetail != null) {
                // 更新已有明细
                existingDetail.setAttachmentUrl(outputUrl);
                existingDetail.setGenerateTime(java.time.LocalDateTime.now());
                costProjectTaskMaterialSummaryDetailManager.updateById(existingDetail);
            } else {
                // 创建新明细
                CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
                detail.setMasterId(masterId);
                detail.setTaskId(req.getTaskId());
                detail.setDocumentName(documentName);
                detail.setFileSource("系统生成电子文书");
                detail.setAttachmentUrl(outputUrl);
                detail.setOrderNum(1);
                detail.setGenerateTime(java.time.LocalDateTime.now());
                detail.setIsDeleted("0");
                costProjectTaskMaterialSummaryDetailManager.save(detail);
            }
        } else {
            // 新增：创建主表记录
            CostProjectTaskMaterialSummary summary = new CostProjectTaskMaterialSummary();
            summary.setTaskId(req.getTaskId());
            summary.setMaterialOrderNum(orderNum);
            summary.setMaterialName(documentName);
            summary.setIsDeleted("0");
            costProjectTaskMaterialSummaryManager.save(summary);
            masterId = summary.getId();
            // 更新task的卷宗号和归档人
            CostProjectTask task = costProjectTaskManager.getById(req.getTaskId());
            if (task != null) {
                task.setArchiveNo(req.getArchiveNo());
                task.setArchiveUser(ContextUtil.getCurrentUser().getAccount());
                costProjectTaskManager.updateById(task);
            }

            // 创建明细记录
            CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
            detail.setMasterId(masterId);
            detail.setTaskId(req.getTaskId());
            detail.setDocumentName(documentName);
            detail.setFileSource("系统生成电子文书");
            detail.setAttachmentUrl(outputUrl);
            detail.setOrderNum(1);
            detail.setGenerateTime(java.time.LocalDateTime.now());
            detail.setIsDeleted("0");
            costProjectTaskMaterialSummaryDetailManager.save(detail);
        }

        return outputUrl;
    }


    /**
     * 根据模板生成文书
     *
     * @param templatePath 模板路径
     * @param documentName 文书名称
     * @param req 请求参数
     * @return 生成的文书URL
     */
    private String generateDocumentFromTemplate(String templatePath, String documentName,
                                                 com.hotent.project.req.ArchiveProofreadReq req) throws Exception {
        java.io.FileInputStream fis = null;
        XWPFDocument document = null;
        java.io.FileOutputStream fos = null;

        try {
            // 读取模板
            fis = new java.io.FileInputStream(templatePath);
            document = new XWPFDocument(fis);

            // 构建替换映射
            Map<String, String> replacements = buildReplacementMap(req);

            // 根据文书类型进行不同处理
            switch (req.getDocumentType()) {
                case 1:
                    // 案卷封面
                    generateCoverDocument(document, replacements);
                    break;
                case 2:
                    // 卷内目录
                    generateCatalogDocument(document, replacements, req.getTaskId());
                    break;
                case 3:
                    // 案卷封底
                    generateBackCoverDocument(document, replacements);
                    break;
            }

            // 生成输出文件路径
            String fileName = FileUploadUtil.generateFileName(documentName + ".docx");
            String outputPath = FileUploadUtil.generateSavePath(
                    EipConfig.getUploadPath(), fileName, "docx");

            // 确保目录存在
            java.io.File outputFile = new java.io.File(outputPath);
            if (!outputFile.getParentFile().exists()) {
                outputFile.getParentFile().mkdirs();
            }

            // 写入文件
            fos = new java.io.FileOutputStream(outputPath);
            document.write(fos);

            // 返回访问URL
            return FileUploadUtil.getPathFileName(outputPath, fileName);

        } finally {
            // 关闭资源
            try {
                if (fos != null) fos.close();
                if (document != null) document.close();
                if (fis != null) fis.close();
            } catch (Exception e) {
                logger.warn("关闭文件流失败：{}", e.getMessage());
            }
        }
    }

    /**
     * 构建替换映射
     * 自动从数据库获取：年份、监审项目名称、被监审单位、监审期间（开始-结束年度）、监审人员、办结时间
     * 需要用户传递：价格主管部门、卷宗号、保管期间周期、立卷人、立卷日期、检查人、检查日期、备注
     */
    private Map<String, String> buildReplacementMap(com.hotent.project.req.ArchiveProofreadReq req) {
        Map<String, String> map = new java.util.HashMap<>();

        // 从数据库获取任务信息
        CostProjectTask task = costProjectTaskManager.getById(req.getTaskId());

        // 从数据库获取立项审批信息（包含监审组人员）
        CostProjectApproval approval = costProjectApprovalManager.getOne(
            new LambdaQueryWrapper<CostProjectApproval>()
                .eq(CostProjectApproval::getProjectId, task.getProjectId())
        );

        // ========== 自动获取的字段 ==========
        Org org = orgManager.getById(approval.getOrgId());
        map.put("{价格主管部门或成本监审机构}", org.getName());
        map.put("{年份}", task.getYear());
        map.put("{监审项目名称}", task.getProjectName());
        map.put("{被监审单位}", task.getAuditedUnitName());

        // 监审期间（解析开始-结束年度，格式如：2024,2025,2023 逗号分隔）
        String startYear = "";
        String endYear = "";
        String auditPeriod = task.getAuditPeriod();
        if (StringUtil.isNotEmpty(auditPeriod)) {
            String[] years = auditPeriod.split(",");
            int minYear = Integer.MAX_VALUE;
            int maxYear = Integer.MIN_VALUE;
            for (String year : years) {
                try {
                    int y = Integer.parseInt(year.trim());
                    if (y < minYear) minYear = y;
                    if (y > maxYear) maxYear = y;
                } catch (NumberFormatException e) {
                }
            }
            if (minYear != Integer.MAX_VALUE) {
                startYear = String.valueOf(minYear);
                endYear = String.valueOf(maxYear);
            }
        }
        map.put("{监审开始年度}", startYear);
        map.put("{监审结束年度}", endYear);

        // 监审组负责人及人员（将ID转换为姓名）
        String auditGroupNames = "";
        if (approval != null && StringUtil.isNotEmpty(approval.getAuditGroup())) {
            String[] userIds = approval.getAuditGroup().split(",");
            StringBuilder names = new StringBuilder();
            for (String userId : userIds) {
                try {
                    User user = userManager.get(userId.trim());
                    if (user != null) {
                        if (names.length() > 0) {
                            names.append(",");
                        }
                        names.append(user.getFullname());
                    }
                } catch (Exception e) {
                }
            }
            auditGroupNames = names.toString();
        }
        map.put("{监审组负责人及人员}", auditGroupNames);

        // 监审办结时间（任务状态为办结时，取更新时间，格式：xxxx年xx月）
        String auditEndTime = "";
        if ("400".equals(task.getStatus()) && task.getUpdateTime() != null) {
            auditEndTime = task.getUpdateTime().getYear() + "年" + task.getUpdateTime().getMonthValue() + "月";
        }
        map.put("{监审办结时间}", auditEndTime);

        // ========== 需要用户传递的字段 ==========
        map.put("{卷宗号}", req.getArchiveNo() != null ? req.getArchiveNo() : "");
        map.put("{保管期间周期}", req.getRetentionPeriod() != null ? req.getRetentionPeriod() : "");

        // ========== 卷宗统计信息 ==========
        // 获取14个资料归纳的总页数
        List<CostProjectTaskMaterialSummary> summaryList = costProjectTaskMaterialSummaryManager.listByTaskId(req.getTaskId());
        summaryList = summaryList.stream()
                .filter(s -> s.getMaterialOrderNum() != null && s.getMaterialOrderNum() > 0)
                .collect(Collectors.toList());
        int totalPageCount = 0;
        for (CostProjectTaskMaterialSummary summary : summaryList) {
            if (summary.getTotalPageCount() != null) {
                try {
                    totalPageCount += Integer.parseInt(summary.getTotalPageCount());
                } catch (NumberFormatException e) {
                }
            }
        }
        map.put("{卷宗件数}", "1"); // 默认1件
        map.put("{卷宗页数}", String.valueOf(totalPageCount));
        map.put("{第几件}", "1"); // 默认第1件

        return map;
    }

    /**
     * 生成案卷封面
     */
    private void generateCoverDocument(XWPFDocument document, Map<String, String> replacements) {
        SmartTemplateWriter.writeToTemplate(document, replacements);
    }

    /**
     * 生成卷内目录（只填充表格，不替换占位符）
     */
    private void generateCatalogDocument(XWPFDocument document, Map<String, String> replacements, String taskId) {
        // 获取资料归纳列表，生成目录表格
        List<CostProjectTaskMaterialSummary> summaryList = costProjectTaskMaterialSummaryManager.listByTaskId(taskId);

        // 过滤掉封面、目录、封底（负数序号）
        summaryList = summaryList.stream()
                .filter(s -> s.getMaterialOrderNum() != null && s.getMaterialOrderNum() > 0)
                .sorted(Comparator.comparing(CostProjectTaskMaterialSummary::getMaterialOrderNum))
                .collect(Collectors.toList());

        // 构建目录数据
        List<CompleteTemplateProcessor.TableRowData> tableDataList = new java.util.ArrayList<>();
        int currentPage = 1;

        for (CostProjectTaskMaterialSummary summary : summaryList) {
            CompleteTemplateProcessor.TableRowData rowData =
                    new CompleteTemplateProcessor.TableRowData();
            rowData.setDocumentName(summary.getMaterialName());

            int pageCount = 0;
            if (summary.getTotalPageCount() != null) {
                try {
                    pageCount = Integer.parseInt(summary.getTotalPageCount());
                } catch (NumberFormatException e) {
                    pageCount = 0;
                }
            }
            rowData.setPageCount(pageCount);

            // 计算页码范围作为备注
            if (pageCount > 0) {
                rowData.setRemark(currentPage + "-" + (currentPage + pageCount - 1));
                currentPage += pageCount;
            } else {
                rowData.setRemark("—");
            }

            tableDataList.add(rowData);
        }

        // 只填充表格数据，
        if (!tableDataList.isEmpty()) {
            processTableData(document, tableDataList);
        }
    }

    /**
     * 生成案卷封底
     */
    private void generateBackCoverDocument(XWPFDocument document, Map<String, String> replacements) {
        SmartTemplateWriter.writeToTemplate(document, replacements);
    }

    /**
     * 处理目录表格数据
     */
    private void processTableData(XWPFDocument document, List<CompleteTemplateProcessor.TableRowData> dataList) {
        List<XWPFTable> tables = document.getTables();
        if (tables.isEmpty()) {
            logger.warn("未找到表格");
            return;
        }

        XWPFTable table = tables.get(0);

        // 找到模板行（第二行，第一行是表头）
        int templateRowIndex = 0;
        if (table.getRows().size() <= templateRowIndex) {
            logger.warn("表格行数不足");
            return;
        }

        // 获取模板行的单元格数量
        int cellCount = table.getRow(templateRowIndex).getTableCells().size();

        // 删除模板行
        table.removeRow(templateRowIndex);

        // 从模板行位置开始插入数据行
        for (int i = 0; i < dataList.size(); i++) {
            CompleteTemplateProcessor.TableRowData data = dataList.get(i);
            XWPFTableRow newRow = table.insertNewTableRow(templateRowIndex + i);
            // 创建单元格
            for (int j = 0; j < cellCount; j++) {
                newRow.addNewTableCell();
            }
            fillTableRow(newRow, i + 1, data);
        }
    }

    /**
     * 填充表格行数据
     */
    private void fillTableRow(XWPFTableRow row, int sequence,
                               CompleteTemplateProcessor.TableRowData data) {
        List<XWPFTableCell> cells = row.getTableCells();
        if (cells.size() >= 4) {
            setCellText(cells.get(0), String.valueOf(sequence));
            setCellText(cells.get(1), data.getDocumentName());
            setCellText(cells.get(2), data.getPageCount() > 0 ? String.valueOf(data.getPageCount()) : "");
            setCellText(cells.get(3), data.getRemark() != null ? data.getRemark() : "");
        }
    }

    /**
     * 设置单元格文本
     */
    private void setCellText(XWPFTableCell cell, String text) {
        // 清除现有内容
        for (int i = cell.getParagraphs().size() - 1; i >= 0; i--) {
            cell.removeParagraph(i);
        }
        // 添加新内容
        XWPFParagraph paragraph = cell.addParagraph();
        XWPFRun run = paragraph.createRun();
        run.setText(text);
        paragraph.setAlignment(ParagraphAlignment.CENTER);
    }

 }
