package com.fs.doctor.service.impl;

import com.fs.audit.chain.AuditResult;
import com.fs.audit.domain.AuditFlow;
import com.fs.audit.dto.AuditRequestDTO;
import com.fs.audit.dto.CreateAuditRequestDTO;
import com.fs.audit.enums.AuditStatus;
import com.fs.audit.enums.AuditTypeEnum;
import com.fs.audit.exception.BusinessException;
import com.fs.audit.service.AuditService;
import com.fs.audit.utils.AuditFlowUtils;
import com.fs.common.BeanCopyUtils;
import com.fs.common.config.LoginContextManager;
import com.fs.common.core.domain.entity.SysUser;
import com.fs.common.enums.UserTypeEnum;
import com.fs.common.utils.DateUtils;
import com.fs.common.utils.SecurityUtils;
import com.fs.common.utils.StringUtils;
import com.fs.company.domain.CompanyUser;
import com.fs.company.service.ICompanyUserService;
import com.fs.doctor.domain.*;
import com.fs.doctor.enums.DoctorAuditStatus;
import com.fs.doctor.mapper.DoctorLevelApplyMapper;
import com.fs.doctor.mapper.DoctorLevelDataMapper;
import com.fs.doctor.mapper.DoctorLevelMaterialMapper;
import com.fs.doctor.mapper.DynamicSurveyDataMapper;
import com.fs.doctor.service.IDoctorCompanyUserService;
import com.fs.doctor.service.IDoctorLevelApplyService;
import com.fs.doctor.service.IDoctorLevelService;
import com.fs.doctor.service.IDoctorService;
import com.fs.doctor.vo.*;
import com.fs.project.domain.ProjectStandard;
import com.fs.project.service.IProjectStandardService;
import com.fs.survey.domain.SurveyQuestionnaire;
import com.fs.survey.domain.SurveyQuestionnaireVersion;
import com.fs.survey.mapper.DynamicTableMapper;
import com.fs.survey.service.ISurveyQuestionnaireService;
import com.fs.survey.service.ISurveyQuestionnaireVersionService;
import com.fs.survey.vo.DoctorLevelApplyQuestionnaireVO;
import com.fs.survey.vo.DynamicInsertParam;
import com.fs.system.service.ISysUserService;
import com.fs.task.vo.audit_Info.AuditFlowVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.PreparedStatement;
import java.sql.Statement;
import java.util.*;

/**
 * 讲者定级申请Service业务层处理
 *
 * @author fs
 * @date 2025-12-30
 */
@Service
public class DoctorLevelApplyServiceImpl implements IDoctorLevelApplyService {
    @Autowired
    private DoctorLevelApplyMapper doctorLevelApplyMapper;
    @Autowired
    private DoctorLevelMaterialMapper doctorLevelMaterialMapper;
    @Autowired
    private AuditService auditService;
    @Lazy
    @Autowired
    private IDoctorService doctorService;
    @Lazy
    @Autowired
    private ISysUserService sysUserService;
    @Lazy
    @Autowired
    private ICompanyUserService companyUserService;
    @Autowired
    private IDoctorLevelService doctorLevelService;
    @Lazy
    @Autowired
    private IDoctorCompanyUserService doctorCompanyUserService;
    @Autowired
    private DynamicSurveyDataMapper dynamicSurveyDataMapper;
    @Lazy
    @Autowired
    private ISurveyQuestionnaireService surveyQuestionnaireService;
    @Autowired
    private ISurveyQuestionnaireVersionService surveyQuestionnaireVersionService;
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private DoctorLevelDataMapper doctorLevelDataMapper;

    /**
     * 查询讲者定级申请
     *
     * @param id 讲者定级申请主键
     * @return 讲者定级申请
     */
    @Override
    public DoctorLevelApplyVO selectDoctorLevelApplyById(Long id) {
        DoctorLevelApply apply = doctorLevelApplyMapper.selectDoctorLevelApplyById(id);
        if (apply == null) return null;

        DoctorLevelApplyVO vo = BeanCopyUtils.copy(apply, DoctorLevelApplyVO.class);
        List<DoctorLevelMaterial> mats = doctorLevelMaterialMapper.selectByApplyId(id);
        List<DoctorLevelMaterialVO> doctorLevelMaterialVOS = BeanCopyUtils.copyList(mats, DoctorLevelMaterialVO.class);
        vo.setMaterials(doctorLevelMaterialVOS);




        // ========== 动态表单数据回显 ==========
        DoctorLevelApplyQuestionnaireVO companyDoctorLevelApplyQuestionnaire = surveyQuestionnaireService.getAdminDoctorLevelApplyQuestionnaire(apply.getCompanyId());

        Long questionnaireVersionId = companyDoctorLevelApplyQuestionnaire.getVersionId();
        Long dynamicFormId = apply.getFormId();

        if (questionnaireVersionId != null && dynamicFormId != null) {
            try {
                // 查询问卷版本
                SurveyQuestionnaireVersion version = surveyQuestionnaireVersionService
                        .selectSurveyQuestionnaireVersionById(questionnaireVersionId);
                if (version != null) {
                    // 返回 formJson（字符串形式，前端自行解析）
                    vo.setFormJson(version.getFormJson());

                    // 查询动态表数据
                    String tableName = version.getTableName();
                    String sql = String.format("SELECT * FROM %s WHERE id = ?", tableName);
                    Map<String, Object> dynamicData = jdbcTemplate.queryForMap(sql, dynamicFormId);

                    // 移除不需要返回的公共字段
                    dynamicData.remove("id");
                    dynamicData.remove("company_id");
                    dynamicData.remove("version_id");
                    dynamicData.remove("submit_time");
                    dynamicData.remove("user_id");
                    dynamicData.remove("is_anonymous");

                    vo.setDynamicFormData(dynamicData);
                    vo.setDynamicFormData(dynamicData);
                    vo.setFormJson(companyDoctorLevelApplyQuestionnaire.getFormJson());
                }
            } catch (EmptyResultDataAccessException e) {
                // 动态表数据不存在，忽略，保持 dynamicFormData 为空
                vo.setDynamicFormData(new HashMap<>());
            } catch (Exception e) {
                vo.setDynamicFormData(new HashMap<>());
            }
        } else {
            vo.setDynamicFormData(new HashMap<>());
        }
        // ========== 动态表单数据回显结束 ==========

        // 2) 组装返回VO
        vo.setQuestionnaireVersionId(questionnaireVersionId);


        return vo;
    }

    /**
     * 查询讲者定级申请列表
     *
     * @param doctorLevelApply 讲者定级申请
     * @return 讲者定级申请
     */
    @Override
    public List<DoctorLevelApply> selectDoctorLevelApplyList(DoctorLevelApply doctorLevelApply) {
        return doctorLevelApplyMapper.selectDoctorLevelApplyList(doctorLevelApply);
    }


    /**
     * 新增讲者定级申请
     *
     * @param doctorLevelApplyVO 讲者定级申请
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int insertDoctorLevelApply(DoctorLevelApplyVO doctorLevelApplyVO) {
        // 检查是否存在待审核的申请
        checkPendingApply(doctorLevelApplyVO.getDoctorId());

        // 1. 设置创建时间
        doctorLevelApplyVO.setCreateTime(DateUtils.getNowDate());

        // 2. 对象转换：VO -> 实体对象
        DoctorLevelApply doctorLevelApply = BeanCopyUtils.copy(doctorLevelApplyVO, DoctorLevelApply.class);

        // 3. 插入主申请记录
        int rows = doctorLevelApplyMapper.insertDoctorLevelApply(doctorLevelApply);
        if (rows <= 0) {
            return 0;
        }

        // 4. 获取生成的申请ID
        Long applyId = doctorLevelApply.getId();
        if (applyId == null) {
            throw new RuntimeException("插入申请成功但未返回ID");
        }

        // 5. 保存申请相关材料（文件上传等操作）
        saveMaterials(doctorLevelApplyVO.getCompanyId(), applyId, doctorLevelApplyVO.getMaterials());

        // 6. 获取当前登录用户ID
        Long userId = LoginContextManager.getCurrentCompanyUserId();

        // 7. 初始化审核流程
        handleAuditInit(doctorLevelApply, userId);

        // ========== 动态表单数据存储（使用 JdbcTemplate） ==========
        // 7.1 获取前端传入的问卷版本ID，查询对应的版本和动态表名
        Long questionnaireVersionId = doctorLevelApplyVO.getQuestionnaireVersionId();
        if (questionnaireVersionId == null) {
            throw new RuntimeException("问卷版本ID不能为空");
        }
        SurveyQuestionnaireVersion version = surveyQuestionnaireVersionService.selectSurveyQuestionnaireVersionById(questionnaireVersionId);
        String tableName = version.getTableName();
        if(tableName.isEmpty()){
            throw new RuntimeException("医生定级未设置");

        }

        // 7.2 准备动态表单数据
        Map<String, Object> dynamicFormData = doctorLevelApplyVO.getDynamicFormData();
        // 添加公共字段
        dynamicFormData.put("company_id", version.getCompanyId());
        dynamicFormData.put("version_id", version.getId());
        dynamicFormData.put("submit_time", new Date());
        dynamicFormData.put("user_id", userId);
        dynamicFormData.put("is_anonymous", 1);

        // 7.3 动态构建 INSERT SQL
        StringBuilder columns = new StringBuilder();
        StringBuilder placeholders = new StringBuilder();
        List<Object> paramValues = new ArrayList<>();

        for (Map.Entry<String, Object> entry : dynamicFormData.entrySet()) {
            String column = entry.getKey();
            Object value = entry.getValue();
            // 字段名校验：只允许字母、数字、下划线（防止SQL注入）
            if (!column.matches("^[a-zA-Z0-9_]+$")) {
                throw new RuntimeException("非法字段名: " + column);
            }
            columns.append("`").append(column).append("`,");
            placeholders.append("?,");
            paramValues.add(value);
        }
        // 移除末尾逗号
        columns.setLength(columns.length() - 1);
        placeholders.setLength(placeholders.length() - 1);

        String sql = String.format("INSERT INTO %s (%s) VALUES (%s)", tableName, columns.toString(), placeholders.toString());

        // 7.4 执行插入并获取自增主键
        KeyHolder keyHolder = new GeneratedKeyHolder();
        jdbcTemplate.update(connection -> {
            PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
            for (int i = 0; i < paramValues.size(); i++) {
                ps.setObject(i + 1, paramValues.get(i));
            }
            return ps;
        }, keyHolder);

        Long dynamicFormId = keyHolder.getKey().longValue();

        // 7.5 回填 dynamic_form_id 到主申请记录
        DoctorLevelApply update = new DoctorLevelApply();
        update.setId(applyId);
        update.setFormId(dynamicFormId);  // 根据你的实体字段名调整（如 setDynamicFormId）
        doctorLevelApplyMapper.updateDoctorLevelApply(update);

        return rows;
    }



    /**
     * 检查医生是否已有待审核的申请
     * 如果有待审核的申请，则抛出业务异常
     *
     * @param doctorId 医生业务ID
     * @throws BusinessException 如果存在待审核的申请
     */
    private void checkPendingApply(String doctorId) {
        long count = doctorLevelApplyMapper.checkPendingApplyCount(doctorId);
        if (count > 0) {
            throw new BusinessException("该医生已有待审核的申请，请等待审核完成后再提交");
        }

    }

    private void handleAuditInit(DoctorLevelApply doctorLevelApply, Long userId) {
        CreateAuditRequestDTO createAuditRequestDTO = new CreateAuditRequestDTO();
        createAuditRequestDTO.setBusinessId(doctorLevelApply.getId());
        createAuditRequestDTO.setBusinessType(AuditTypeEnum.GRADE_AUDIT.getCode());
        createAuditRequestDTO.setTempCode(AuditTypeEnum.GRADE_AUDIT.getCode());
        createAuditRequestDTO.setInitiatorId(userId);
        createAuditRequestDTO.setCompanyId(doctorLevelApply.getCompanyId());
        Long finishAuditInstanceId = auditService.createAudit(createAuditRequestDTO);
        doctorLevelApply.setAuditInstanceId(finishAuditInstanceId);
        doctorLevelApplyMapper.updateDoctorLevelApplyAuditInstanceId(doctorLevelApply.getId(), doctorLevelApply.getAuditInstanceId());
    }


    @Transactional
    @Override
    public int updateDoctorLevelApply(DoctorLevelApplyVO doctorLevelApplyVO) {
        // 1. 更新主表信息
        doctorLevelApplyVO.setUpdateTime(DateUtils.getNowDate());
        DoctorLevelApply doctorLevelApply = BeanCopyUtils.copy(doctorLevelApplyVO, DoctorLevelApply.class);
        int rows = doctorLevelApplyMapper.updateDoctorLevelApply(doctorLevelApply);
        if (rows <= 0) return 0;

        // 2. 更新证明材料（删除旧文件，插入新文件）
        List<DoctorLevelMaterialVO> doctorLevelMaterialVOList = doctorLevelApplyVO.getMaterials();
        doctorLevelMaterialMapper.deleteDoctorLevelMaterialByDoctorLevelApplyId(doctorLevelApply.getId());
        saveMaterials(doctorLevelApplyVO.getCompanyId(), doctorLevelApplyVO.getId(), doctorLevelMaterialVOList);

        // ========== 3. 更新动态表单数据 ==========
        // 3.1 获取现有申请的 questionnaireVersionId 和 formId
        DoctorLevelApplyVO oldApply = this.selectDoctorLevelApplyById(doctorLevelApplyVO.getId());
        Long questionnaireVersionId = oldApply.getQuestionnaireVersionId();
        Long dynamicFormId = oldApply.getFormId(); // 如果字段是 dynamicFormId 请调整
        if (questionnaireVersionId == null || dynamicFormId == null) {
            return rows;
        }

        // 3.2 获取问卷版本，得到表名
        SurveyQuestionnaireVersion version = surveyQuestionnaireVersionService.selectSurveyQuestionnaireVersionById(questionnaireVersionId);
        if (version == null) {
            throw new RuntimeException("问卷版本不存在，id=" + questionnaireVersionId);
        }
        String tableName = version.getTableName();

        // 3.3 准备动态表单数据（前端提交的用户填写值）
        Map<String, Object> dynamicFormData = doctorLevelApplyVO.getDynamicFormData();
        if (dynamicFormData == null || dynamicFormData.isEmpty()) {
            // 如果没有动态数据需要更新，直接返回
            return rows;
        }

        // 3.4 动态构建 UPDATE SQL
        StringBuilder setClause = new StringBuilder();
        List<Object> params = new ArrayList<>();
        for (Map.Entry<String, Object> entry : dynamicFormData.entrySet()) {
            String column = entry.getKey();
            Object value = entry.getValue();
            // 字段名校验
            if (!column.matches("^[a-zA-Z0-9_]+$")) {
                throw new RuntimeException("非法字段名: " + column);
            }
            setClause.append("`").append(column).append("` = ?,");
            params.add(value);
        }
        // 去除末尾逗号
        setClause.setLength(setClause.length() - 1);
        params.add(dynamicFormId); // WHERE id = ?

        String sql = String.format("UPDATE %s SET %s WHERE id = ?", tableName, setClause.toString());
        jdbcTemplate.update(sql, params.toArray());

        return rows;
    }

    /**
     * 批量删除讲者定级申请
     *
     * @param ids 需要删除的讲者定级申请主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteDoctorLevelApplyByIds(Long[] ids) {
        doctorLevelMaterialMapper.deleteDoctorLevelMaterialByDoctorLevelApplyIds(ids);
        int i = doctorLevelApplyMapper.deleteDoctorLevelApplyByIds(ids);
        return i;


    }

    /**
     * 删除讲者定级申请信息
     *
     * @param id 讲者定级申请主键
     * @return 结果
     */
    @Override
    public int deleteDoctorLevelApplyById(Long id) {
        return doctorLevelApplyMapper.deleteDoctorLevelApplyById(id);
    }

    /**
     * 存储申请文件
     *
     * @param companyId
     * @param applyId
     * @param materials
     */
    private void saveMaterials(Long companyId, Long applyId, List<DoctorLevelMaterialVO> materials) {
        if (materials == null || materials.isEmpty()) return;

        List<DoctorLevelMaterial> list = new ArrayList<>();
        int i = 0;

        for (DoctorLevelMaterialVO m : materials) {
            if (m == null) continue;
            String url = m.getFileUrl();
            if (url == null || url.trim().isEmpty()) continue;

            DoctorLevelMaterial e = new DoctorLevelMaterial();
            e.setCompanyId(companyId);
            e.setApplyId(applyId);
            e.setFileUrl(url.trim());
            e.setFileName(m.getFileName());
            e.setFileSize(m.getFileSize());
            e.setFileType(m.getFileType());
            e.setSortOrder(m.getSortOrder() != null ? m.getSortOrder() : i);
            e.setDeleted(0l);

            list.add(e);
            i++;
        }

        if (!list.isEmpty()) {
            doctorLevelMaterialMapper.batchInsert(list);
        }
    }
    /**
     * 根据动态表名和主键ID查询整行数据，返回 Map（字段名 -> 值）
     */
    private Map<String, Object> selectDynamicFormData(String tableName, Long id) {
        String sql = String.format("SELECT * FROM %s WHERE id = ?", tableName);
        try {
            return jdbcTemplate.queryForMap(sql, id);
        } catch (EmptyResultDataAccessException e) {
            return new HashMap<>();
        }
    }

    @Override
    public DoctorApplyDetailInfoVO getDoctorApplyDetailInfoById(Long id) {
        DoctorApplyDetailInfoVO vo = new DoctorApplyDetailInfoVO();

        // 1) 查询申请主记录
        DoctorLevelApplyVO apply = this.selectDoctorLevelApplyById(id);
        if (apply == null) {
            throw new RuntimeException("定级申请不存在，id=" + id);
        }
        if(apply.getCompanyId()==null){
            throw new RuntimeException("定级申请非法请求");

        }

        // ========== 动态表单数据回显 ==========
        DoctorLevelApplyQuestionnaireVO companyDoctorLevelApplyQuestionnaire = surveyQuestionnaireService.getCompanyDoctorLevelApplyQuestionnaire(apply.getCompanyId());

        Long questionnaireVersionId = companyDoctorLevelApplyQuestionnaire.getVersionId();
        Long dynamicFormId = apply.getFormId(); // 如果实体中是 dynamicFormId，请改为 getDynamicFormId()

        if (questionnaireVersionId != null && dynamicFormId != null) {
            try {
                // 查询问卷版本
                SurveyQuestionnaireVersion version = surveyQuestionnaireVersionService
                        .selectSurveyQuestionnaireVersionById(questionnaireVersionId);
                if (version != null) {
                    // 返回 formJson（字符串形式，前端自行解析）
                    apply.setFormJson(version.getFormJson());

                    // 查询动态表数据
                    String tableName = version.getTableName();
                    String sql = String.format("SELECT * FROM %s WHERE id = ?", tableName);
                    Map<String, Object> dynamicData = jdbcTemplate.queryForMap(sql, dynamicFormId);

                    // 移除不需要返回的公共字段
                    dynamicData.remove("id");
                    dynamicData.remove("company_id");
                    dynamicData.remove("version_id");
                    dynamicData.remove("submit_time");
                    dynamicData.remove("user_id");
                    dynamicData.remove("is_anonymous");

                    apply.setDynamicFormData(dynamicData);
                    vo.setDynamicFormData(dynamicData);
                    vo.setFormJson(companyDoctorLevelApplyQuestionnaire.getFormJson());
                }
            } catch (EmptyResultDataAccessException e) {
                // 动态表数据不存在，忽略，保持 dynamicFormData 为空
                apply.setDynamicFormData(new HashMap<>());
            } catch (Exception e) {
                apply.setDynamicFormData(new HashMap<>());
            }
        } else {
            apply.setDynamicFormData(new HashMap<>());
        }
        // ========== 动态表单数据回显结束 ==========

        // 2) 组装返回VO
        vo.setDoctorLevelApplyVO(apply);
        vo.setQuestionnaireVersionId(questionnaireVersionId);
        // 3) 查询医生信息
        DoctorVO doctorVO = new DoctorVO();
        String doctorId = apply.getDoctorId();
        if (StringUtils.isNotBlank(doctorId)) {
            Doctor doctor = doctorService.selectDoctorByDoctorId(doctorId);
            if (doctor != null) {
                doctorVO = BeanCopyUtils.copy(doctor, DoctorVO.class);
            }
        }

        DoctorLevelData doctorLevelData = new DoctorLevelData();
        doctorLevelData.setCompanyId(apply.getCompanyId());
        doctorLevelData.setSort(Long.valueOf(apply.getApplyLevel()));
        List<DoctorLevelData> doctorLevelDataList = doctorLevelDataMapper.selectDoctorLevelDataList(doctorLevelData);
        if(!doctorLevelDataList.isEmpty()){
            DoctorLevelData doctorLevelData1 = doctorLevelDataList.get(0);
            apply.setApplyLevelName(doctorLevelData1.getLevelName());
        }
        vo.setDoctorVO(doctorVO);



        // 4) 查询审核流程
        Long auditInstanceId = apply.getAuditInstanceId();
        List<AuditFlow> auditFlows = (auditInstanceId == null)
                ? Collections.emptyList()
                : auditService.getAuditFlows(auditInstanceId);

        List<AuditFlowVO> auditFlowVOS = BeanCopyUtils.copyList(auditFlows, AuditFlowVO.class);
        for (AuditFlowVO auditFlowVO : auditFlowVOS) {
            // 审核状态中文
            auditFlowVO.setStatusName(AuditStatus.fromCode(auditFlowVO.getStatus()).getDesc());

            // 统一算出“要展示的审核人ID”
            Long displayUserId = auditFlowVO.getAuditUserId();
            if (displayUserId == null) {
                displayUserId = AuditFlowUtils.parseFirstIdFromAuditUserIds(auditFlowVO.getAuditUserIds());
            }

            if (displayUserId == null) {
                auditFlowVO.setAuditUserName("-");
                continue;
            }

            // 统一算出“审核人类型”
            Integer typeCode = auditFlowVO.getAuditUserType();
            boolean isStep0 = auditFlowVO.getStepNumber() != null && auditFlowVO.getStepNumber() == 0;

            if (typeCode == null) {
                if (isStep0) {
                    typeCode = 1; // 申请人默认系统用户
                } else {
                    typeCode = -1; // 触发兜底双查
                }
            }

            // 根据类型查用户名
            String name = "-";
            if (typeCode == 0) {
                // 销售用户
                CompanyUser cu = companyUserService.selectCompanyUserById(displayUserId);
                if (cu != null) name = cu.getUserName();
            } else if (typeCode == 1) {
                // 系统用户
                SysUser sysUser = sysUserService.selectUserById(displayUserId);
                if (sysUser != null) name = sysUser.getUserName();
            } else {
                // 兜底：先查系统用户，再查销售用户
                SysUser sysUser = sysUserService.selectUserById(displayUserId);
                if (sysUser != null) {
                    name = sysUser.getUserName();
                } else {
                    CompanyUser cu = companyUserService.selectCompanyUserById(displayUserId);
                    if (cu != null) name = cu.getUserName();
                }
            }
            auditFlowVO.setAuditUserName(name);
        }

        vo.setAuditFlowList(auditFlowVOS);
        return vo;
    }


    @Override
    public DoctorApplyDetailInfoVO getAdminDoctorApplyDetailInfoById(Long id) {
        DoctorApplyDetailInfoVO vo = new DoctorApplyDetailInfoVO();


        // 1) 查询申请主记录
        DoctorLevelApplyVO apply = this.selectDoctorLevelApplyById(id);
        if (apply == null) {
            throw new RuntimeException("定级申请不存在，id=" + id);
        }

        // ========== 动态表单数据回显 ==========
        DoctorLevelApplyQuestionnaireVO companyDoctorLevelApplyQuestionnaire = surveyQuestionnaireService.getAdminDoctorLevelApplyQuestionnaire(apply.getCompanyId());

        Long questionnaireVersionId = companyDoctorLevelApplyQuestionnaire.getVersionId();
        Long dynamicFormId = apply.getFormId(); // 如果实体中是 dynamicFormId，请改为 getDynamicFormId()

        if (questionnaireVersionId != null && dynamicFormId != null) {
            try {
                // 查询问卷版本
                SurveyQuestionnaireVersion version = surveyQuestionnaireVersionService
                        .selectSurveyQuestionnaireVersionById(questionnaireVersionId);
                if (version != null) {
                    // 返回 formJson（字符串形式，前端自行解析）
                    apply.setFormJson(version.getFormJson());

                    // 查询动态表数据
                    String tableName = version.getTableName();
                    String sql = String.format("SELECT * FROM %s WHERE id = ?", tableName);
                    Map<String, Object> dynamicData = jdbcTemplate.queryForMap(sql, dynamicFormId);

                    // 移除不需要返回的公共字段
                    dynamicData.remove("id");
                    dynamicData.remove("company_id");
                    dynamicData.remove("version_id");
                    dynamicData.remove("submit_time");
                    dynamicData.remove("user_id");
                    dynamicData.remove("is_anonymous");

                    apply.setDynamicFormData(dynamicData);
                    vo.setDynamicFormData(dynamicData);
                    vo.setFormJson(companyDoctorLevelApplyQuestionnaire.getFormJson());
                }
            } catch (EmptyResultDataAccessException e) {
                // 动态表数据不存在，忽略，保持 dynamicFormData 为空
                apply.setDynamicFormData(new HashMap<>());
            } catch (Exception e) {
                apply.setDynamicFormData(new HashMap<>());
            }
        } else {
            apply.setDynamicFormData(new HashMap<>());
        }
        // ========== 动态表单数据回显结束 ==========

        // 2) 组装返回VO
        vo.setDoctorLevelApplyVO(apply);
        vo.setQuestionnaireVersionId(questionnaireVersionId);
        // 3) 查询医生信息
        DoctorVO doctorVO = new DoctorVO();
        String doctorId = apply.getDoctorId();
        if (StringUtils.isNotBlank(doctorId)) {
            Doctor doctor = doctorService.selectDoctorByDoctorId(doctorId);
            if (doctor != null) {
                doctorVO = BeanCopyUtils.copy(doctor, DoctorVO.class);
            }
        }
        vo.setDoctorVO(doctorVO);

        // 4) 查询审核流程
        Long auditInstanceId = apply.getAuditInstanceId();
        List<AuditFlow> auditFlows = (auditInstanceId == null)
                ? Collections.emptyList()
                : auditService.getAuditFlows(auditInstanceId);

        List<AuditFlowVO> auditFlowVOS = BeanCopyUtils.copyList(auditFlows, AuditFlowVO.class);
        for (AuditFlowVO auditFlowVO : auditFlowVOS) {
            // 审核状态中文
            auditFlowVO.setStatusName(AuditStatus.fromCode(auditFlowVO.getStatus()).getDesc());

            // 统一算出“要展示的审核人ID”
            Long displayUserId = auditFlowVO.getAuditUserId();
            if (displayUserId == null) {
                displayUserId = AuditFlowUtils.parseFirstIdFromAuditUserIds(auditFlowVO.getAuditUserIds());
            }

            if (displayUserId == null) {
                auditFlowVO.setAuditUserName("-");
                continue;
            }

            // 统一算出“审核人类型”
            Integer typeCode = auditFlowVO.getAuditUserType();
            boolean isStep0 = auditFlowVO.getStepNumber() != null && auditFlowVO.getStepNumber() == 0;

            if (typeCode == null) {
                if (isStep0) {
                    typeCode = 1; // 申请人默认系统用户
                } else {
                    typeCode = -1; // 触发兜底双查
                }
            }

            // 根据类型查用户名
            String name = "-";
            if (typeCode == 0) {
                // 销售用户
                CompanyUser cu = companyUserService.selectCompanyUserById(displayUserId);
                if (cu != null) name = cu.getUserName();
            } else if (typeCode == 1) {
                // 系统用户
                SysUser sysUser = sysUserService.selectUserById(displayUserId);
                if (sysUser != null) name = sysUser.getUserName();
            } else {
                // 兜底：先查系统用户，再查销售用户
                SysUser sysUser = sysUserService.selectUserById(displayUserId);
                if (sysUser != null) {
                    name = sysUser.getUserName();
                } else {
                    CompanyUser cu = companyUserService.selectCompanyUserById(displayUserId);
                    if (cu != null) name = cu.getUserName();
                }
            }
            auditFlowVO.setAuditUserName(name);
        }

        vo.setAuditFlowList(auditFlowVOS);
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void doAudit(DoctorApplyAuditReqVO req) {

        // 0) 参数校验
        if (req == null || req.getId() == null) {
            throw new BusinessException("申请ID不能为空");
        }
        if (req.getStatus() == null || (req.getStatus() != 1 && req.getStatus() != 2)) {
            throw new BusinessException("审核状态不合法（1通过/2驳回）");
        }

        // 1) 当前登录人
        Long currentCompanyId = LoginContextManager.getCurrentCompanyId();
        if (currentCompanyId == null) {
            throw new BusinessException("当前用户不存在");
        }

        Long applyId = req.getId();

        // 2) 查申请
        DoctorLevelApplyVO apply = this.selectDoctorLevelApplyById(applyId);
        if (apply == null) {
            throw new BusinessException("申请记录不存在：" + applyId);
        }

        // 3) 防重复审核（按你业务改：比如只有待审核(0)才能审核）
        // 假设：0待审核 1通过 2驳回
        if (apply.getStatus() != null && apply.getStatus().intValue() != 0) {
            throw new BusinessException("该申请已审核，不能重复操作");
        }

        // 4) 落库：状态 + 审核意见（关键：用前端传来的 remark）
        apply.setStatus(req.getStatus().longValue());
        apply.setRemark(req.getRemark()); // ✅ 保存审核意见
        this.updateDoctorLevelApply(apply);

        // 5) 审核实例校验
        Long auditInstanceId = apply.getAuditInstanceId();
        if (auditInstanceId == null) {
            throw new BusinessException("审核实例ID为空，无法执行审核流程");
        }

        // 6) 调用审核执行：comment 用 req.remark；action 用 req.status（如需映射在这里做）
        AuditRequestDTO dto = new AuditRequestDTO();
        dto.setAuditId(auditInstanceId);
        dto.setUserId(currentCompanyId);
        dto.setUserType(UserTypeEnum.SALES.getCode());
        dto.setCompanyId(apply.getCompanyId());
        // ✅ 用前端传来的审核意见
        dto.setComment(req.getRemark());
        // ✅ 默认直接用 1/2（如果审核服务不是 1/2，改这里映射）
        dto.setAction(req.getStatus());
        auditService.doAudit(dto);

        //如果审核通过，讲者级别表应当有数据
        if (Objects.equals(apply.getStatus(), DoctorAuditStatus.APPROVED.getCode())) {
            DoctorLevel doctorLevel = doctorLevelService.selectDoctorLevelByDoctorId(apply.getDoctorId());

            //查询出产品组
            String ProductGroupStr = doctorCompanyUserService.queryProductGroup(apply.getCompanyId(), apply.getDoctorId());
            if (Objects.nonNull(doctorLevel)) {
                doctorLevel.setProductGroup(ProductGroupStr);
                doctorLevel.setLevel(Integer.valueOf(apply.getApplyLevel()));
                doctorLevelService.updateDoctorLevel(doctorLevel);
            } else {
                doctorLevel = new DoctorLevel();
                doctorLevel.setProductGroup(ProductGroupStr);
                doctorLevel.setDoctorId(apply.getDoctorId());
                doctorLevel.setLevel(Integer.valueOf(apply.getApplyLevel()));
                doctorLevel.setCompanyId(apply.getCompanyId());
                doctorLevelService.insertDoctorLevel(doctorLevel);

            }
        }
    }


    @Override
    public void appDoAudit(DoctorApplyAuditReqVO req) {

        // 0) 参数校验
        if (req == null || req.getId() == null) {
            throw new BusinessException("申请ID不能为空");
        }
        if (req.getStatus() == null || (req.getStatus() != 1 && req.getStatus() != 2)) {
            throw new BusinessException("审核状态不合法（1通过/2驳回）");
        }

        // 1) 当前登录人
        Long currentCompanyUserId = req.getAuditUserId();
        if (currentCompanyUserId == null) {
            throw new BusinessException("当前用户不存在");
        }

        Long applyId = req.getId();

        // 2) 查申请
        DoctorLevelApplyVO apply = this.selectDoctorLevelApplyById(applyId);
        if (apply == null) {
            throw new BusinessException("申请记录不存在：" + applyId);
        }

        // 3) 防重复审核（按你业务改：比如只有待审核(0)才能审核）
//        if (apply.getStatus() != null && apply.getStatus().intValue() != 1) {
//            throw new BusinessException("该申请已审核，不能重复操作");
//        }

        // 4) 落库：状态 + 审核意见（关键：用前端传来的 remark）
        apply.setStatus(req.getStatus().longValue());
        apply.setRemark(req.getRemark()); // ✅ 保存审核意见
        this.updateDoctorLevelApply(apply);

        // 5) 审核实例校验
        Long auditInstanceId = apply.getAuditInstanceId();
        if (auditInstanceId == null) {
            throw new BusinessException("审核实例ID为空，无法执行审核流程");
        }

        // 6) 调用审核执行：comment 用 req.remark；action 用 req.status（如需映射在这里做）
        AuditRequestDTO dto = new AuditRequestDTO();
        dto.setAuditId(auditInstanceId);
        dto.setUserId(currentCompanyUserId);
        dto.setUserType(UserTypeEnum.SALES.getCode());
        dto.setCompanyId(apply.getCompanyId());
        // ✅ 用前端传来的审核意见
        dto.setComment(req.getRemark());
        // ✅ 默认直接用 1/2（如果审核服务不是 1/2，改这里映射）
        dto.setAction(req.getStatus());
        AuditResult auditResult = auditService.doAudit(dto);
        if(!auditResult.isSuccess()){
            throw new BusinessException(auditResult.getMessage());
        }

        //如果审核通过，讲者级别表应当有数据
        if (Objects.equals(apply.getStatus(), DoctorAuditStatus.APPROVED.getCode())) {
            DoctorLevel doctorLevel = doctorLevelService.selectDoctorLevelByDoctorId(apply.getDoctorId());

            //查询出产品组
            String ProductGroupStr = doctorCompanyUserService.queryProductGroup(apply.getCompanyId(), apply.getDoctorId());
            if (Objects.nonNull(doctorLevel)) {
                doctorLevel.setProductGroup(ProductGroupStr);
                doctorLevel.setLevel(Integer.valueOf(apply.getApplyLevel()));
                doctorLevelService.updateDoctorLevel(doctorLevel);
            } else {
                doctorLevel = new DoctorLevel();
                doctorLevel.setProductGroup(ProductGroupStr);
                doctorLevel.setDoctorId(apply.getDoctorId());
                doctorLevel.setLevel(Integer.valueOf(apply.getApplyLevel()));
                doctorLevel.setCompanyId(apply.getCompanyId());
                doctorLevelService.insertDoctorLevel(doctorLevel);

            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long insertDynamicApply(DynamicApplyAddVO addVO) {
        // 1. 插入申请表
        DoctorLevelApplyVO applyVO = addVO.getApply();
        DoctorLevelApply apply = new DoctorLevelApply();
        BeanUtils.copyProperties(applyVO, apply);
        apply.setStatus(0L);
        doctorLevelApplyMapper.insertDoctorLevelApply(apply);
        Long applyId = apply.getId();

        // 2. 动态数据（不加 form_id）
        Map<String, Object> dynamicData = addVO.getDynamicData();
        dynamicData.put("company_id", apply.getCompanyId());
        dynamicData.put("version_id", addVO.getSurveyInfo().getVersionId());  // ✅ 关键修复
        dynamicData.put("submit_time", new Date());

        // 3. 插入动态表，获取自增主键
        String tableName = addVO.getSurveyInfo().getTableName();
        dynamicSurveyDataMapper.insertData(tableName, dynamicData);
        Long dynamicId = null;
        Object idObj = dynamicData.get("id");
        if (idObj != null) {
            dynamicId = Long.valueOf(idObj.toString());
        }
        if (dynamicId == null) {
            throw new RuntimeException("动态表主键回填失败");
        }

        // 4. 回填 form_id = 动态表主键
        doctorLevelApplyMapper.updateFormId(applyId, dynamicId);

        // 5. 保存材料、初始化审核
        saveMaterials(apply.getCompanyId(), applyId, applyVO.getMaterials());
        handleAuditInit(apply, LoginContextManager.getCurrentCompanyUserId());

        return applyId;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateDynamicApply(DynamicApplyUpdateVO updateVO) {
        // 1. 更新申请表
        DoctorLevelApplyVO applyVO = updateVO.getApply();
        DoctorLevelApply apply = new DoctorLevelApply();
        BeanUtils.copyProperties(applyVO, apply);
        doctorLevelApplyMapper.updateDoctorLevelApply(apply);

        // 2. 动态表主键从 apply 中取
        String tableName = updateVO.getSurveyInfo().getTableName();
        Long dynamicId = apply.getFormId(); // 关键：申请表存的 form_id 就是动态表主键

        // 3. 按主键直接更新
        Map<String, Object> dynamicData = updateVO.getDynamicData();
        dynamicData.put("update_time", new Date());
        dynamicSurveyDataMapper.updateById(tableName, dynamicId, dynamicData);

        // 4. 更新证明材料
        doctorLevelMaterialMapper.deleteDoctorLevelMaterialByDoctorLevelApplyId(apply.getId());
        saveMaterials(apply.getCompanyId(), apply.getId(), applyVO.getMaterials());
    }



}
