package com.gxwebsoft.ai.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.aliyun.bailian20231229.Client;
import com.aliyun.bailian20231229.models.RetrieveResponse;
import com.aliyun.bailian20231229.models.RetrieveResponseBody.RetrieveResponseBodyDataNodes;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.config.KnowledgeBaseConfig;
import com.gxwebsoft.ai.factory.KnowledgeBaseClientFactory;
import com.gxwebsoft.ai.service.AuditReportService;
import com.gxwebsoft.ai.util.AiCloudKnowledgeBaseUtil;
import com.gxwebsoft.pwl.entity.PwlProject;
import com.gxwebsoft.pwl.entity.PwlProjectLibrary;
import com.gxwebsoft.pwl.service.PwlProjectLibraryService;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.ai.dto.AuditReportSaveRequest;
import com.gxwebsoft.ai.entity.AuditEvidence;
import com.gxwebsoft.ai.entity.AuditReport;
import com.gxwebsoft.ai.mapper.AuditEvidenceMapper;
import com.gxwebsoft.ai.mapper.AuditReportMapper;
import com.gxwebsoft.common.core.Constants;
import com.gxwebsoft.common.core.web.ApiResult;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class AuditReportServiceImpl extends ServiceImpl<AuditReportMapper, AuditReport> implements AuditReportService {

    @Autowired
    private KnowledgeBaseClientFactory clientFactory;

    @Autowired
    private KnowledgeBaseConfig config;
    
    @Autowired
    private PwlProjectLibraryService pwlProjectLibraryService;
    
    @Autowired
    private AuditEvidenceMapper auditEvidenceMapper;

    // 工作流配置
    private static final String QUESTION_GENERATION_WORKFLOW_URL = "http://1.14.159.185:8180/v1/workflows/run";
    private static final String QUESTION_GENERATION_TOKEN = "Bearer app-vqbecZtTGmpGL5YhQzsy0Ctr";
    
    private static final String QUESTION_ANALYSIS_WORKFLOW_URL = "http://1.14.159.185:8180/v1/workflows/run";
    private static final String QUESTION_ANALYSIS_TOKEN = "Bearer app-5CQWPxctsPape0HePWA3cP4Y";

    private static final String QUOTA_STR = "1.《中华人民共和国审计法》；\n" +
            "2.《中华人民共和国注册会计师法》；\n" +
            "3.《中国注册会计师执业准则》；\n" +
            "4.《党政主要领导干部和国有企事业单位主要领导人员经济责任审计规定》（中办发〔2019〕45号）（以下简称“两办《规定》”）；\n" +
            "5.《企业国有资本保值增值结果确认暂行办法》（国资委令第9号）；";

    @Override
    public JSONObject generateCompleteAuditReport(String auditContent, String fileName, 
                                                String kbId, String libraryIds, 
                                                String analysisLibrary, String projectLibrary,
                                                String userName) {
        
        List<String> idList = StrUtil.split(libraryIds, ',');
        List<PwlProjectLibrary> ret = pwlProjectLibraryService.list(new LambdaQueryWrapper<PwlProjectLibrary>().in(PwlProjectLibrary::getId, idList));
        String libraryKbIds = ret.stream().map(PwlProjectLibrary::getKbId).collect(Collectors.joining(","));
        
        JSONObject result = new JSONObject();
        
        // 1. 从知识库召回相关规定
        List<String> regulations = retrieveRegulations(auditContent, kbId, libraryKbIds);
        
        // 2. 生成审计问题列表
        JSONArray questionList = generateAuditQuestions(auditContent, regulations, userName);
        
        // 3. 分析每个问题
        JSONArray findings = analyzeQuestions(questionList, analysisLibrary, projectLibrary, userName);
        
        // 4. 构建返回结果
        result.put("source_file", fileName);
        result.put("audit_content", auditContent);
        result.put("total_questions", questionList.size());
        result.put("total_findings", findings.size());
        result.put("findings", findings);
        result.put("generated_time", new Date().toString());
        
        return result;
    }

    /**
     * 从知识库召回相关规定
     */
    private List<String> retrieveRegulations(String auditContent, String kbId, String libraryKbIds) {
        List<String> regulations = new ArrayList<>();
        String query = buildRegulationQuery(auditContent);
        
        // 主知识库
        if (StrUtil.isNotBlank(kbId)) {
            regulations.addAll(queryKnowledgeBase(kbId, query, 10));
        }
        
        // 多个库
        if (StrUtil.isNotBlank(libraryKbIds)) {
            for (String libId : libraryKbIds.split(",")) {
                if (StrUtil.isNotBlank(libId.trim())) {
                    regulations.addAll(queryKnowledgeBase(libId.trim(), query, 5));
                }
            }
        }
        
        return regulations.stream().distinct().collect(Collectors.toList());
    }

    /**
     * 生成审计问题列表
     */
    private JSONArray generateAuditQuestions(String auditContent, List<String> regulations, String userName) {
        // 构建知识上下文
        String knowledgeContext = buildKnowledgeContext(auditContent, regulations);
        
        JSONObject requestBody = buildQuestionGenerationRequest(knowledgeContext, userName);

        return callQuestionGenerationWorkflow(requestBody);
    }

    /**
     * 分析每个问题
     */
    private JSONArray analyzeQuestions(JSONArray questions, String analysisLib, String projectLib, String userName) {
        JSONArray findings = new JSONArray();
        
        for (int i = 0; i < questions.size(); i++) {
            JSONObject question = questions.getJSONObject(i);
            
            // 从两个库召回证据
            List<String> analysisEvidence = retrieveEvidence(question.toJSONString(), analysisLib);
            List<String> projectEvidence = retrieveEvidence(question.toJSONString(), projectLib);
            
            // 调用工作流分析
            JSONArray analysisResult = analyzeSingleQuestion(question, analysisEvidence, projectEvidence, userName);
            
            if (analysisResult != null && !analysisResult.isEmpty()) {
                JSONObject finding = analysisResult.getJSONObject(0);
                // 添加索引
                finding.put("index", i + 1);
                findings.add(finding);
            }
        }
        
        return findings;
    }

    /**
     * 召回证据
     */
    private List<String> retrieveEvidence(String question, String libraryId) {
        if (StrUtil.isBlank(libraryId)) return new ArrayList<>();
        return new ArrayList<>(queryKnowledgeBase(libraryId, question, 5));
    }

    /**
     * 分析单个问题
     */
    private JSONArray analyzeSingleQuestion(JSONObject question, List<String> analysisEvidence, 
                                          List<String> projectEvidence, String userName) {
        
        String evidenceContext = buildEvidenceContext(analysisEvidence, projectEvidence);
        String questionText = buildQuestionText(question);
        
        JSONObject requestBody = buildQuestionAnalysisRequest(questionText, evidenceContext, userName);
        
        return callQuestionAnalysisWorkflow(requestBody);
    }

    /**
     * 构建问题文本
     */
    private String buildQuestionText(JSONObject question) {
        StringBuilder sb = new StringBuilder();
        sb.append("问题表述: ").append(question.getString("问题表述")).append("\n");
        sb.append("问题明细: ").append(question.getString("问题明细")).append("\n");
        sb.append("法规依据: ").append(question.getString("法规依据"));
        return sb.toString();
    }

    /**
     * 构建知识上下文
     */
    private String buildKnowledgeContext(String auditContent, List<String> regulations) {
        StringBuilder context = new StringBuilder();
        context.append("审计内容：\n").append(auditContent).append("\n\n");
        if (!regulations.isEmpty()) {
            context.append("相关规定：\n");
            regulations.forEach(reg -> context.append("- ").append(reg).append("\n"));
        }
        return context.toString();
    }

    /**
     * 构建证据上下文
     */
    private String buildEvidenceContext(List<String> analysisEvidence, List<String> projectEvidence) {
        StringBuilder context = new StringBuilder();
        
        if (!analysisEvidence.isEmpty()) {
            context.append("分析库证据：\n");
            analysisEvidence.forEach(ev -> context.append("- ").append(ev).append("\n"));
        }
        
        if (!projectEvidence.isEmpty()) {
            context.append("项目库证据：\n");
            projectEvidence.forEach(ev -> context.append("- ").append(ev).append("\n"));
        }
        
        return context.toString().trim();
    }

    /**
     * 调用问题生成工作流
     */
    private JSONArray callQuestionGenerationWorkflow(JSONObject requestBody) {
        try {
            String result = HttpUtil.createPost(QUESTION_GENERATION_WORKFLOW_URL)
                    .header("Authorization", QUESTION_GENERATION_TOKEN)
                    .header("Content-Type", "application/json")
                    .body(requestBody.toString())
                    .timeout(600000)
                    .execute()
                    .body();
            
            JSONObject jsonResponse = JSONObject.parseObject(result);
            String outputText = jsonResponse.getJSONObject("data")
                                           .getJSONObject("outputs")
                                           .getString("result");
            
            // 解析JSON数组
            return JSONArray.parseArray(outputText);
            
        } catch (Exception e) {
            throw new RuntimeException("调用问题生成工作流失败: " + e.getMessage(), e);
        }
    }

    /**
     * 调用问题分析工作流
     */
    private JSONArray callQuestionAnalysisWorkflow(JSONObject requestBody) {
        try {
            String result = HttpUtil.createPost(QUESTION_ANALYSIS_WORKFLOW_URL)
                    .header("Authorization", QUESTION_ANALYSIS_TOKEN)
                    .header("Content-Type", "application/json")
                    .body(requestBody.toString())
                    .timeout(600000)
                    .execute()
                    .body();
            
            JSONObject jsonResponse = JSONObject.parseObject(result);
            String outputText = jsonResponse.getJSONObject("data")
                                           .getJSONObject("outputs")
                                           .getString("result");
            
            // 解析JSON数组
            return JSONArray.parseArray(outputText);
            
        } catch (Exception e) {
            System.err.println("分析问题失败: " + e.getMessage());
            // 返回默认结构，避免整个流程中断
            return createDefaultFinding();
        }
    }

    /**
     * 创建默认的发现条目
     */
    private JSONArray createDefaultFinding() {
        JSONObject finding = new JSONObject();
        finding.put("是否存在相关问题", "false");
        finding.put("问题表述", "");
        finding.put("问题明细", "");
        finding.put("法规依据", "");
        finding.put("涉及金额（万元）", "/");
        finding.put("具体责任界定", "/");
        finding.put("整改类型", "/");
        finding.put("整改要求", "/");
        finding.put("整改时限", "/");
        finding.put("审计建议", "/");
        
        JSONArray array = new JSONArray();
        array.add(finding);
        return array;
    }

    /**
     * 构建问题生成工作流请求
     */
    private JSONObject buildQuestionGenerationRequest(String knowledge, String userName) {
        JSONObject requestBody = new JSONObject();
        JSONObject inputs = new JSONObject();
        
        inputs.put("knowledge", knowledge);
        
        requestBody.put("inputs", inputs);
        requestBody.put("response_mode", "blocking");
        requestBody.put("user", userName);
        
        return requestBody;
    }

    /**
     * 构建问题分析工作流请求
     */
    private JSONObject buildQuestionAnalysisRequest(String query, String knowledge, String userName) {
        JSONObject requestBody = new JSONObject();
        JSONObject inputs = new JSONObject();
        
        inputs.put("query", query);
        inputs.put("knowledge", knowledge);
        
        requestBody.put("inputs", inputs);
        requestBody.put("response_mode", "blocking");
        requestBody.put("user", userName);
        
        return requestBody;
    }

    /**
     * 查询知识库
     */
    private Set<String> queryKnowledgeBase(String kbId, String query, int topK) {
        Set<String> results = new LinkedHashSet<>();
        String workspaceId = config.getWorkspaceId();

        try {
            Client client = clientFactory.createClient();
            RetrieveResponse resp = AiCloudKnowledgeBaseUtil.retrieveIndex(client, workspaceId, kbId, query);
            
            if (resp.getBody() != null && resp.getBody().getData() != null 
                && resp.getBody().getData().getNodes() != null) {
                
                for (RetrieveResponseBodyDataNodes node : resp.getBody().getData().getNodes()) {
                    results.add(node.getText());
                    if (results.size() >= topK) break;
                }
            }
        } catch (Exception e) {
            // 记录日志但不中断流程
            System.err.println("查询知识库失败: " + e.getMessage());
        }
        
        return results;
    }

    /**
     * 构建法规查询
     */
    private String buildRegulationQuery(String auditContent) {
        String[] keywords = {"制度", "办法", "规定", "流程", "标准", "规范", "要求"};
        return String.join(" ", keywords);
    }

    @Override
    public ApiResult<AuditReport> saveAuditReport(AuditReportSaveRequest request) {
        log.info("开始保存审计报告 - 用户：{}, 项目：{}", request.getAuditedTarget(), request.getProjectName());
        
        try {
            // 1. 验证必填字段
            if (request.getProjectId() == null) {
                return new ApiResult<>(1, "项目编号不能为空");
            }
            
            if (request.getFormCommit() == null) {
                return new ApiResult<>(1, "表单提交标识不能为空");
            }
            
            // 2. 检查是否已存在（根据projectId + formCommit）
            LambdaQueryWrapper<AuditReport> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(AuditReport::getProjectId, request.getProjectId())
                       .eq(AuditReport::getFormCommit, request.getFormCommit())
                       .eq(AuditReport::getDeleted, 0);
            
            AuditReport existingReport = baseMapper.selectOne(queryWrapper);
            
            AuditReport auditReport;
            if (existingReport != null) {
                // 3. 更新现有记录
                log.info("发现已存在的记录，执行更新操作 - ID: {}", existingReport.getId());
                auditReport = existingReport;
                
                // 更新字段
                auditReport.setProjectName(request.getProjectName());
                auditReport.setCaseIndex(request.getCaseIndex());
                auditReport.setAuditedTarget(request.getAuditedTarget());
                auditReport.setReportContent(request.getReportContent());
                auditReport.setPreviewHtml(request.getPreviewHtml());
                auditReport.setSectionCount(request.getSectionCount());
                
                // 更新数据库
                baseMapper.updateById(auditReport);
                
                log.info("审计报告更新成功 - ID: {}", auditReport.getId());
            } else {
                // 4. 新增记录
                log.info("未发现已存在的记录，执行新增操作");
                auditReport = new AuditReport();
                
                // 基本信息
                auditReport.setProjectId(request.getProjectId());
                auditReport.setProjectName(request.getProjectName());
                auditReport.setCaseIndex(request.getCaseIndex());
                auditReport.setAuditedTarget(request.getAuditedTarget());
                auditReport.setReportContent(request.getReportContent());
                auditReport.setPreviewHtml(request.getPreviewHtml());
                auditReport.setSectionCount(request.getSectionCount());
                auditReport.setFormCommit(request.getFormCommit());
                
                // 保存到数据库
                baseMapper.insert(auditReport);
                
                log.info("审计报告保存成功 - ID: {}", auditReport.getId());
            }
            
            // 设置 success 标志
            auditReport.setSuccess(true);
            
            return new ApiResult<>(Constants.RESULT_OK_CODE, Constants.RESULT_OK_MSG, auditReport);
            
        } catch (Exception e) {
            log.error("保存审计报告到数据库失败", e);
            return new ApiResult<>(1, "保存审计报告失败：" + e.getMessage());
        }
    }

    @Override
    public ApiResult<AuditReport> queryAuditReport(Integer projectId, Integer formCommit) {
        log.info("查询审计报告 - 项目 ID: {}, formCommit: {}", projectId, formCommit);
        
        try {
            if (projectId == null || formCommit == null) {
                return new ApiResult<>(1, "项目编号和表单提交标识不能为空");
            }
            
            // 根据projectId + formCommit 查询
            LambdaQueryWrapper<AuditReport> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(AuditReport::getProjectId, projectId)
                       .eq(AuditReport::getFormCommit, formCommit)
                       .eq(AuditReport::getDeleted, 0);
            
            AuditReport auditReport = baseMapper.selectOne(queryWrapper);
            
            if (auditReport != null) {
                log.info("查询到审计报告 - ID: {}", auditReport.getId());
                auditReport.setSuccess(true);
                return new ApiResult<>(Constants.RESULT_OK_CODE, Constants.RESULT_OK_MSG, auditReport);
            } else {
                log.info("未查询到审计报告");
                return new ApiResult<>(Constants.RESULT_OK_CODE, "未查询到记录", null);
            }
            
        } catch (Exception e) {
            log.error("查询审计报告失败", e);
            return new ApiResult<>(1, "查询审计报告失败：" + e.getMessage());
        }
    }
    
    @Override
    public Map<String, Object> queryAuditDataByProjectId(PwlProject project, List<Long> selectedEvidenceIds) {
        // 调用新方法，不传入 selectedEvidenceIds（兼容旧接口）
        return queryAuditDataByProjectIdWithAnalysis(project, selectedEvidenceIds);
    }
    
    /**
     * 根据项目 ID 查询审计报告和取证单数据，并对勾选的取证单进行 AI 分析
     * @param project 项目 ID
     * @param selectedEvidenceIds 勾选的取证单 ID 列表（可为 null）
     * @return 包含 reports、evidences、evaluate、suggestion 的 Map
     */
    @Override
    public Map<String, Object> queryAuditDataByProjectIdWithAnalysis(PwlProject project, List<Long> selectedEvidenceIds) {
        Integer projectId = project.getId();
        log.info("=== 开始查询审计数据 ===");
        log.info("项目 ID: {}, 勾选取证单 IDs: {}", projectId, selectedEvidenceIds);

        Map<String, Object> result = new HashMap<>();

        // 添加章节顺序配置，供前端使用
        List<Map<String, Object>> sectionOrder = new ArrayList<>();
        sectionOrder.add(createSectionInfo(1, "基本情况", Arrays.asList(41, 42, 43)));
        sectionOrder.add(createSectionInfo(2, "总体评价", null));
        sectionOrder.add(createSectionInfo(3, String.format("%s主要业绩", project.getPersonName()), null));
        sectionOrder.add(createSectionInfo(4, "履行经济责任的主要情况及审计发现的问题与责任认定", Arrays.asList(51, 52, 53, 54, 55, 56, 57)));
        sectionOrder.add(createSectionInfo(5, "审计建议", null));
        sectionOrder.add(createSectionInfo(6, "其他事项说明", null));
        result.put("sectionOrder", sectionOrder);
        
        try {
            if (projectId == null) {
                log.warn("项目 ID 为 null，返回空结果");
                result.put("reports", new ArrayList<>());
                result.put("evidences", new ArrayList<>());
                result.put("evaluate", "");
                result.put("suggestion", "");
                return result;
            }
            
            // 1. 查询审计报告数据
            log.info("正在查询审计报告...");
            List<AuditReport> reports = new ArrayList<>();
            AuditReport report10 = new AuditReport();
            report10.setFormCommit(10);
            report10.setProjectId(projectId);
            report10.setReportContent(QUOTA_STR);
            reports.add(report10);

            LambdaQueryWrapper<AuditReport> reportWrapper = new LambdaQueryWrapper<>();
            reportWrapper.eq(AuditReport::getProjectId, projectId)
                       .eq(AuditReport::getDeleted, 0)
                        .in(AuditReport::getFormCommit, Arrays.asList(41, 42, 43))
                       .orderByAsc(AuditReport::getFormCommit);

            List<AuditReport> reportList = baseMapper.selectList(reportWrapper);
            if(CollectionUtil.isNotEmpty(reportList)){
                reports.addAll(reportList);
            }
            log.info("查询到 {} 条审计报告记录", reports.size());
            
            // 2. 查询审计取证单数据 - 查询该项目下所有的取证单
            log.info("正在查询审计取证单...");
            LambdaQueryWrapper<AuditEvidence> evidenceWrapper = new LambdaQueryWrapper<>();
            evidenceWrapper.eq(AuditEvidence::getProjectId, projectId)
                       .eq(AuditEvidence::getDeleted, 0)
                       .orderByAsc(AuditEvidence::getId);

            List<AuditEvidence> evidences = auditEvidenceMapper.selectList(evidenceWrapper);
            log.info("查询到 {} 条审计取证单记录", evidences.size());
            
            result.put("reports", reports);
            result.put("evidences", evidences);
            
            // 3. 获取项目信息（用于获取项目名称）
            String projectName = project.getName() != null ? project.getName() : "";
            result.put("projectName", projectName);  // 添加项目名称到返回结果
            log.info("项目名称：{}", projectName);
            
            // 生成审计引言
            String auditIntro = generateAuditIntro(project);
            result.put("auditIntro", auditIntro);  // 添加审计引言到返回结果
            
            // 生成其他事项说明
            String otherMatters = generateOtherMatters(project);
            result.put("otherMatters", otherMatters);  // 添加其他事项说明到返回结果
            
            // 4. 如果传入了勾选的取证单 ID，进行字段叠加
            if (selectedEvidenceIds != null && !selectedEvidenceIds.isEmpty()) {
                log.info("开始对 {} 条勾选的取证单进行字段叠加", selectedEvidenceIds.size());
//                LambdaQueryWrapper<AuditEvidence> evidenceWrapper = new LambdaQueryWrapper<>();
//                evidenceWrapper.eq(AuditEvidence::getProjectId, projectId)
//                           .eq(AuditEvidence::getDeleted, 0)
//                           .orderByAsc(AuditEvidence::getId);
                
                // 筛选出勾选的取证单
                List<AuditEvidence> selectedEvidences = evidences.stream()
                    .filter(e -> selectedEvidenceIds.contains(e.getId()))
                    .collect(Collectors.toList());
//                List<AuditEvidence> selectedEvidences = auditEvidenceMapper.selectList(evidenceWrapper);
                log.info("实际筛选出 {} 条取证单进行叠加", selectedEvidences.size());
                
                if (!selectedEvidences.isEmpty()) {
                    // 叠加字段内容
                    String evaluate = concatenateField(selectedEvidences, "auditFinding");
                    String suggestion = concatenateField(selectedEvidences, "suggestion");
                    result.put("evaluate", evaluate);
                    result.put("suggestion", suggestion);
                    
                    log.info("字段叠加完成，评价字数：{}，建议字数：{}", 
                        evaluate.length(), 
                        suggestion.length());
                } else {
                    log.info("没有筛选到勾选的取证单，返回空的评价和建议");
                    result.put("evaluate", "");
                    result.put("suggestion", "");
                }
            } else {
                // 没有勾选，返回空值
                log.info("未传入勾选的取证单 ID，返回空的评价和建议");
                result.put("evaluate", "");
                result.put("suggestion", "");
            }
            
            log.info("=== 审计数据查询完成 ===");
            return result;
            
        } catch (Exception e) {
            log.error("根据项目 ID 查询审计数据失败，异常信息：{}", e.getMessage(), e);
            result.put("reports", new ArrayList<>());
            result.put("evidences", new ArrayList<>());
            result.put("evaluate", "");
            result.put("suggestion", "");
            return result;
        }
    }
    
    /**
     * 生成审计引言段落
     * @param project 项目信息
     * @return 审计引言文本
     */
    private String generateAuditIntro(PwlProject project) {
        if (project == null) {
            return "我们接受委托，自 20XX 年 XX 月 XX 日至 20XX 年 XX 月 XX 日，对 XX 同志自 20XX 年 XX 月 XX 日至 20XX 年 XX 月 XX 日担任公司董事长（具体职务）期间的经济责任履行情况进行了就地审计。公司及 XX 同志的责任是提供与本次审计相关的全部资料，并保证其真实、完整。我们的责任是在实施审计工作的基础上发表审计意见。审计工作为发表意见提供了合理基础。现将审计情况报告如下：";
        }

        String intro = "我们接受%s委托，自 20XX 年 XX 月 XX 日至 20XX 年 XX 月 XX 日，对%s自 20XX 年 XX 月 XX 日至 20XX 年 XX 月 XX 日担任%s %s期间的经济责任履行情况进行了就地审计。%s及%s责任是提供与本次审计相关的全部资料，并保证其真实、完整。我们的责任是在实施审计工作的基础上发表审计意见。审计工作为发表意见提供了合理基础。现将审计情况报告如下：";
        
        return String.format(intro, project.getName(), project.getPersonName(), project.getName(), project.getPosition(), project.getName(), project.getPersonName());
    }
    
    /**
     * 生成其他事项说明内容
     * @param project 项目信息
     * @return 其他事项说明文本
     */
    private String generateOtherMatters(PwlProject project) {
        return String.format("（一）本报告依据委托方及 %s 提供的审计相关资料出具，审计意见受所提供资料真实性及完整性的影响。" +
                // 第二段
                "（二）本报告仅供委托方 %s 了解 %s 的经济责任履行情况之用，未经本所书面同意不得用作其他用途，因使用不当造成的后果，与执行本次专项审计业务的注册会计师及会计师事务所无关。", project.getName(), project.getName(), project.getPersonName());
    }

    /**
     * 创建章节信息
     * @param order 章节顺序
     * @param title 章节标题
     * @param formCommits 表单提交标识列表
     * @return 章节信息Map
     */
    private Map<String, Object> createSectionInfo(int order, String title, List<Integer> formCommits) {
        Map<String, Object> sectionInfo = new HashMap<>();
        sectionInfo.put("order", order);
        sectionInfo.put("title", title);
        sectionInfo.put("formCommits", formCommits);
        return sectionInfo;
    }

    private String concatenateField(List<AuditEvidence> selectedEvidences, String fieldName) {
        log.info("开始叠加字段：{}", fieldName);
        StringBuilder result = new StringBuilder();
        
        for (int i = 0; i < selectedEvidences.size(); i++) {
            AuditEvidence evidence = selectedEvidences.get(i);
            String fieldValue = null;
            
            if ("auditFinding".equals(fieldName)) {
                fieldValue = evidence.getAuditFinding();
            } else if ("suggestion".equals(fieldName)) {
                fieldValue = evidence.getSuggestion();
            }
            
            log.info("取证单 ID={}, 序号={}, 字段={}, 值长度={}", 
                evidence.getId(), i+1, fieldName, fieldValue != null ? fieldValue.length() : 0);
            
            if (StrUtil.isNotBlank(fieldValue)) {
                // 添加序号和审计事项作为标题
                String auditMatter = evidence.getAuditMatter();
                String numText = getChineseNumber(i + 1);
                
                if (StrUtil.isNotBlank(auditMatter)) {
                    result.append("(").append(numText).append(") ").append(auditMatter).append("\n");
                } else {
                    result.append("(").append(numText).append(") 事项").append(i + 1).append("\n");
                }
                
                // 将内容按换行符分割，每段都首行缩进
                String[] paragraphs = fieldValue.split("\\n+");
                for (String paragraph : paragraphs) {
                    if (StrUtil.isNotBlank(paragraph.trim())) {
                        result.append("    ").append(paragraph.trim()).append("\n");
                    }
                }
                
                // 如果不是最后一条，添加空行分隔
                if (i < selectedEvidences.size() - 1) {
                    result.append("\n");
                }
            } else {
                log.warn("取证单 ID={}, 字段 {} 为空或空字符串", evidence.getId(), fieldName);
            }
        }
        
        log.info("字段 {} 叠加完成，总长度={}", fieldName, result.length());
        return result.toString();
    }
    
    /**
     * 获取中文序号（一、二、三...十）
     * @param number 数字（1-10）
     * @return 中文序号字符串
     */
    private String getChineseNumber(int number) {
        String[] chineseNumbers = {"零", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十"};
        
        if (number >= 1 && number <= 10) {
            return chineseNumbers[number];
        } else if (number > 10 && number <= 20) {
            return "十" + chineseNumbers[number - 10];
        } else {
            // 超过 20 的数字，直接返回阿拉伯数字
            return String.valueOf(number);
        }
    }
}