package com.qmth.distributed.print.business.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.distributed.print.business.bean.dto.ExamTaskDetailDto;
import com.qmth.distributed.print.business.bean.params.RelatePaperParam;
import com.qmth.distributed.print.business.entity.*;
import com.qmth.distributed.print.business.enums.ExamDetailStatusEnum;
import com.qmth.distributed.print.business.enums.FlowJoinTypeEnum;
import com.qmth.distributed.print.business.enums.PrintPlanStatusEnum;
import com.qmth.distributed.print.business.mapper.ExamTaskDetailMapper;
import com.qmth.distributed.print.business.service.*;
import com.qmth.teachcloud.common.bean.dto.MqDto;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.SysOrg;
import com.qmth.teachcloud.common.entity.SysUser;
import com.qmth.teachcloud.common.enums.*;
import com.qmth.teachcloud.common.service.CommonCacheService;
import com.qmth.teachcloud.common.service.SysUserService;
import com.qmth.teachcloud.common.service.TBTaskService;
import com.qmth.teachcloud.common.service.TeachcloudCommonService;
import com.qmth.teachcloud.common.util.RedisUtil;
import com.qmth.teachcloud.common.util.ServletUtil;
import org.activiti.engine.TaskService;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 命题任务明细表（入库申请） 服务实现类
 * </p>
 *
 * @author xf
 * @since 2021-03-23
 */
@Service
public class ExamTaskDetailServiceImpl extends ServiceImpl<ExamTaskDetailMapper, ExamTaskDetail> implements ExamTaskDetailService {

    @Autowired
    private ExamTaskService examTaskService;

    @Autowired
    private ExamDetailService examDetailService;

    @Autowired
    private ExamDetailCourseService examDetailCourseService;

    @Autowired
    private ExamStudentService examStudentService;

    @Autowired
    @Lazy
    private PrintCommonService printCommonService;

    @Autowired
    private ExamPrintPlanService examPrintPlanService;

    @Resource
    TBTaskService tbTaskService;

    @Resource
    TeachcloudCommonService teachcloudCommonService;

    @Resource
    RedisUtil redisUtil;

    @Resource
    ActivitiService activitiService;

    @Resource
    TaskService taskService;

    @Autowired
    TFFlowApproveService tfFlowApproveService;

    @Resource
    TFFlowJoinService tfFlowJoinService;

    @Resource
    SysUserService sysUserService;

    @Resource
    CommonCacheService commonCacheService;

    @Transactional
    @Override
    public boolean enable(ExamTaskDetail examTaskDetail) {
        ExamTask examTask = examTaskService.getById(examTaskDetail.getId());
        List<ExamDetail> examDetails = examDetailService.listByCourseCodeAndPaperNumber(examTask.getSchoolId(), examTask.getCourseCode(), examTask.getPaperNumber());
        if (examDetails != null && examDetails.size() > 0) {
            // 有考场提交打印，不能禁用启用
            long count = examDetails.stream().filter(m -> !ExamDetailStatusEnum.NEW.name().equals(m.getStatus().name()) && !ExamDetailStatusEnum.READY.name().equals(m.getStatus().name())).count();
            if (count > 0) {
                throw ExceptionResultEnum.ERROR.exception("有考场已提交打印，不能启用/禁用");
            }

            Map<Long, List<Long>> map = examDetails.stream().collect(Collectors.groupingBy(ExamDetail::getPrintPlanId, Collectors.mapping(ExamDetail::getId, Collectors.toList())));
            for (Map.Entry<Long, List<Long>> listEntry : map.entrySet()) {
                boolean b = tbTaskService.countByPrintPlanIdAndEntityId(examTask.getSchoolId(), listEntry.getKey(), listEntry.getValue());
                if (!b) {
                    throw ExceptionResultEnum.ERROR.exception("有关联该任务的考场正在生成打印pdf，不能启用/禁用卷库");
                }
            }
        }
        // 禁用，解决试卷关联关系，并且解除生成pdf绑定
        if (!examTaskDetail.getEnable()) {
            // 正在生成pdf不能禁用
            if (examDetails != null && examDetails.size() > 0) {
                Map<Long, List<Long>> map = examDetails.stream().collect(Collectors.groupingBy(ExamDetail::getPrintPlanId, Collectors.mapping(ExamDetail::getId, Collectors.toList())));
                for (Map.Entry<Long, List<Long>> listEntry : map.entrySet()) {
                    // 解除所有考场该任务绑定关系
                    // 更新exam_detail
                    List<Long> examDetailIds = listEntry.getValue();
                    UpdateWrapper<ExamDetail> examDetailUpdateWrapper = new UpdateWrapper<>();
                    examDetailUpdateWrapper.lambda()
                            .set(ExamDetail::getStatus, ExamDetailStatusEnum.NEW)
                            .set(ExamDetail::getAttachmentId, null)
                            .set(ExamDetail::getAttachmentPath, null)
                            .set(ExamDetail::getPagesA3, null)
                            .set(ExamDetail::getPagesA4, null)
                            .in(ExamDetail::getId, examDetailIds);
                    examDetailService.update(examDetailUpdateWrapper);
                    // 更新绑定关系
                    List<ExamDetailCourse> examDetailCourses = examDetailCourseService.listByPrintPlanIdAndCourseCodeAndPaperNumber(examTask.getSchoolId(), listEntry.getKey(), examTask.getCourseCode(), examTask.getPaperNumber());
                    List<Long> examDetailCourseIds = examDetailCourses.stream().map(m -> m.getId()).collect(Collectors.toList());
                    UpdateWrapper<ExamDetailCourse> examDetailCourseUpdateWrapper = new UpdateWrapper<>();
                    examDetailCourseUpdateWrapper.lambda()
                            .set(ExamDetailCourse::getPaperType, null)
                            .set(ExamDetailCourse::getPaperPagesA3, null)
                            .set(ExamDetailCourse::getCardPagesA3, null)
                            .in(ExamDetailCourse::getId, examDetailCourseIds);
                    examDetailCourseService.update(examDetailCourseUpdateWrapper);

                    // 全部任务都取消，更新计划状态
                    //所有考场都撤回，印刷任务状态改为就绪
                    QueryWrapper<ExamDetail> examDetailQueryWrapper = new QueryWrapper<>();
                    examDetailQueryWrapper.lambda().eq(ExamDetail::getPrintPlanId, listEntry.getKey()).notIn(ExamDetail::getStatus, ExamDetailStatusEnum.NEW, ExamDetailStatusEnum.READY);
                    List<ExamDetail> examDetailList = examDetailService.list(examDetailQueryWrapper);
                    if (examDetailList.isEmpty()) {
                        UpdateWrapper<ExamPrintPlan> printPlanUpdateWrapper = new UpdateWrapper<>();
                        printPlanUpdateWrapper.lambda().set(ExamPrintPlan::getStatus, PrintPlanStatusEnum.READY).eq(ExamPrintPlan::getId, listEntry.getKey());
                        examPrintPlanService.update(printPlanUpdateWrapper);
                    }
                }
            }
        }
        UpdateWrapper<ExamTaskDetail> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().set(ExamTaskDetail::getEnable, examTaskDetail.getEnable()).eq(ExamTaskDetail::getExamTaskId, examTaskDetail.getId());
        this.update(updateWrapper);

        return true;
    }

    @Transactional
    @Override
    public boolean updatePaper(RelatePaperParam paperParam) throws IOException {
        ExamPrintPlan examPrintPlan = examPrintPlanService.getById(paperParam.getPrintPlanId());
        if (PrintPlanStatusEnum.END.equals(examPrintPlan.getStatus())) {
            throw ExceptionResultEnum.ERROR.exception("印刷计划已结束，不能修改");
        }
        ExamTask examTask = examTaskService.getById(paperParam.getExamTaskId());
        // 校验课程关联考场，是否已经提交打印
        Boolean isCreate = printCommonService.checkExamDetailStatus(examTask.getSchoolId(), examPrintPlan.getId(), examTask.getCourseCode(), examTask.getPaperNumber());
        if (isCreate) {
            // 提交印刷的考场，不允许修改关联试卷
            List<ExamDetail> examDetails = examDetailService.listByPrintPlanIdAndCourseCodeAndPaperNumber(examTask.getSchoolId(), paperParam.getPrintPlanId(), examTask.getCourseCode(), examTask.getPaperNumber());
            List<ExamDetail> examDetails1 = examDetails.stream().filter(m -> !ExamDetailStatusEnum.NEW.equals(m.getStatus()) && !ExamDetailStatusEnum.READY.equals(m.getStatus())).collect(Collectors.toList());
            if (!examDetails1.isEmpty()) {
                throw ExceptionResultEnum.ERROR.exception("有考场已开始打印，不能修改");
            }

            List<Long> entityIds = examDetails.stream().map(m -> m.getId()).collect(Collectors.toList());
            boolean b = tbTaskService.countByPrintPlanIdAndEntityId(examTask.getSchoolId(), paperParam.getPrintPlanId(), entityIds);
            if (!b) {
                throw ExceptionResultEnum.ERROR.exception("有关联该任务的考场正在生成打印pdf，不能修改关联类型");
            }

            for (ExamDetail examDetail : examDetails) {
                List<ExamDetailCourse> examDetailCourses = examDetailCourseService.listByExamDetailIdAndStatus(examDetail.getId());
                // 4.没有未完成的命题任务
                if (!CollectionUtils.isEmpty(examDetailCourses)) {
                    throw ExceptionResultEnum.ERROR.exception("有关联该任务的考场有未完成的命题任务，不能修改关联类型");
                }
            }

            // 更新关联卷型
            ExamTask newExamTask = examTaskService.getByCourseCodeAndPaperNumber(examTask.getSchoolId(), examTask.getCourseCode(), paperParam.getPaperNumber());
            UpdateWrapper<ExamTaskDetail> updateWrapper = new UpdateWrapper<>();
            updateWrapper.lambda().set(ExamTaskDetail::getRelatePaperType, paperParam.getRelatePaperType()).eq(ExamTaskDetail::getExamTaskId, newExamTask.getId());
            this.update(updateWrapper);

            // 更新试卷编号
            String examDetailCourseIdStr = paperParam.getExamDetailCourseIds();
            List<Long> examDetailCourseIds = Arrays.asList(examDetailCourseIdStr.split(",")).stream().map(m -> Long.valueOf(m)).collect(Collectors.toList());
            examDetailCourseService.updatePaperNumber(examDetailCourseIds, paperParam.getPaperNumber(), paperParam.getRelatePaperType());

            // 更新考生关联类型
//            examStudentService.updatePaperType(examDetailCourseIds, paperParam.getRelatePaperType());
            ExamTaskDetail examTaskDetail = this.getByExamTaskId(newExamTask.getId());
            List<String> types = Arrays.asList(paperParam.getRelatePaperType().split(","));
            int drawCount = examTaskDetail.getDrawCount().intValue();
            if (drawCount - types.size() > 0) {
                throw ExceptionResultEnum.ERROR.exception("没有足够数量的卷型可用");
            }
            for (Long examDetailCourseId : examDetailCourseIds) {
                QueryWrapper<ExamStudent> studentQueryWrapper = new QueryWrapper<>();
                studentQueryWrapper.lambda().eq(ExamStudent::getExamDetailCourseId, examDetailCourseId);
                List<ExamStudent> students = examStudentService.list(studentQueryWrapper);
                int i = 0;
                for (ExamStudent student : students) {
                    int mod = i % drawCount;
                    student.setPaperType(types.get(mod));
                    examStudentService.updateById(student);
                    i++;
                }
            }

            // 重新生成pdf
            List<ExamDetailCourse> examDetailCourses = examDetailCourseService.listByIds(examDetailCourseIds);
            Map<Long, List<Long>> examDetailIdMap = examDetailCourses.stream().collect(Collectors.groupingBy(ExamDetailCourse::getExamDetailId, Collectors.mapping(ExamDetailCourse::getId, Collectors.toList())));
            for (Map.Entry<Long, List<Long>> listEntry : examDetailIdMap.entrySet()) {
                SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
                Map<String, Object> map = tbTaskService.saveTask(TaskTypeEnum.CREATE_PDF, paperParam.getPrintPlanId(), sysUser, listEntry.getKey());
                map.computeIfAbsent("examDetailCourseIds", v -> listEntry.getValue());
                map.computeIfAbsent("paperType", v -> paperParam.getRelatePaperType());
//                asyncCreatePdfTempleteService.createPdf(map, null);
                MqDto mqDto = new MqDto(MqTagEnum.PDF.getCode(), map, String.valueOf(map.get(SystemConstant.TB_TASK_ID)));
                redisUtil.sendMessage(mqDto.getTopic(), mqDto);
            }
        }
        return true;
    }

    @Override
    public IPage<ExamTaskDetailDto> list(String relateType, List<Long> printPlanIdList, String courseCode, String paperNumber, String userName, Long cardRuleId, Integer pageNumber, Integer pageSize) {
        userName = SystemConstant.translateSpecificSign(userName);
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        Set<Long> orgIds = teachcloudCommonService.listSubOrgIds(null);
        Page<ExamTaskDetailDto> page = new Page<>(pageNumber, pageSize);
        IPage<ExamTaskDetailDto> examDetailDtoIPage = this.baseMapper.listPage(page, schoolId, relateType, printPlanIdList, courseCode, paperNumber, userName, cardRuleId, orgIds);
        examDetailDtoIPage.getRecords().stream().map(m -> {
            String paperType = StringUtils.isBlank(m.getRelatePaperType()) ? null : m.getRelatePaperType();
            Long printPlanIdT = Long.valueOf(m.getPrintPlanId());
            String courseCodeT = m.getCourseCode();
            String paperNumberT = m.getPaperNumber();
            List<String> examDetailCourseIds = this.baseMapper.listExamDetailCourse(schoolId, paperType, printPlanIdT, courseCodeT, paperNumberT);
            m.setExamDetailCourseIds(String.join(",", examDetailCourseIds));
            return m;
        }).collect(Collectors.toList());
        return examDetailDtoIPage;
    }

    @Override
    public List<ExamTaskDetail> listByCardId(Long cardId) {
        QueryWrapper<ExamTaskDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ExamTaskDetail::getCardId, cardId);
        return this.list(queryWrapper);
    }

    @Override
    public void bindCardId(String examTaskId, ExamCard examCard) {
        UpdateWrapper<ExamTaskDetail> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().set(ExamTaskDetail::getCardId, examCard.getId()).set(ExamTaskDetail::getMakeMethod, examCard.getMakeMethod().name()).eq(ExamTaskDetail::getExamTaskId, examTaskId);
        this.update(updateWrapper);
    }

    @Override
    public void resetCardId(Long id) {
        UpdateWrapper<ExamTaskDetail> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().set(ExamTaskDetail::getCardId, null).eq(ExamTaskDetail::getExamTaskId, id);
        this.update(updateWrapper);
    }

    @Override
    public List<ExamTaskDetail> listByTemplateId(Long templateId) {
        return this.baseMapper.listByTemplateId(templateId);
    }

    @Override
    public List<Map<String, String>> getPaperUrl(Long schoolId, Long printPlanId, Long examTaskId) {
        ExamTask examTask = examTaskService.getById(examTaskId);
        List<ExamDetailCourse> examDetailCourses = examDetailCourseService.listByPrintPlanIdAndCourseCodeAndPaperNumber(schoolId, printPlanId, examTask.getCourseCode(), examTask.getPaperNumber());
        if (!CollectionUtils.isEmpty(examDetailCourses)) {
            Set<String> relatePaperTypes = examDetailCourses.stream().filter(m -> StringUtils.isNotBlank(m.getPaperType())).map(m -> m.getPaperType()).collect(Collectors.toSet());
            List<Map<String, String>> paperList = new ArrayList<>();
            QueryWrapper<ExamTaskDetail> examTaskDetailQueryWrapper = new QueryWrapper<>();
            examTaskDetailQueryWrapper.lambda().eq(ExamTaskDetail::getExamTaskId, examTaskId);
            ExamTaskDetail examTaskDetail = this.getOne(examTaskDetailQueryWrapper);
            if (Objects.isNull(examTaskDetail)) {
                throw ExceptionResultEnum.ERROR.exception("未查询到卷库中的试卷");
            }
            if (CollectionUtils.isEmpty(relatePaperTypes)) {
                throw ExceptionResultEnum.ERROR.exception("未找到关联的试卷卷型");
            }
            String paperAttachmentIds = examTaskDetail.getPaperAttachmentIds();
            List<Map> list = JSONObject.parseArray(paperAttachmentIds, Map.class);
            if (CollectionUtils.isEmpty(list)) {
                throw ExceptionResultEnum.ERROR.exception("未找到关联的试卷文件");
            }

            Map<String, String> paperMap = list.stream().collect(Collectors.toMap(m -> m.get("name").toString(), m -> m.get("attachmentId").toString()));
            for (String relatePaperType : relatePaperTypes) {
                String[] paperTypes = relatePaperType.split(",");
                for (String paperType : paperTypes) {
                    if (!paperMap.containsKey(paperType)) {
                        continue;
                    }
                    String attachmentId = paperMap.get(paperType);
                    if (StringUtils.isNotBlank(attachmentId)) {
                        paperList.add(teachcloudCommonService.filePreviewByAttachmentId(Long.valueOf(attachmentId), false));
                    }
                }
            }
            paperList = paperList.stream().distinct().collect(Collectors.toList());
            return paperList;
        }
        return null;
    }

    @Override
    @Transactional
    public boolean paperUpdate(ExamTaskDetail examTaskDetail) {
        SysUser requestUser = (SysUser) ServletUtil.getRequestUser();

        validPaperUpdate(examTaskDetail);
        SysOrg sysOrg = commonCacheService.orgCache(requestUser.getOrgId());

        ExamTaskDetail examTaskDetail1 = this.getByExamTaskId(examTaskDetail.getExamTaskId());
        String unexposedPaperType = examTaskDetail.getPaperType();
        if (StringUtils.isNotBlank(examTaskDetail1.getExposedPaperType())) {
            List<String> paperTypeAll = new ArrayList<>(Arrays.asList(examTaskDetail.getPaperType().split(",")));
            List<String> exposePaperTypes = Arrays.asList(examTaskDetail1.getExposedPaperType().split(","));
            for (String exposePaperType : exposePaperTypes) {
                if (paperTypeAll.contains(exposePaperType)) {
                    paperTypeAll.remove(exposePaperType);
                }
            }
            unexposedPaperType = String.join(",", paperTypeAll);
        }

        UpdateWrapper<ExamTaskDetail> examTaskDetailUpdateWrapper = new UpdateWrapper<>();
        examTaskDetailUpdateWrapper.lambda().set(ExamTaskDetail::getPaperType, examTaskDetail.getPaperType())
                .set(ExamTaskDetail::getPaperAttachmentIds, examTaskDetail.getPaperAttachmentIds())
                .set(ExamTaskDetail::getCardId, examTaskDetail.getCardId())
                .set(ExamTaskDetail::getUnexposedPaperType, unexposedPaperType)
                .eq(ExamTaskDetail::getExamTaskId, examTaskDetail.getExamTaskId());
        this.update(examTaskDetailUpdateWrapper);

        ExamTask examTask = examTaskService.getById(examTaskDetail.getExamTaskId());
        List<ExamDetail> examDetails = examDetailService.listByCourseCodeAndPaperNumber(examTask.getSchoolId(), examTask.getCourseCode(), examTask.getPaperNumber());
        if (!CollectionUtils.isEmpty(examDetails)) {
            List<ExamDetail> examDetailList = examDetails.stream().filter(m -> m.getStatus().equals(ExamDetailStatusEnum.WAITING)).collect(Collectors.toList());
            for (ExamDetail examDetail : examDetailList) {
                examDetail.setStatus(ExamDetailStatusEnum.NEW);
                examDetailService.updateById(examDetail);
            }
        }

        // 不需要审核，直接更新，否则加入待审核列表(状态为不需要审核的或者为管理员身份的都不重新走审核流程)
        if (examTask.getReview() || !sysUserService.isAdminDataAuth(requestUser.getId())) {
            // 发起新流程
            Map<String, Object> map = SystemConstant.buildFlowVar(examTask.getId(),
                    examTask,
                    TFCustomTypeEnum.ELECTRON_FLOW,
                    examTask.getUserId(),
                    false);
            map.computeIfAbsent(SystemConstant.OLD_FLOW_ID, v -> examTask.getFlowId());
            map.computeIfAbsent(SystemConstant.FLOW_JOIN_TYPE, v -> FlowJoinTypeEnum.RESTART);
            map = activitiService.customFlowStart(map);
            Long flowId = SystemConstant.convertIdToLong((String) map.get(SystemConstant.FLOW_ID));
            UpdateWrapper<ExamTask> updateWrapper = new UpdateWrapper<>();
            updateWrapper.lambda().set(ExamTask::getFlowId, flowId).eq(ExamTask::getId, examTaskDetail.getExamTaskId());
            examTaskService.update(updateWrapper);

            tfFlowJoinService.saveOrUpdate(map);
            if (Objects.nonNull(flowId)) {
                // 审核一级
                Task task = taskService.createTaskQuery().processInstanceId(String.valueOf(flowId)).singleResult();
                if (Objects.nonNull(task)) {
                    Map<String, Object> approverMap = new HashMap<>();
                    approverMap.computeIfAbsent(SystemConstant.FLOW_TASK_ID, v -> task.getId());
                    approverMap.computeIfAbsent(SystemConstant.PAPAER_ATTACHMENT_IDS, v -> examTaskDetail.getPaperAttachmentIds());
                    approverMap.computeIfAbsent(SystemConstant.APPROVE_OPERATION, v -> FlowApprovePassEnum.PASS);
                    String remark = Objects.nonNull(sysOrg) ? sysOrg.getName() : "无机构";
                    approverMap.computeIfAbsent(SystemConstant.APPROVE_REMARK, v -> requestUser.getRealName() + "(" + remark + ")" + FlowApprovePassEnum.RESTART.getTitle());
                    activitiService.taskApprove(approverMap);
                }
            }
        }
        return true;
    }

    @Override
    public ExamTaskDetail getByExamTaskId(Long examTaskId) {
        QueryWrapper<ExamTaskDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ExamTaskDetail::getExamTaskId, examTaskId);
        return this.getOne(queryWrapper);
    }

    /**
     * 卷库校验
     *
     * @param examTaskDetail
     */
    void validPaperUpdate(ExamTaskDetail examTaskDetail) {
        // 旧记录
        ExamTaskDetail examTaskDetailTemp = this.getByExamTaskId(examTaskDetail.getExamTaskId());
        if (examTaskDetailTemp == null) {
            throw ExceptionResultEnum.ERROR.exception("命题任务数据异常");
        }

        List<Map> oldPaperAttachmentIdsList = JSONObject.parseArray(examTaskDetailTemp.getPaperAttachmentIds(), Map.class);
        List<Map> newPaperAttachmentIdsList = JSONObject.parseArray(examTaskDetail.getPaperAttachmentIds(), Map.class);
        // 卷型、题卡没有变动，直接return
        if (oldPaperAttachmentIdsList.size() == newPaperAttachmentIdsList.size()) {
            String oldString = oldPaperAttachmentIdsList.stream().sorted(Comparator.comparing(m -> m.get("name").toString())).map(m -> m.get("name").toString() + m.get("attachmentId").toString()).collect(Collectors.joining());
            String newString = newPaperAttachmentIdsList.stream().sorted(Comparator.comparing(m -> m.get("name").toString())).map(m -> m.get("name").toString() + m.get("attachmentId").toString()).collect(Collectors.joining());
            if (oldString.equals(newString) && examTaskDetailTemp.getCardId().equals(examTaskDetail.getCardId())) {
                return;
            }
        }

        ExamTask examTask = examTaskService.getById(examTaskDetail.getExamTaskId());
        // 是否审核中
        TFFlowApprove tfFlowApprove = tfFlowApproveService.findByFlowId(examTask.getFlowId());
        if (!tfFlowApprove.getStatus().equals(FlowStatusEnum.FINISH)) {
            throw ExceptionResultEnum.ERROR.exception("命题任务没有审核完成，不能修改卷库");
        }

        // 提交印刷的考场，不允许修改关联试卷
        List<ExamDetail> examDetails = examDetailService.listByCourseCodeAndPaperNumber(examTask.getSchoolId(), examTask.getCourseCode(), examTask.getPaperNumber());
        if (!CollectionUtils.isEmpty(examDetails)) {
            List<ExamDetail> examDetails1 = examDetails.stream().filter(m -> !ExamDetailStatusEnum.NEW.equals(m.getStatus())
                    && !ExamDetailStatusEnum.READY.equals(m.getStatus())
                    && !ExamDetailStatusEnum.WAITING.equals(m.getStatus())).collect(Collectors.toList());
            if (!examDetails1.isEmpty()) {
                throw ExceptionResultEnum.ERROR.exception("印刷任务已开始打印，不能修改卷库");
            }
            Map<Long, List<Long>> map = examDetails.stream().collect(Collectors.groupingBy(ExamDetail::getPrintPlanId, Collectors.mapping(ExamDetail::getId, Collectors.toList())));
            for (Map.Entry<Long, List<Long>> listEntry : map.entrySet()) {
                boolean b = tbTaskService.countByPrintPlanIdAndEntityId(examTask.getSchoolId(), listEntry.getKey(), listEntry.getValue());
                if (!b) {
                    throw ExceptionResultEnum.ERROR.exception("关联命题任务的考场正在生成打印文件，不能修改卷库");
                }
            }
        }

        // 已曝光试卷不能修改
        String exposedPaperType = examTaskDetailTemp.getExposedPaperType();
        if (StringUtils.isNotBlank(exposedPaperType)) {
            Map<String, String> oldPaperAttachmentIdMap = oldPaperAttachmentIdsList.stream().collect(Collectors.toMap(m -> m.get("name").toString(), m -> m.get("attachmentId").toString()));
            String[] exposedPaperTypes = exposedPaperType.split(",");
            String newPaperAttachmentIds = examTaskDetail.getPaperAttachmentIds();
            if (StringUtils.isBlank(newPaperAttachmentIds)) {
                throw ExceptionResultEnum.ERROR.exception("已曝光试卷不能删除");
            } else {
                Map<String, String> newPaperAttachmentIdMap = newPaperAttachmentIdsList.stream().collect(Collectors.toMap(m -> m.get("name").toString(), m -> m.get("attachmentId").toString()));
                for (String paperType : exposedPaperTypes) {
                    if (!oldPaperAttachmentIdMap.containsKey(paperType)) {
                        throw ExceptionResultEnum.ERROR.exception("原试卷卷型【" + paperType + "】不存在");
                    }
                    if (!newPaperAttachmentIdMap.containsKey(paperType)) {
                        throw ExceptionResultEnum.ERROR.exception("已曝光卷型【" + paperType + "】不能删除");
                    }

                    String newAttachmentId = newPaperAttachmentIdMap.get(paperType);
                    String oldAttachmentId = oldPaperAttachmentIdMap.get(paperType);
                    if (!newAttachmentId.equals(oldAttachmentId)) {
                        throw ExceptionResultEnum.ERROR.exception("已曝光卷型【" + paperType + "】不能修改试卷文件");
                    }
                }
            }

            // 已有曝光卷型时，题卡不能修改
            if (!examTaskDetailTemp.getCardId().equals(examTaskDetail.getCardId())) {
                throw ExceptionResultEnum.ERROR.exception("已有试卷曝光，不能修改题卡");
            }
        }
    }
}
