package com.qmth.sop.business.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.boot.api.exception.ApiException;
import com.qmth.sop.business.activiti.service.ActivitiService;
import com.qmth.sop.business.bean.dto.CrmDetailImportDto;
import com.qmth.sop.business.bean.params.CrmDetailSopParam;
import com.qmth.sop.business.bean.params.SopPublishParam;
import com.qmth.sop.business.bean.params.TBCrmDetailParam;
import com.qmth.sop.business.bean.result.CrmProjectResult;
import com.qmth.sop.business.bean.result.FlowFormWidgetResult;
import com.qmth.sop.business.bean.result.FlowResult;
import com.qmth.sop.business.bean.result.FlowTaskResult;
import com.qmth.sop.business.entity.*;
import com.qmth.sop.business.mapper.TBCrmDetailMapper;
import com.qmth.sop.business.service.*;
import com.qmth.sop.business.util.excel.BasicExcelListener;
import com.qmth.sop.common.contant.SystemConstant;
import com.qmth.sop.common.enums.*;
import com.qmth.sop.common.util.GsonUtil;
import com.qmth.sop.common.util.JacksonUtil;
import com.qmth.sop.common.util.ResultUtil;
import com.qmth.sop.common.util.ServletUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.multipart.MultipartFile;

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

/**
 * <p>
 * 派单明细表 服务实现类
 * </p>
 *
 * @author wangliang
 * @since 2024-05-14
 */
@Service
public class TBCrmDetailServiceImpl extends ServiceImpl<TBCrmDetailMapper, TBCrmDetail> implements TBCrmDetailService {

    private final static Logger log = LoggerFactory.getLogger(TBCrmDetailServiceImpl.class);

    @Resource
    TBCrmService tbCrmService;

    @Resource
    TBCrmDetailService tbCrmDetailService;

    @Resource
    TFCustomFlowService tfCustomFlowService;

    @Resource
    TBServiceService tbServiceService;

    @Resource
    TDFormWidgetService tdFormWidgetService;

    @Resource
    TBSopInfoService tbSopInfoService;

    @Resource
    TFCustomFlowEntityService tfCustomFlowEntityService;

    @Resource
    TFFlowApproveService tfFlowApproveService;

    @Resource
    TBDingService tbDingService;

    @Resource
    ActivitiService activitiService;

    @Resource
    TFFlowLogService tfFlowLogService;

    /**
     * 查找派单sop信息
     *
     * @param crmNo
     * @return
     */
    @Override
    public CrmProjectResult sopVarInfo(String crmNo) {
        CrmProjectResult crmProjectResult = tbCrmService.findCrmProjectInfo(null, null, crmNo);
        Objects.requireNonNull(crmProjectResult, "未找到派单信息");

        TBCrm tbCrm = tbCrmService.findByCrmNo(crmNo);
        TBService tbService = tbServiceService.getById(tbCrm.getServiceId());
        Objects.requireNonNull(tbService, "未找到服务单元");

        //        if (tbService.getType() == ProductTypeEnum.CLOUD_MARK) {
        //            throw ExceptionResultEnum.ERROR.exception(tbService.getType().getTitle() + "暂不支持创建sop");
        //        }
        if (Objects.isNull(crmProjectResult.getProcessVar())) {
            if (tbService.getType() == ProductTypeEnum.OFFICE) {
                List<FlowFormWidgetResult> flowFormWidgetResultList = tdFormWidgetService.flowWidgetQuery(
                        TFCustomTypeEnum.OFFICE_SOP_FLOW, 1, SystemConstant.OFFICE_COMMON_GROUP);
                if (CollectionUtils.isEmpty(flowFormWidgetResultList)) {
                    throw ExceptionResultEnum.ERROR.exception("教务处sop公用控件未设置");
                }
                crmProjectResult.setProcessVar(JacksonUtil.parseJson(flowFormWidgetResultList));
            }
        }
        return crmProjectResult;
    }

    /**
     * 派单明细sop变量保存
     *
     * @param crmDetailSopParam
     * @return
     */
    @Override
    @Transactional
    public boolean sopVarSave(CrmDetailSopParam crmDetailSopParam) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        TBCrm tbCrm = tbCrmService.findByCrmNo(crmDetailSopParam.getCrmNo());
        List<FlowFormWidgetResult> flowFormWidgetResultList = JSONArray.parseArray(crmDetailSopParam.getProcessVar(),
                FlowFormWidgetResult.class);
        for (FlowFormWidgetResult f : flowFormWidgetResultList) {
            JSONObject jsonObject = JSONObject.parseObject(f.getValue());
            String value = jsonObject.getString(SystemConstant.VALUE);
            if (Objects.isNull(value)) {
                throw ExceptionResultEnum.ERROR.exception(f.getTitle() + "不能为空");
            }
        }
        tbCrm.updateProcessVar(crmDetailSopParam.getProcessVar(), sysUser.getId());
        return tbCrmService.updateById(tbCrm);
    }

    /**
     * 派单明细sop导入
     *
     * @param file
     * @param crmNo
     * @return
     */
    @Override
    @Transactional
    public Map<String, String> sopExcelImport(MultipartFile file, String crmNo) {
        log.debug("导入Excel开始...");
        long start = System.currentTimeMillis();

        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        TFCustomFlow tfCustomFlow = tbCrmDetailService.queryCustomFlow(crmNo);
        Map<String, String> messageMap = new LinkedHashMap<>();
        try {
            StringJoiner errorData = new StringJoiner("");
            StringJoiner successData = new StringJoiner("");

            LinkedMultiValueMap<String, CrmDetailImportDto> crmDetailImportDtoLinkedMultiValueMap = new LinkedMultiValueMap<>();
            EasyExcel.read(file.getInputStream(), CrmDetailImportDto.class,
                    new BasicExcelListener<CrmDetailImportDto>() {

                        @Override
                        public void handle(LinkedMultiValueMap<String, CrmDetailImportDto> dataList,
                                StringJoiner errorDataSj, Exception exception) {
                            crmDetailImportDtoLinkedMultiValueMap.addAll(dataList);
                            errorData.add(errorDataSj.toString());
                        }
                    }).headRowNumber(2).sheet(0).doRead();

            List<CrmDetailImportDto> crmDetailImportDtoList = crmDetailImportDtoLinkedMultiValueMap.get(
                    BasicExcelListener.SUCCESS);
            if (CollectionUtils.isNotEmpty(crmDetailImportDtoList)) {
                if (crmDetailImportDtoList.size() > 1000) {
                    throw ExceptionResultEnum.ERROR.exception("一次最多支持导入1000条");
                }
                List<TBCrmDetail> tbCrmDetailList = new ArrayList<>(crmDetailImportDtoList.size());
                Set<String> courseNameSet = new LinkedHashSet<>();
                List<String> duplicateCourseNameList = new ArrayList<>();
                for (int i = 0; i < crmDetailImportDtoList.size(); i++) {
                    CrmDetailImportDto c = crmDetailImportDtoList.get(i);
                    if (!courseNameSet.add(c.getCourseName())) { // 如果set.add返回false，表示已经添加过该元素，即有重复
                        duplicateCourseNameList.add(c.getCourseName());
                    }
                    tbCrmDetailList.add(new TBCrmDetail(crmNo, tfCustomFlow.getFlowDeploymentId(), c, sysUser.getId()));
                }
                if (CollectionUtils.isNotEmpty(duplicateCourseNameList)) {
                    throw ExceptionResultEnum.ERROR.exception(
                            "导入数据里有重复的科目：" + StringUtils.join(duplicateCourseNameList, ","));
                }
                if (!CollectionUtils.isEmpty(tbCrmDetailList)) {
                    if (CollectionUtils.isNotEmpty(courseNameSet)) {
                        List<TBCrmDetail> tbCrmDetailListAll = new ArrayList<>();
                        int size = courseNameSet.size();
                        List<String> courseNameList = new ArrayList<>(courseNameSet);
                        int max = SystemConstant.PAGE_SIZE_MAX, min = 0;
                        if (max >= size) {
                            max = size;
                        }
                        while (max <= size) {
                            List<TBCrmDetail> tbCrmDetailTempList = tbCrmDetailService.list(
                                    new QueryWrapper<TBCrmDetail>().lambda().eq(TBCrmDetail::getCrmNo, crmNo)
                                            .in(TBCrmDetail::getCourseName, courseNameList.subList(min, max)));
                            if (CollectionUtils.isNotEmpty(tbCrmDetailTempList)) {
                                tbCrmDetailListAll.addAll(tbCrmDetailTempList);
                            }
                            if (max == size) {
                                break;
                            }
                            min = max;
                            max += max;
                            if (max >= size) {
                                max = size;
                            }
                        }
                        if (CollectionUtils.isNotEmpty(tbCrmDetailListAll)) {
                            List<String> courseNameDuplicateList = tbCrmDetailListAll.stream()
                                    .map(s -> s.getCourseName()).collect(Collectors.toList());
                            throw ExceptionResultEnum.ERROR.exception(
                                    "已有重复的科目：" + StringUtils.join(courseNameDuplicateList, ","));
                        }
                    }
                    successData.add("共导入").add(crmDetailImportDtoList.size() + "").add("条数据");
                    tbCrmDetailService.saveBatch(tbCrmDetailList);
                }
            }
            messageMap.put(SystemConstant.SUCCESS, successData.length() > 0 ? successData.toString() : "无");
            messageMap.put(SystemConstant.EXCEL_ERROR, errorData.length() > 0 ? errorData.toString() : "无");
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            if (e instanceof DuplicateKeyException) {
                String errorColumn = e.getCause().toString();
                String[] strs = StringUtils.split(errorColumn, "-");
                String[] columns = StringUtils.split(strs[strs.length - 1], "\\'");
                throw ExceptionResultEnum.SQL_ERROR.exception(
                        FieldUniqueEnum.convertToTitle(columns[columns.length - 1]) + ":[" + columns[0] + "]数据不允许重复插入");
            } else if (e instanceof ApiException) {
                ResultUtil.error((ApiException) e, ((ApiException) e).getCode(), e.getMessage());
            } else {
                ResultUtil.error(e.getMessage());
            }
        }
        log.debug("导入Excel结束...");
        long end = System.currentTimeMillis();
        log.info("============耗时{}秒============:", (end - start) / 1000);
        return messageMap;
    }

    /**
     * 查询派单明细sop信息列表
     *
     * @param iPage
     * @param crmNo
     * @return
     */
    @Override
    public IPage<TBCrmDetail> list(IPage<Map> iPage, String crmNo) {
        return this.baseMapper.list(iPage, crmNo);
    }

    /**
     * 创建/编辑派单明细sop
     *
     * @param tbCrmDetail
     * @return
     */
    @Override
    @Transactional
    public boolean sopSave(TBCrmDetail tbCrmDetail) {
        try {
            SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
            if (Objects.nonNull(tbCrmDetail.getScanStartTime()) && Objects.nonNull(tbCrmDetail.getScanEndTime())
                    && tbCrmDetail.getScanEndTime().longValue() <= tbCrmDetail.getScanStartTime().longValue()) {
                throw ExceptionResultEnum.ERROR.exception("扫描结束时间不能小于等于扫描开始时间");
            }
            if (Objects.nonNull(tbCrmDetail.getScanEndTime()) && Objects.nonNull(tbCrmDetail.getMarkPaperStartTime())
                    && tbCrmDetail.getMarkPaperStartTime().longValue() <= tbCrmDetail.getScanEndTime().longValue()) {
                throw ExceptionResultEnum.ERROR.exception("阅卷开始时间不能小于等于扫描结束时间");
            }
            if (Objects.nonNull(tbCrmDetail.getMarkPaperStartTime()) && Objects.nonNull(
                    tbCrmDetail.getMarkPaperEndTime())
                    && tbCrmDetail.getMarkPaperEndTime().longValue() <= tbCrmDetail.getMarkPaperStartTime()
                    .longValue()) {
                throw ExceptionResultEnum.ERROR.exception("阅卷结束时间不能小于等于阅卷开始时间");
            }
            if (Objects.isNull(tbCrmDetail.getId())) {//说明创建sop
                TFCustomFlow tfCustomFlow = tbCrmDetailService.queryCustomFlow(tbCrmDetail.getCrmNo());
                tbCrmDetail.createSop(tfCustomFlow.getFlowDeploymentId(), sysUser.getId());
            } else {
                TBCrmDetail tbCrmDetailDb = tbCrmDetailService.getById(tbCrmDetail.getId());
                Objects.requireNonNull(tbCrmDetailDb, "未找到派单sop信息");

                tbCrmDetail.updateSop(tbCrmDetailDb, sysUser.getId());
                if (tbCrmDetail.getStatus() == CrmStatusEnum.PUBLISH) {
                    SopStatusEnum sopStatus = tbSopInfoService.findBySopNo(tbCrmDetail.getSopNo());
                    if (sopStatus == SopStatusEnum.START) {
                        throw ExceptionResultEnum.ERROR.exception("该条sop状态已改变，请刷新页面");
                    }
                    CrmProjectResult crmProjectResult = tbCrmService.findCrmProjectInfo(tbCrmDetail.getSopNo(),
                            tbCrmDetail.getId(), tbCrmDetail.getCrmNo());
                    Objects.requireNonNull(crmProjectResult, "未找到派单信息");

                    TFCustomFlowEntity tfCustomFlowEntity = tfCustomFlowEntityService.findByCode(
                            tbCrmDetail.getSopNo());

                    TFCustomFlow tfCustomFlow = tfCustomFlowService.findById(tfCustomFlowEntity.gettFCustomFlowId());

                    FlowResult flowResult = JSONObject.parseObject(tfCustomFlowEntity.getFlowProcessVar(),
                            FlowResult.class);
                    LinkedHashMap<String, FlowTaskResult> setupMap = flowResult.getSetupMap();
                    FlowTaskResult flowTaskResult = tbSopInfoService.getFormProperties(tfCustomFlowEntity, 1);
                    flowTaskResult = tbSopInfoService.updateSetupOne(flowTaskResult, tfCustomFlow, null, tbCrmDetail,
                            crmProjectResult);

                    setupMap.put(flowTaskResult.getTaskKey(), flowTaskResult);
                    tfCustomFlowEntity.setFlowProcessVar(JacksonUtil.parseJson(flowResult));
                    tfCustomFlowEntityService.updateById(tfCustomFlowEntity);
                    tbDingService.resetDingExceptionBySopNo(tbCrmDetail.getSopNo());

                    TFFlowApprove tfFlowApprove = tfFlowApproveService.findByFlowId(tfCustomFlowEntity.getFlowId());
                    TFFlowLog tfFlowLog = tfFlowLogService.findByLastFlowLogByFlowId(tfCustomFlowEntity.getFlowId());
                    TBSopInfo tbSopInfo = tbSopInfoService.findByCode(tfCustomFlowEntity.getCode());
                    Map<String, Object> map = new HashMap<>();
                    map.put(SystemConstant.FLOW_CUSTOM, tfCustomFlow);
                    map.put(SystemConstant.FLOW_ENTITY, tfCustomFlowEntity);
                    map.put(SystemConstant.FLOW_APPROVE, tfFlowApprove);
                    map.put(SystemConstant.FLOW_APPROVE_LOG, tfFlowLog);
                    map.put(SystemConstant.CRM_INFO, crmProjectResult);
                    map.put(SystemConstant.SOP_ID, tbSopInfo.getId());
                    tbSopInfoService.saveJobRemind(map);
                }
            }
            return tbCrmDetailService.saveOrUpdate(tbCrmDetail);
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            if (e instanceof DuplicateKeyException) {
                String errorColumn = e.getCause().toString();
                String[] strs = StringUtils.split(errorColumn, "-");
                String[] columns = StringUtils.split(strs[strs.length - 1], "\\'");
                throw ExceptionResultEnum.SQL_ERROR.exception(
                        FieldUniqueEnum.convertToTitle(columns[columns.length - 1]) + ":[" + columns[0] + "]数据不允许重复插入");
            } else if (e instanceof ApiException) {
                ResultUtil.error((ApiException) e, ((ApiException) e).getCode(), e.getMessage());
            } else {
                ResultUtil.error(e.getMessage());
            }
        }
        return false;
    }

    /**
     * 编辑派单明细研究生sop
     *
     * @param tbCrmDetailParam
     * @return
     */
    @Override
    @Transactional
    public boolean sopCloudMarkSave(TBCrmDetailParam tbCrmDetailParam) {
        try {
            SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
            TBCrmDetail tbCrmDetail = GsonUtil.fromJson(JacksonUtil.parseJson(tbCrmDetailParam), TBCrmDetail.class);
            if (Objects.isNull(tbCrmDetail.getId())) {//说明创建sop
                TFCustomFlow tfCustomFlow = tbCrmDetailService.queryCustomFlow(tbCrmDetail.getCrmNo());
                tbCrmDetail.createSop(tfCustomFlow.getFlowDeploymentId(), sysUser.getId());
                tbCrmDetail.initCloudMarkSop();
            } else {
                TBCrmDetail tbCrmDetailDb = tbCrmDetailService.getById(tbCrmDetail.getId());
                Objects.requireNonNull(tbCrmDetailDb, "未找到派单sop信息");

                tbCrmDetail.updateSop(tbCrmDetailDb, sysUser.getId());
                if (tbCrmDetail.getStatus() == CrmStatusEnum.PUBLISH) {
                    SopStatusEnum sopStatus = tbSopInfoService.findBySopNo(tbCrmDetail.getSopNo());
                    if (sopStatus == SopStatusEnum.START) {
                        throw ExceptionResultEnum.ERROR.exception("该条sop状态已改变，请刷新页面");
                    }
                    CrmProjectResult crmProjectResult = tbCrmService.findCrmProjectInfo(tbCrmDetail.getSopNo(),
                            tbCrmDetail.getId(), tbCrmDetail.getCrmNo());
                    Objects.requireNonNull(crmProjectResult, "未找到派单信息");
                    tbDingService.resetDingExceptionBySopNo(tbCrmDetail.getSopNo());
                }
            }
            return tbCrmDetailService.saveOrUpdate(tbCrmDetail);
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            if (e instanceof DuplicateKeyException) {
                String errorColumn = e.getCause().toString();
                String[] strs = StringUtils.split(errorColumn, "-");
                String[] columns = StringUtils.split(strs[strs.length - 1], "\\'");
                throw ExceptionResultEnum.SQL_ERROR.exception(
                        FieldUniqueEnum.convertToTitle(columns[columns.length - 1]) + ":[" + columns[0] + "]数据不允许重复插入");
            } else if (e instanceof ApiException) {
                ResultUtil.error((ApiException) e, ((ApiException) e).getCode(), e.getMessage());
            } else {
                ResultUtil.error(e.getMessage());
            }
        }
        return false;
    }

    /**
     * 自动创建派单明细研究生sop
     *
     * @param tbCrmDetailParam
     * @return
     */
    @Override
    @Transactional
    public boolean sopAutoCloudMarkCreate(TBCrmDetailParam tbCrmDetailParam) {
        try {
            SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
            TBCrmDetail tbCrmDetail = GsonUtil.fromJson(JacksonUtil.parseJson(tbCrmDetailParam), TBCrmDetail.class);
            TFCustomFlow tfCustomFlow = tbCrmDetailService.queryCustomFlow(tbCrmDetail.getCrmNo());
            tbCrmDetail.createSop(tfCustomFlow.getFlowDeploymentId(), sysUser.getId());
            tbCrmDetail.initCloudMarkSop();
            return tbCrmDetailService.save(tbCrmDetail);
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            if (e instanceof DuplicateKeyException) {
                String errorColumn = e.getCause().toString();
                String[] strs = StringUtils.split(errorColumn, "-");
                String[] columns = StringUtils.split(strs[strs.length - 1], "\\'");
                throw ExceptionResultEnum.SQL_ERROR.exception(
                        FieldUniqueEnum.convertToTitle(columns[columns.length - 1]) + ":[" + columns[0] + "]数据不允许重复插入");
            } else if (e instanceof ApiException) {
                ResultUtil.error((ApiException) e, ((ApiException) e).getCode(), e.getMessage());
            } else {
                ResultUtil.error(e.getMessage());
            }
        }
        return false;
    }

    /**
     * 查询自定义流程
     *
     * @param crmNo
     * @return
     */
    @Override
    public TFCustomFlow queryCustomFlow(String crmNo) {
        TBCrm tbCrm = tbCrmService.findByCrmNo(crmNo);
        Objects.requireNonNull(tbCrm, "未找到派单号");
        TBService tbService = tbServiceService.getById(tbCrm.getServiceId());
        Objects.requireNonNull(tbService, "未找到服务单元");

        TFCustomFlow tfCustomFlow = null;
        if (tbService.getType() == ProductTypeEnum.OFFICE) {
            if (Objects.isNull(tbCrm.getProcessVar()) || Objects.equals(tbCrm.getProcessVar().trim(), "")) {
                throw ExceptionResultEnum.ERROR.exception("请先保存属性【部署方式】【阅卷方式】【扫描场地网络】");
            }
            tfCustomFlow = tfCustomFlowService.findMaxVersion(null, null, TFCustomTypeEnum.OFFICE_SOP_FLOW);
            Objects.requireNonNull(tfCustomFlow, "未找到教务处流程");
        } else {
            tfCustomFlow = tfCustomFlowService.findMaxVersion(null, null, TFCustomTypeEnum.CLOUD_MARK_SOP_FLOW);
            Objects.requireNonNull(tfCustomFlow, "未找到研究生流程");
        }
        return tfCustomFlow;
    }

    /**
     * 派单明细sop发布
     *
     * @param id
     * @return
     */
    @Override
    @Transactional
    public boolean sopPublish(Long id) throws Exception {
        TBCrmDetail tbCrmDetail = tbCrmDetailService.getById(id);
        Objects.requireNonNull(tbCrmDetail, "未找到派单sop信息");

        if (tbCrmDetail.getStatus() == CrmStatusEnum.PUBLISH) {
            throw ExceptionResultEnum.ERROR.exception("该条派单sop已经发布");
        }
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        tbCrmDetail.updateStatus(CrmStatusEnum.PUBLISH, sysUser.getId());

        TBCrm tbCrm = tbCrmService.findByCrmNo(tbCrmDetail.getCrmNo());
        //发布流程
        TFCustomFlow tfCustomFlow = tbCrmDetailService.queryCustomFlow(tbCrmDetail.getCrmNo());

        if (tfCustomFlow.getType() == TFCustomTypeEnum.OFFICE_SOP_FLOW) {
            if (Objects.nonNull(tbCrmDetail.getScanStartTime()) && Objects.nonNull(tbCrmDetail.getScanEndTime())
                    && tbCrmDetail.getScanEndTime().longValue() <= tbCrmDetail.getScanStartTime().longValue()) {
                throw ExceptionResultEnum.ERROR.exception("扫描结束时间不能小于等于扫描开始时间");
            }
            if (Objects.nonNull(tbCrmDetail.getScanEndTime()) && Objects.nonNull(tbCrmDetail.getMarkPaperStartTime())
                    && tbCrmDetail.getMarkPaperStartTime().longValue() <= tbCrmDetail.getScanEndTime().longValue()) {
                throw ExceptionResultEnum.ERROR.exception("阅卷开始时间不能小于等于扫描结束时间");
            }
            if (Objects.nonNull(tbCrmDetail.getMarkPaperStartTime()) && Objects.nonNull(
                    tbCrmDetail.getMarkPaperEndTime())
                    && tbCrmDetail.getMarkPaperEndTime().longValue() <= tbCrmDetail.getMarkPaperStartTime()
                    .longValue()) {
                throw ExceptionResultEnum.ERROR.exception("阅卷结束时间不能小于等于阅卷开始时间");
            }
        }

        Map<String, Object> var = new HashMap<>();
        var.put(SystemConstant.CRM_DETAIL, tbCrmDetail);
        var.put(SystemConstant.PROCESS_VAR, tbCrm.getProcessVar());

        SopPublishParam sopPublishParam = new SopPublishParam(tbCrmDetail.getCrmNo(), tbCrmDetail.getId(),
                tfCustomFlow.getFlowDeploymentId(), FlowApprovePassEnum.DRAFT, null, null, var);
        String sopNo = tbSopInfoService.sopPublish(sopPublishParam);
        tbCrmDetail.setSopNo(sopNo);
        return tbCrmDetailService.updateById(tbCrmDetail);
    }

    /**
     * 派单明细sop删除
     *
     * @param id
     * @return
     */
    @Override
    @Transactional
    public boolean sopDelete(Long id) {
        TBCrmDetail tbCrmDetail = tbCrmDetailService.getById(id);
        Objects.requireNonNull(tbCrmDetail, "未找到派单sop信息");

        if (tbCrmDetail.getStatus() == CrmStatusEnum.PUBLISH) {
            SopStatusEnum sopStatus = tbSopInfoService.findBySopNo(tbCrmDetail.getSopNo());
            if (sopStatus == SopStatusEnum.START) {
                throw ExceptionResultEnum.ERROR.exception("该条sop状态已改变，请刷新页面");
            }
            if (Objects.nonNull(tbCrmDetail.getSopNo())) {
                TFCustomFlowEntity tfCustomFlowEntity = tfCustomFlowEntityService.findByCode(tbCrmDetail.getSopNo());
                activitiService.flowEnd(tfCustomFlowEntity.getFlowId());
            }
        }
        boolean result = tbCrmDetailService.removeById(tbCrmDetail.getId());
        int count = tbCrmDetailService.count(
                new QueryWrapper<TBCrmDetail>().lambda().eq(TBCrmDetail::getStatus, CrmStatusEnum.PUBLISH));
        if (count == 0) {
            tbCrmService.updateCrmStatus(tbCrmDetail.getCrmNo(), CrmStatusEnum.UN_PUBLISH);
        }
        return result;
    }

    /**
     * 根据sopNo查询派单明细
     *
     * @param sopNo
     * @return
     */
    @Override
    public TBCrmDetail findBySopNo(String sopNo) {
        TFCustomFlowEntity tfCustomFlowEntity = tfCustomFlowEntityService.findByCode(sopNo);
        TFCustomFlow tfCustomFlow = tfCustomFlowService.findById(tfCustomFlowEntity.gettFCustomFlowId());

        TBCrmDetail tbCrmDetail = null;
        if (tfCustomFlow.getType() == TFCustomTypeEnum.CLOUD_MARK_SOP_FLOW
                || tfCustomFlow.getType() == TFCustomTypeEnum.OFFICE_SOP_FLOW) {
            tbCrmDetail = tbCrmDetailService.getOne(
                    new QueryWrapper<TBCrmDetail>().lambda().eq(TBCrmDetail::getSopNo, sopNo));
            Objects.requireNonNull(tbCrmDetail, "未找到派单sop信息");
        }
        return tbCrmDetail;
    }

    /**
     * 根据id查询流程状态
     *
     * @param id
     * @return
     */
    @Override
    public FlowStatusEnum findById(Long id) {
        TBCrmDetail tbCrmDetail = tbCrmDetailService.getById(id);
        Objects.requireNonNull(tbCrmDetail, "未找到派单sop信息");

        TFFlowApprove tfFlowApprove = null;
        if (tbCrmDetail.getStatus() == CrmStatusEnum.PUBLISH) {
            TFCustomFlowEntity tfCustomFlowEntity = tfCustomFlowEntityService.findByCode(tbCrmDetail.getSopNo());
            tfFlowApprove = tfFlowApproveService.findByFlowId(tfCustomFlowEntity.getFlowId());
        }
        return Objects.nonNull(tfFlowApprove) ? tfFlowApprove.getStatus() : null;
    }

    @Override
    public List<TBCrmDetail> findByServiceIdAndCustomId(Long serviceId, Long customId) {
        return this.baseMapper.findByServiceIdAndCustomId(serviceId, customId);
    }

    /**
     * 保存实际时间
     *
     * @param type
     * @param tfFlowApprove
     * @param tbCrmDetail
     */
    @Override
    @Transactional
    public void saveActualTime(TFCustomTypeEnum type, TFFlowApprove tfFlowApprove, TBCrmDetail tbCrmDetail) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        Long updateTime = tbCrmDetail.getUpdateTime();
        if (type == TFCustomTypeEnum.OFFICE_SOP_FLOW) {
            if (tfFlowApprove.getSetup().intValue() == 3) {//扫描收尾检查
                tbCrmDetail.setScanActualStartTime(tfFlowApprove.getUpdateTime());
                tbCrmDetail.updateInfo(sysUser.getId());
            } else if (tfFlowApprove.getSetup().intValue() == 4) {//阅卷参数检查
                tbCrmDetail.setScanActualEndTime(tfFlowApprove.getUpdateTime());
                tbCrmDetail.updateInfo(sysUser.getId());
            } else if (tfFlowApprove.getSetup().intValue() == 5) {//阅卷收尾检查
                tbCrmDetail.setMarkPaperActualStartTime(tfFlowApprove.getUpdateTime());
                tbCrmDetail.updateInfo(sysUser.getId());
            } else if (tfFlowApprove.getSetup().intValue() == 0) {//结束
                tbCrmDetail.setMarkPaperActualEndTime(tfFlowApprove.getUpdateTime());
                tbCrmDetail.updateInfo(sysUser.getId());
            }
        } else if (type == TFCustomTypeEnum.CLOUD_MARK_SOP_FLOW) {
            if (tfFlowApprove.getSetup().intValue() == 5) {//扫描准备
                tbCrmDetail.setScanActualStartTime(tfFlowApprove.getUpdateTime());
                tbCrmDetail.updateInfo(sysUser.getId());
            } else if (tfFlowApprove.getSetup().intValue() == 7) {//校验收尾
                tbCrmDetail.setScanActualEndTime(tfFlowApprove.getUpdateTime());
                tbCrmDetail.updateInfo(sysUser.getId());
            } else if (tfFlowApprove.getSetup().intValue() == 8) {//成绩复核
                tbCrmDetail.setMarkPaperActualStartTime(tfFlowApprove.getUpdateTime());
                tbCrmDetail.updateInfo(sysUser.getId());
            } else if (tfFlowApprove.getSetup().intValue() == 0) {//结束
                tbCrmDetail.setMarkPaperActualEndTime(tfFlowApprove.getUpdateTime());
                tbCrmDetail.updateInfo(sysUser.getId());
            }
        }
        if (Objects.isNull(updateTime) || updateTime.longValue() != tbCrmDetail.getUpdateTime().longValue()) {
            tbCrmDetailService.updateById(tbCrmDetail);
        }
    }
}
