package com.zt.plat.module.qms.business.reportdoc.service;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zt.plat.framework.common.pojo.CommonResult;
import com.zt.plat.framework.common.pojo.PageResult;
import com.zt.plat.framework.common.util.object.BeanUtils;
import com.zt.plat.framework.datapermission.core.annotation.DeptDataPermissionIgnore;
import com.zt.plat.framework.security.core.LoginUser;
import com.zt.plat.framework.security.core.util.SecurityFrameworkUtils;
import com.zt.plat.module.bpm.api.task.BpmProcessInstanceApi;
import com.zt.plat.module.bpm.api.task.BpmTaskApi;
import com.zt.plat.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import com.zt.plat.module.bpm.api.task.dto.BpmTaskApproveReqDTO;
import com.zt.plat.module.bpm.api.task.dto.BpmTaskRespDTO;
import com.zt.plat.module.infra.api.businessfile.BusinessFileApi;
import com.zt.plat.module.infra.api.businessfile.dto.BusinessFilePageReqDTO;
import com.zt.plat.module.infra.api.businessfile.dto.BusinessFileRespDTO;
import com.zt.plat.module.infra.api.file.FileApi;
import com.zt.plat.module.infra.api.file.dto.FileRespDTO;
import com.zt.plat.module.qms.api.task.BMPCallbackInterface;
import com.zt.plat.module.qms.api.task.dto.QmsBpmDTO;
import com.zt.plat.module.qms.business.bus.controller.vo.BusinessAssayReportDataPageReqVO;
import com.zt.plat.module.qms.business.bus.dal.dataobject.BusinessAssayReportDataDO;
import com.zt.plat.module.qms.business.bus.dal.dataobject.BusinessSampleEntrustRegistrationDO;
import com.zt.plat.module.qms.business.bus.service.BusinessAssayReportDataService;
import com.zt.plat.module.qms.business.bus.service.BusinessSampleEntrustRegistrationService;
import com.zt.plat.module.qms.business.config.dal.dataobject.ConfigUserSignatureDO;
import com.zt.plat.module.qms.business.config.service.ConfigUserSignatureService;
import com.zt.plat.module.qms.business.reportdoc.constant.ReportDocConstant;
import com.zt.plat.module.qms.business.reportdoc.controller.vo.*;
import com.zt.plat.module.qms.business.reportdoc.dal.dataobject.*;
import com.zt.plat.module.qms.business.reportdoc.dal.mapper.ReportDocumentMainMapper;
import com.zt.plat.module.qms.common.data.service.DataKeyCheckService;
import com.zt.plat.module.qms.core.code.SequenceUtil;
import com.zt.plat.module.qms.enums.QmsBpmConstant;
import com.zt.plat.module.qms.enums.QmsCommonConstant;
import com.zt.plat.module.system.mq.iwork.IWorkBizCallbackMessage;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception0;
import static com.zt.plat.framework.common.pojo.CommonResult.error;
import static com.zt.plat.module.qms.enums.ErrorCodeConstants.*;
import static com.zt.plat.module.qms.enums.QmsBpmConstant.BPM_CALLBACK_BEAN_NAME;

/**
 * 检测报告业务 Service 实现类
 *
 * @author 后台管理
 */
@Service("reportDocumentMainService")
@Validated
@Slf4j
@DeptDataPermissionIgnore(enable = "true")
public class ReportDocumentMainServiceImpl implements ReportDocumentMainService, BMPCallbackInterface {

    @Resource private ReportDocumentMainMapper reportDocumentMainMapper;
    @Resource private BusinessAssayReportDataService businessAssayReportDataService;
    @Resource private ReportDocumentDataService reportDocumentDataService;
    @Resource private BpmProcessInstanceApi bpmProcessInstanceApi;
    @Resource private BpmTaskApi bpmTaskApi;
    @Resource private BusinessFileApi businessFileApi;
    @Resource private FileApi fileApi;
    @Resource private ReportDocumentMainCorrelationService reportDocumentMainCorrelationService;
    @Resource private ReportDocumentTypeService reportDocumentTypeService;
    @Resource private ConfigUserSignatureService configUserSignatureService;
    @Resource private BusinessSampleEntrustRegistrationService businessSampleEntrustRegistrationService;
    @Resource private ReportDocumentAssistService reportDocumentAssistService;
    @Resource private ReportDocumentFileService reportDocumentFileService;
    @Resource private DataKeyCheckService dataKeyCheckService;
    @Resource private SequenceUtil sequenceUtil;

    /*
    * 测试异步执行
    * */
    @Async("asyncTaskExecutor")
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void testAsyncTask(Long id) {
        ReportDocumentMainDO entity = reportDocumentMainMapper.selectById(id);
        entity.setFlowStatus("success");
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        reportDocumentMainMapper.updateById(entity);
    }

    /***
     * 增加报表数据（按样品）
     * 传入：报告id、 报表数据ids
     * */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<String> execAddDataBySample(ReportDocumentMainSaveReqVO reqVO) {
        Long id = reqVO.getId();
        String businessAssayReportDataIds = reqVO.getBusinessAssayReportDataIds();
        List<Long> addReportDataIdList = new ArrayList<>();
        if(!ObjectUtils.isEmpty(businessAssayReportDataIds)){
            String[] split = businessAssayReportDataIds.split(",");
            for (String s : split) {
                Long aLong = Long.valueOf(s);
                addReportDataIdList.add(aLong);
            }
        }
        if(ObjectUtils.isEmpty(businessAssayReportDataIds) || addReportDataIdList.isEmpty())
            return error(REPORT_DOCUMENT_DATA_NOT_EXISTS.getCode(), "缺少businessAssayReportDataIds参数，请刷新后重试");
        List<ReportDocumentDataDO> savedDataList = reportDocumentDataService.listByMainDataId(id).getData();
        List<Long> hasIds = savedDataList.stream().map(ReportDocumentDataDO::getSourceId).toList();
        boolean isExist = false;
        for (Long addReportDataId : addReportDataIdList) {
            if(hasIds.contains(addReportDataId)){
                isExist = true;
                break;
            }
        }
        if(isExist)
            return error(REPORT_DOCUMENT_DATA_NOT_EXISTS.getCode(), "报表数据已在本报告使用，请勿重复添加");
        BusinessAssayReportDataPageReqVO reportDataQueryVo = new BusinessAssayReportDataPageReqVO();
        reportDataQueryVo.setIdList(addReportDataIdList);
        reportDataQueryVo.setPageNo(1);
        reportDataQueryVo.setPageSize(9999);
        PageResult<BusinessAssayReportDataDO> assayReportPage = businessAssayReportDataService.queryWaitingDataForReport( reportDataQueryVo);
        List<BusinessAssayReportDataDO> assayReportDataList = assayReportPage.getList();
        return execAddByBusinessAssayReportData(assayReportDataList, id, new ArrayList<>());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<String> execAddDataByEntrust(ReportDocumentMainSaveReqVO reqVO) {
        Long id = reqVO.getId();
        String businessSampleEntrustRegistrationIds = reqVO.getBusinessSampleEntrustRegistrationIds();
        if(id == null)
            return error(REPORT_DOCUMENT_DATA_NOT_EXISTS.getCode(), "缺少id参数，请刷新后重试");
        if(ObjectUtils.isEmpty(businessSampleEntrustRegistrationIds))
            return error(REPORT_DOCUMENT_DATA_NOT_EXISTS.getCode(), "缺少businessSampleEntrustRegistrationIds参数，请刷新后重试");
        List<Long> businessSampleEntrustRegistrationIdList = new ArrayList<>();
        String[] split = businessSampleEntrustRegistrationIds.split(",");
        for (String s : split) {
            Long aLong = Long.valueOf(s);
            businessSampleEntrustRegistrationIdList.add(aLong);
        }
        List<BusinessSampleEntrustRegistrationDO> entrustList = businessSampleEntrustRegistrationService.listByIds(businessSampleEntrustRegistrationIdList);
        BusinessAssayReportDataPageReqVO reportDataQueryVo = new BusinessAssayReportDataPageReqVO();
        reportDataQueryVo.setBusinessSampleEntrustRegistrationIdList(businessSampleEntrustRegistrationIdList);
        reportDataQueryVo.setPageNo(1);
        reportDataQueryVo.setPageSize(9999);
        PageResult<BusinessAssayReportDataDO> assayReportPage = businessAssayReportDataService.queryWaitingDataForReport( reportDataQueryVo);
        List<BusinessAssayReportDataDO> assayReportDataList = assayReportPage.getList();
        CommonResult<String> ret = execAddByBusinessAssayReportData(assayReportDataList, id, entrustList);
        if(!ret.isSuccess())
            return ret;
        //保存报告关系表
        List<ReportDocumentMainCorrelationDO> correlationList = new ArrayList<>();
        for(Long businessSampleEntrustRegistrationId : businessSampleEntrustRegistrationIdList){
            ReportDocumentMainCorrelationDO correlationEntity = new ReportDocumentMainCorrelationDO();
            correlationEntity.setMainId( id);
            correlationEntity.setCorrelationId(businessSampleEntrustRegistrationId);
            correlationEntity.setCorrelationType(ReportDocumentMainCorrelationService.CorrelationType_entrust);
            correlationList.add(correlationEntity);
        }
        if(!correlationList.isEmpty())
            reportDocumentMainCorrelationService.insertBatch(correlationList);

        return CommonResult.success("操作成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<String> execAddByBusinessAssayReportData(List<BusinessAssayReportDataDO> assayReportDataList, Long id, List<BusinessSampleEntrustRegistrationDO> entrustList){
        if(ObjectUtils.isEmpty(assayReportDataList))
            return error(REPORT_DOCUMENT_DATA_NOT_EXISTS.getCode(), "您选择的委托还没产生可编制报告的数据，请稍后重试！");
        List<ReportDocumentDataDO> insertList = new ArrayList<>();
        for (BusinessAssayReportDataDO assayReportData : assayReportDataList) {
            ReportDocumentDataDO reportDocumentDataDO = new ReportDocumentDataDO();
            reportDocumentDataDO.setMainId(id);
            reportDocumentDataDO.setSourceId(assayReportData.getId());
            reportDocumentDataDO.setSampleCode(assayReportData.getSampleCode());
            reportDocumentDataDO.setSampleName(assayReportData.getSampleName());
            reportDocumentDataDO.setBaseSampleName(assayReportData.getBaseSampleName());
            reportDocumentDataDO.setDocumentContent(assayReportData.getAssayData());
            reportDocumentDataDO.setSampleTypeKey(assayReportData.getSampleTypeKey());
            reportDocumentDataDO.setEntrustSampleCode(assayReportData.getEntrustSampleCode());
            reportDocumentDataDO.setEntrustSampleName(assayReportData.getEntrustSampleName());
            reportDocumentDataDO.setSort(assayReportData.getEntrustDetailSort());
            insertList.add(reportDocumentDataDO);
        }
        if(!insertList.isEmpty())
            reportDocumentDataService.insertBatch(insertList);
        ReportDocumentMainDO reportDocumentMainDO = reportDocumentMainMapper.selectById(id);
        ReportDocumentTypeDO typeDO = reportDocumentTypeService.getReportDocumentType(reportDocumentMainDO.getReportDocumentTypeId());
        updateCommonField(reportDocumentMainDO, typeDO);

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String formData = reportDocumentMainDO.getFormData();
        JSONObject formDataJson = new JSONObject();
        if(!ObjectUtils.isEmpty(formData))
            formDataJson = JSONObject.parseObject(formData);

        String customConfig = typeDO.getCustomConfig();
        String defaultConclusion = "";
        if(!ObjectUtils.isEmpty(customConfig)){
            JSONObject config = JSONObject.parseObject(customConfig);
            defaultConclusion = config.getString("defaultConclusion");
        }
        formDataJson.put("conclusion", defaultConclusion);
        if(!assayReportDataList.isEmpty())
            formDataJson.put("sampleName", assayReportDataList.get(0).getSampleName());
        //处理检测标准
        String standard = assembleStandard(assayReportDataList);
        formDataJson.put("standard", standard);
        formDataJson.put("reportTime", sdf.format(new Date()));

        //委托单号
        String entrustCode = "";
        String entrustId = "";
        String sampleCategoryForTitle = "";
        if(!ObjectUtils.isEmpty(entrustList)){
            for(BusinessSampleEntrustRegistrationDO entrust : entrustList){
                entrustCode += entrust.getEntrustNumber() + ",";
                entrustId += entrust.getId() + ",";
                String externalInfomation = entrust.getExternalInfomation();
                if(!ObjectUtils.isEmpty(externalInfomation)){
                    JSONObject externalInfomationJson = JSONObject.parseObject(externalInfomation);
                    String sampleCategory = externalInfomationJson.getString("sampleCategory");
                    if(!ObjectUtils.isEmpty(sampleCategory)){
                        sampleCategoryForTitle = sampleCategory;
                        formDataJson.put("sampleCategory", sampleCategory);
                    }

                }
                break;
            }
        }
        if(!ObjectUtils.isEmpty(entrustCode))
            entrustCode = entrustCode.substring(0, entrustCode.length() - 1);
        if(!ObjectUtils.isEmpty(entrustId))
            entrustId = entrustId.substring(0, entrustId.length() - 1);
        formDataJson.put("entrustCode", entrustCode);
        formDataJson.put("entrustId", entrustId);


        String documentTitle = reportDocumentMainDO.getDocumentTitle();
        if(!ObjectUtils.isEmpty(sampleCategoryForTitle))
            documentTitle = sampleCategoryForTitle + "-" + documentTitle;
        if(!ObjectUtils.isEmpty(entrustCode))
            documentTitle = entrustCode + "-" + documentTitle;
       reportDocumentMainDO.setDocumentTitle(documentTitle);

        reportDocumentMainDO.setFormData(formDataJson.toJSONString());
        reportDocumentMainMapper.updateById(reportDocumentMainDO);
        return CommonResult.success("操作成功");
    }

    //组装检测标准
    private String assembleStandard(List<BusinessAssayReportDataDO> dataList){
        Set<String> standardSet = new HashSet<>();
        for(BusinessAssayReportDataDO data : dataList){
            String content = data.getAssayData();
            if(ObjectUtils.isEmpty( content))
                continue;
            JSONObject json = JSONObject.parseObject(content);
            for(String key : json.keySet()){
                JSONObject obj = json.getJSONObject(key);
                if ("ingredient".equals(obj.get("usage"))) {//如果是配料的，则不拼接
					continue;
				}
                String methodName = obj.getString("methodName");
                if(ObjectUtils.isEmpty(methodName))
                    continue;
                standardSet.add(methodName);
            }
        }
        if(standardSet.isEmpty())
            return "";
        return String.join(",", standardSet);
    }

    @Override
    public void updateCommonField(ReportDocumentMainDO reportDocumentMainDO, ReportDocumentTypeDO typeDO) {
        if(reportDocumentMainDO == null)
            return;
        String documentCode = reportDocumentMainDO.getDocumentCode();
        if(ObjectUtils.isEmpty(documentCode)){
            String codeRule = typeDO.getCodeRule();
            documentCode = sequenceUtil.genCode(codeRule);
            reportDocumentMainDO.setDocumentCode(documentCode);
        }
        if(reportDocumentMainDO.getCancelFlag() == null || reportDocumentMainDO.getCancelFlag().equals("-1"))
            reportDocumentMainDO.setCancelFlag("0");
    }

    /***
     * 增加报表数据
     * 传入：报告id、 报告明细数据id
     * */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<String> execRemoveData(ReportDocumentMainSaveReqVO reqVO) {
        Long id = reqVO.getId();
        String reportDocumentDataIds = reqVO.getReportDocumentDataIds();
        List<Long> reportDocumentDataIdsList = new ArrayList<>();
        if(!ObjectUtils.isEmpty(reportDocumentDataIds)){
            String[] split = reportDocumentDataIds.split(",");
            for (String s : split) {
                Long aLong = Long.valueOf(s);
                reportDocumentDataIdsList.add(aLong);
            }
        }
        if(ObjectUtils.isEmpty(reportDocumentDataIds) || reportDocumentDataIdsList.isEmpty())
            return error(REPORT_DOCUMENT_DATA_NOT_EXISTS, "缺少reportDocumentDataIds参数，请刷新后重试");
        return reportDocumentDataService.removeByMainIdAndDetailIds(id, reportDocumentDataIdsList);
    }

    //保存报告
    @Override
    public void doSave(ReportDocumentMainSaveReqVO updateReqVO) {
        Long id = updateReqVO.getId();
        // 校验存在
        validateReportDocumentMainExists(id);
        // 更新
        ReportDocumentMainDO updateObj = BeanUtils.toBean(updateReqVO, ReportDocumentMainDO.class);
        reportDocumentMainMapper.updateById(updateObj);
        List<ReportDocumentDataSaveReqVO> reportDocumentDataList = updateReqVO.getReportDocumentDataList();
        if(!reportDocumentDataList.isEmpty())
            reportDocumentDataService.updateBatch(reportDocumentDataList);
    }

    @Override
    public ReportDocumentMainRespVO createReportDocumentMain(ReportDocumentMainSaveReqVO createReqVO) {
        // 插入
        ReportDocumentMainDO reportDocumentMain = BeanUtils.toBean(createReqVO, ReportDocumentMainDO.class);
        reportDocumentMainMapper.insert(reportDocumentMain);
        // 返回
        return BeanUtils.toBean(reportDocumentMain, ReportDocumentMainRespVO.class);
    }

    @Override
    public void updateReportDocumentMain(ReportDocumentMainSaveReqVO updateReqVO) {
        // 校验存在
        validateReportDocumentMainExists(updateReqVO.getId());
        // 更新
        ReportDocumentMainDO updateObj = BeanUtils.toBean(updateReqVO, ReportDocumentMainDO.class);
        reportDocumentMainMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteReportDocumentMain(Long id) {
        // 校验存在
        validateReportDocumentMainExists(id);
        // 删除
        reportDocumentMainMapper.deleteById(id);
        //删除关联表
        reportDocumentMainCorrelationService.deleteByMainId(id);
        reportDocumentDataService.deleteByMainId(id);
    }

    @Override
    public void deleteReportDocumentMainListByIds(List<Long> ids) {
        // 校验存在
        validateReportDocumentMainExists(ids);
        // 删除
        reportDocumentMainMapper.deleteByIds(ids);
    }

    private void validateReportDocumentMainExists(List<Long> ids) {
        List<ReportDocumentMainDO> list = reportDocumentMainMapper.selectByIds(ids);
        if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
            throw exception(REPORT_DOCUMENT_MAIN_NOT_EXISTS);
        }
    }

    private void validateReportDocumentMainExists(Long id) {
        if (reportDocumentMainMapper.selectById(id) == null) {
            throw exception(REPORT_DOCUMENT_MAIN_NOT_EXISTS);
        }
    }

    @Override
    public ReportDocumentMainDO getReportDocumentMain(Long id) {
        return reportDocumentMainMapper.selectById(id);
    }

    @Override
    public ReportDocumentMainDO getByCode(String code) {
        LambdaQueryWrapper<ReportDocumentMainDO> query = new LambdaQueryWrapper<>();
        query.eq(ReportDocumentMainDO::getDocumentCode, code);
        query.orderByDesc(ReportDocumentMainDO::getCreateTime);
        List<ReportDocumentMainDO> list = reportDocumentMainMapper.selectList(query);
        return list.isEmpty() ? null : list.get(0);
    }

    @Override
    public PageResult<ReportDocumentMainRespVO> getReportDocumentMainPage(ReportDocumentMainPageReqVO pageReqVO) {
        return reportDocumentMainMapper.selectPage(pageReqVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<ReportDocumentMainRespVO> createProcessInstance(ReportDocumentMainSaveReqVO param) {
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        //当前登录用户昵称
        String nickName = SecurityFrameworkUtils.getLoginUserNickname();
        Long id = param.getId();
        ReportDocumentMainDO entity = getReportDocumentMain(id);
        String flowInsId = entity.getFlowInstanceId();

        if(!ObjectUtils.isEmpty(flowInsId)){
            CommonResult<List<BpmTaskRespDTO>> taskRet = bpmTaskApi.getTaskListByProcessInstanceId(flowInsId);
            List<BpmTaskRespDTO> taskList = taskRet.getData();
            if(taskList.isEmpty())
                throw exception0(ERROR_CODE_MODULE_COMMON, "流程任务查询失败，请联系管理员处理");
            String taskId = taskList.get(taskList.size() - 1).getId();
            //驳回后重新提交
            BpmTaskApproveReqDTO reqVO = new BpmTaskApproveReqDTO();
            reqVO.setId(taskId);
            CommonResult<Boolean> result = bpmProcessInstanceApi.approveTask(reqVO);
            if(!result.isSuccess()){
                throw exception0(ERROR_CODE_MODULE_COMMON, result.getMsg());
            }
            entity.setFlowStatus(QmsCommonConstant.IN_PROGRESS);
            reportDocumentMainMapper.updateById(entity);
            ReportDocumentMainRespVO respVO = BeanUtils.toBean(entity, ReportDocumentMainRespVO.class);
            return CommonResult.success(respVO);
        }

        JSONObject formData = new JSONObject();
        if(entity.getFormData() != null)
            formData = JSONObject.parseObject(entity.getFormData());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        formData.put("mainId",  id);
        formData.put("applyUser",  nickName);
        formData.put("applyUserId",  loginUser.getId());
        formData.put("applyDepartment",  loginUser.getVisitDeptName());
        formData.put("applyDepartmentId",  loginUser.getVisitDeptId());
        formData.put("applyTime",  sdf.format(new Date()));
        Map<String, Object> variables = formData.toJavaObject(Map.class);
        variables.put(BPM_CALLBACK_BEAN_NAME, "reportDocumentMainService"); //流程回调时使用的service
        BpmProcessInstanceCreateReqDTO reqDTO = new BpmProcessInstanceCreateReqDTO();
        reqDTO.setBusinessKey(String.valueOf(id));
        reqDTO.setProcessDefinitionKey(entity.getFlowKey());
        reqDTO.setVariables(variables);
        CommonResult<String> result = bpmProcessInstanceApi.createProcessInstance(loginUser.getId(), reqDTO);
        if(!result.isSuccess()){
            throw exception0(ERROR_CODE_MODULE_COMMON, result.getMsg());
        }
        String wfInsId = result.getData();
        entity.setFlowInstanceId(wfInsId);
        entity.setFlowStatus(QmsCommonConstant.IN_PROGRESS);
        reportDocumentMainMapper.updateById(entity);
        ReportDocumentMainRespVO respVO = BeanUtils.toBean(entity, ReportDocumentMainRespVO.class);
        return CommonResult.success(respVO);
    }

    //流程回调
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<JSONObject> callback(QmsBpmDTO reqDTO) {
        log.error("流程回调：{}", JSONObject.toJSONString(reqDTO));
        JSONObject variables = reqDTO.getVariables();
        String processInsId = variables.getString(QmsBpmConstant.BPM_PROCESS_INS_ID);
        String currentActivityInsId = variables.getString(QmsBpmConstant.BPM_CUR_ACTIVITY_INS_ID);
        String returnFlag = variables.getString(QmsBpmConstant.BPM_REJECT_TO_FIRST_FLAG); //退回标识。在任务监听中设置
        //同一个节点实例只触发一次
        String checkKey = currentActivityInsId;
        if(ObjectUtils.isEmpty(currentActivityInsId))
            checkKey = processInsId + "-create";
        if("1".equals(returnFlag))
            checkKey += "-reject";
        try{
            dataKeyCheckService.create(checkKey, this.getClass().getName());
        }catch (Exception e){
//            e.printStackTrace();
            log.error("checkKey 重复：key={}", checkKey);
            return CommonResult.success(new JSONObject());
        }
        //流程状态  1-提交（含退回）  4-取消流程
        String PROCESS_STATUS = variables.getString(QmsBpmConstant.PROCESS_INSTANCE_VARIABLE_STATUS);
        String mainId = variables.getString("mainId");
        JSONArray fieldExtensions = new JSONArray();
        if(variables.containsKey(QmsBpmConstant.BPM_FIELD_EXTENSIONS)){
            fieldExtensions = variables.getJSONArray(QmsBpmConstant.BPM_FIELD_EXTENSIONS);
        }
        ReportDocumentMainDO entity = getReportDocumentMain(Long.valueOf(mainId));
        String currentActivityId = variables.getString(QmsBpmConstant.BPM_CALLBACK_ACTIVITY_ID);

        //判断是否最后一个节点
        String lastActivityFlag = "0";
        String firstActivityFlag = "0";
        if(!fieldExtensions.isEmpty()){
            for(int i = 0; i < fieldExtensions.size(); i++){
                JSONObject extension = fieldExtensions.getJSONObject(i);
                String fieldName = extension.getString("fieldName");
                String stringValue = extension.getString("stringValue");
                if(ObjectUtils.isEmpty(stringValue))
                    stringValue = "";
                if(fieldName.equalsIgnoreCase(QmsBpmConstant.BPM_LAST_ACTIVITY_FLAG) && stringValue.equals("1")){
                    lastActivityFlag = "1";
                }
                if(fieldName.equalsIgnoreCase(QmsBpmConstant.BPM_FIRST_ACTIVITY_FLAG) && stringValue.equals("1")){
                    firstActivityFlag = "1";
                }
            }
        }
        //"RETURN_FLAG_Activity_001": true 标识驳回到发起环节
        if(("1").equals(returnFlag)){
            //驳回。流程需要配置退回到发起节点
            entity.setFlowStatus(QmsCommonConstant.REJECTED);
            entity.setDocumentSignature("");
        }else if("4".equals(PROCESS_STATUS)){
            //作废
            entity.setFlowStatus(QmsCommonConstant.VOID);
            entity.setDocumentSignature("");
        }else if("1".equals(PROCESS_STATUS)){
            //通过
            assembleSignature(currentActivityId, entity);
            if("1".equals(firstActivityFlag))
                entity.setFlowStatus(QmsCommonConstant.IN_PROGRESS);    //驳回后重新提交
            if("1".equals(lastActivityFlag))
                entity.setFlowStatus(QmsCommonConstant.COMPLETED);      //结束审批
        }
        boolean updateDocFileFlag = reportDocumentAssistService.checkUpdateDocFile(variables);
        if(updateDocFileFlag){
            Integer version = entity.getDocumentVersion();
            if(version == null)
                version = 1;
            else
                version++;
            entity.setDocumentVersion(version);     //版本+1
        }
        reportDocumentMainMapper.updateById(entity);

        try {
            reportDocumentAssistService.updateDocFileAndCreateIWorkflow( variables, entity);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        JSONObject ret = new JSONObject();
        return CommonResult.success(ret);
    }

    private void assembleSignature(String currentActivityId, ReportDocumentMainDO entity){
        if(ObjectUtils.isEmpty(currentActivityId) || "null".equals(currentActivityId))
            return;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String sign = entity.getDocumentSignature();
        JSONObject signObj = new JSONObject();
        if(!ObjectUtils.isEmpty( sign))
            signObj = JSONObject.parseObject(sign);
        if(signObj.containsKey(currentActivityId))
            return;
        JSONObject obj = new JSONObject();
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        Long userId = loginUser.getId();
        //当前登录用户昵称
        String nickName = SecurityFrameworkUtils.getLoginUserNickname();
        ConfigUserSignatureDO configUserSignatureDO = configUserSignatureService.getByUserId(userId);
        obj.put("signatureId", "");
        if(configUserSignatureDO != null)
            obj.put("signatureId", configUserSignatureDO.getId());
        obj.put("userId", userId);
        obj.put("userName", nickName);
        obj.put("signTime", sdf.format(new Date()));
        signObj.put(currentActivityId, obj);
        entity.setDocumentSignature(signObj.toJSONString());
    }

    /**
     * 处理报告用印iwork回调逻辑
     * 1. 解析 payload 获取回调数据
     * 2. 保存签章文件等
     * 3. 更新业务状态
     * */
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<String> execCallBackByIwork(IWorkBizCallbackMessage message){
        JSONObject payload = new JSONObject();
        try{
            Map<String, Object> payloadMap = (Map<String, Object>) message.getPayload();
            payload = new JSONObject(payloadMap);
        }catch (Exception e){
            log.error("iwork用印回调，解析回调数据失败", e.getMessage());
            e.getMessage();
            throw new RuntimeException("iwork用印回调，解析回调数据失败");
        }
        //获取附件对象
        String businessCode = payload.getString("businessCode");
        String fileName = payload.getString("fileName");
        String requestId = payload.getString("requestId");
        //获取主数据
        ReportDocumentMainDO mainDO = getByCode(businessCode);

        //查询附件对象
        BusinessFilePageReqDTO pageReqDTO = new BusinessFilePageReqDTO();
        pageReqDTO.setBusinessCode(businessCode);
        pageReqDTO.setSource(ReportDocConstant.REPORT_DOCUMENT_BUSINESS_FILE_SOURCE_IWORK);
        CommonResult<PageResult<BusinessFileRespDTO>> bisFileRet = businessFileApi.getBusinessFilePage(pageReqDTO);
        if(!bisFileRet.isSuccess()){
            log.error("iwork用印回调，查询回调附件失败！" + bisFileRet.getMsg());
            throw new RuntimeException("iwork用印回调，查询回调附件失败！");
        }
        PageResult<BusinessFileRespDTO> bisFilePage = bisFileRet.getData();
        List<BusinessFileRespDTO> bisFileList = bisFilePage.getList();
        if(bisFileList == null || bisFileList.isEmpty()){
            log.error("iwork用印回调，附件不存在！" + bisFileRet.getMsg());
            throw new RuntimeException("iwork用印回调，附件不存在！");
        }
        BusinessFileRespDTO bisFile = bisFileList.get(0);
        Long fileId = bisFile.getFileId();
        CommonResult<FileRespDTO> fileRet = fileApi.getFile(fileId);
        FileRespDTO fileRespDTO = fileRet.getData();
        //写入ReportDocumentFile
        ReportDocumentFileDO documentFileDO = new ReportDocumentFileDO();
        documentFileDO.setMainId(mainDO.getId());
        documentFileDO.setFileId(fileRespDTO.getId());
        documentFileDO.setName(fileName);
        documentFileDO.setPath(fileRespDTO.getDirectory());
        documentFileDO.setUrl(fileRespDTO.getUrl());
        documentFileDO.setVersion(mainDO.getDocumentVersion());
        documentFileDO.setType(ReportDocConstant.REPORT_DOCUMENT_BUSINESS_FILE_SOURCE_IWORK);
        reportDocumentFileService.createReportDocumentFile(documentFileDO);

        //触发流程提交
        String flowInsId = mainDO.getFlowInstanceId();
        CommonResult<List<BpmTaskRespDTO>> taskRet = bpmTaskApi.getTaskListByProcessInstanceId(flowInsId);
        List<BpmTaskRespDTO> taskList = taskRet.getData();
        if(taskList.isEmpty())
            throw exception0(ERROR_CODE_MODULE_COMMON, "流程任务查询失败，请联系管理员处理");
        String taskId = taskList.get(taskList.size() - 1).getId();
        //提交流程
        BpmTaskApproveReqDTO reqVO = new BpmTaskApproveReqDTO();
        reqVO.setId(taskId);
        CommonResult<Boolean> result = bpmProcessInstanceApi.approveTask(reqVO);
        return CommonResult.success("");
    }

}
