package com.yeejoin.amos.boot.module.jg.biz.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.utils.RedisKey;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.boot.module.jg.api.dto.*;
import com.yeejoin.amos.boot.module.jg.api.entity.JgScrapCancel;
import com.yeejoin.amos.boot.module.jg.api.entity.JgScrapCancelEq;
import com.yeejoin.amos.boot.module.jg.api.enums.BusinessTypeEnum;
import com.yeejoin.amos.boot.module.jg.api.enums.CancelTypeEnum;
import com.yeejoin.amos.boot.module.jg.api.enums.WorkFlowStatusEnum;
import com.yeejoin.amos.boot.module.jg.api.mapper.JgScrapCancelEqMapper;
import com.yeejoin.amos.boot.module.jg.api.mapper.JgScrapCancelMapper;
import com.yeejoin.amos.boot.module.jg.api.service.IJgScrapCancelService;
import com.yeejoin.amos.boot.module.jg.biz.feign.TzsServiceFeignClient;
import com.yeejoin.amos.boot.module.jg.biz.service.IIdxBizJgRegisterInfoService;
import com.yeejoin.amos.boot.module.jg.flc.api.fegin.WorkFlowFeignService;
import com.yeejoin.amos.boot.module.ymt.api.entity.IdxBizJgRegisterInfo;
import com.yeejoin.amos.boot.module.ymt.api.entity.IdxBizJgUseInfo;
import com.yeejoin.amos.boot.module.ymt.api.entity.OtherInfo;
import com.yeejoin.amos.boot.module.ymt.api.entity.SuperviseInfo;
import com.yeejoin.amos.boot.module.ymt.api.enums.ApplicationFormTypeEnum;
import com.yeejoin.amos.boot.module.ymt.api.enums.EquimentEnum;
import com.yeejoin.amos.boot.module.ymt.api.enums.EquipmentClassifityEnum;
import com.yeejoin.amos.boot.module.ymt.api.enums.FlowStatusEnum;
import com.yeejoin.amos.boot.module.ymt.api.mapper.*;
import com.yeejoin.amos.feign.systemctl.model.TaskV2Model;
import com.yeejoin.amos.feign.workflow.model.ActWorkflowBatchDTO;
import com.yeejoin.amos.feign.workflow.model.ActWorkflowStartDTO;
import com.yeejoin.amos.feign.workflow.model.ProcessTaskDTO;
import com.yeejoin.amos.feign.workflow.model.TaskResultDTO;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.rdbms.service.BaseService;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;
import org.typroject.tyboot.core.restful.utils.ResponseModel;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 设备报废注销服务实现类
 *
 * @author system_generator
 * @date 2023-12-20
 */
@Service
public class JgScrapCancelServiceImpl extends BaseService<JgScrapCancelDto, JgScrapCancel, JgScrapCancelMapper> implements IJgScrapCancelService {


    private static final String SUBMIT_TYPE_FLOW = "1";
    private static final String PAGE_KEY = "jgScrapCancelAdd";
    private static final String template = "来自%s【%s】【%s】的业务办理，【申请单号：%s】";
    @Autowired
    WorkFlowFeignService workFlowFeginService;
    @Autowired
    TzsServiceFeignClient tzsServiceFeignClient;
    @Autowired
    IdxBizJgOtherInfoMapper idxBizJgOtherInfoMapper;
    @Autowired
    SuperviseInfoMapper superviseInfoMapper;
    @Autowired
    CommonServiceImpl commonService;
    @Autowired
    CmWorkflowServiceImpl cmWorkflowService;
    @Autowired
    RedisUtils redisUtils;
    @Autowired
    IdxBizJgRegisterInfoMapper idxBizJgRegisterInfoMapper;
    @Autowired
    IIdxBizJgRegisterInfoService idxBizJgRegisterInfoService;
    @Autowired
    private OtherInfoMapper otherInfoMapper;
    @Autowired
    private JgScrapCancelEqServiceImpl jgScrapCancelEqService;
    @Autowired
    private JgScrapCancelEqMapper jgScrapCancelEqMapper;
    @Autowired
    private IdxBizJgUseInfoMapper idxBizJgUseInfoMapper;

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 移装移装注销/报废注销判断
     *
     * @return BusinessTypeEnum 业务对应枚举
     */
    public static BusinessTypeEnum businessTypeJudgment(String type) {
        return "1".equals(type) ? BusinessTypeEnum.JG_EQUIPMENT_CANCEL : BusinessTypeEnum.JG_EQUIPMENT_MOVE;
    }

    public Page<Map<String, Object>> getList(JgScrapCancelDto dto, Page<Map<String, Object>> page, List<String> roleIds) {
        ReginParams reginParams = this.getSelectedOrgInfo();
        String orgCode = reginParams.getCompany().getCompanyCode();
        dto.setCreateUserId(reginParams.getUserModel().getUserId());
        String currentUserId = reginParams.getUserModel().getUserId();
        Page<Map<String, Object>> listPage = this.baseMapper.getListPage(page, dto, roleIds, orgCode, currentUserId);
        listPage.getRecords().forEach(item -> {
            if (item.containsKey("auditStatus") && Objects.nonNull(item.get("auditStatus"))) {
                item.put("auditStatusDesc", item.get("auditStatus").toString());
            }
            if (item.containsKey("cancelType") && Objects.nonNull(item.get("cancelType"))) {
                item.put("cancelTypeDesc", CancelTypeEnum.getNameByType(item.get("cancelType").toString()));
            }
        });
        return listPage;
    }

    private void convertField(JgScrapCancelDto model) {
        // 处理图片
        if (!ValidationUtil.isEmpty(model.getCancelCertificateList())) {
            model.setCancelCertificate(JSON.toJSONString(model.getCancelCertificateList()));
        }
        String receiveOrgId = model.getReceiveOrgCode();
        if (!ObjectUtils.isEmpty(receiveOrgId)) {
            String[] receiveOrgIdList = receiveOrgId.split("_");
            if (receiveOrgIdList.length > 1) {
                model.setReceiveOrgCode(receiveOrgIdList[0]);
                model.setReceiveCompanyCode(receiveOrgIdList[0]);
                model.setReceiveOrgName(receiveOrgIdList[1]);
            }
        }
    }

    /**
     * 获取登录用户信息
     *
     * @return
     */
    protected ReginParams getSelectedOrgInfo() {
        return JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
    }

    @Transactional(rollbackFor = Exception.class)
    public List<JgScrapCancel> saveList(String submitType, Map<String, Object> mapParams) {
        return Collections.singletonList(this.save(submitType, mapParams));
    }

    @SuppressWarnings({"Duplicates", "rawtypes"})
    @Transactional(rollbackFor = Exception.class)
    public JgScrapCancel save(String submitType, Map<String, Object> mapParams) {
        ReginParams reginParams = this.getSelectedOrgInfo();
        Map<String, Object> noticeParams = (Map) mapParams.get(PAGE_KEY);
        String equipId = String.valueOf(noticeParams.get("record"));
        String[] receiveOrg = String.valueOf(noticeParams.get("receiveOrgCreditCode")).split("_");
        noticeParams.remove("record");
        String[] taskName = new String[]{"流程结束"};
        JgScrapCancelDto model = JSON.parseObject(JSON.toJSONString(noticeParams), JgScrapCancelDto.class);
        model.setSEQUENCE_NBR(equipId);
        model.setReceiveOrgCode(receiveOrg[0]);
        model.setReceiveCompanyCode(receiveOrg[0]);
        model.setReceiveOrgName(receiveOrg[1]);
        // 字段转换
        convertField(model);
        // 获取告知单号
        ResponseModel<List<String>> listResponseModel = tzsServiceFeignClient.applicationFormCode(ApplicationFormTypeEnum.getCode.get(String.valueOf(noticeParams.get("businessCode"))), 1);
        if (!ObjectUtils.isEmpty(listResponseModel) && listResponseModel.getStatus() != HttpStatus.OK.value()) {
            log.error(" 获取告知单号失败");
            throw new RuntimeException();
        }
        HashMap<String, Object> deviceMap = new HashMap<>();
        deviceMap.put("SEQUENCE_NBR", model.getSEQUENCE_NBR());

        String instanceId = "";
        String nextTaskId = "";
        String nextUserIds = "";
        List<ProcessTaskDTO> processTaskDTOS;
        List<String> roleListNext = new ArrayList<>();
        List<String> roleListAll = new ArrayList<>();
        List<String> applyNoList = listResponseModel.getResult();
        if (CollectionUtils.isEmpty(applyNoList)) {
            return null;
        }
        // 判断当前是否为提交
        List<WorkflowResultDto> workflowResultDtos = null;
        if (SUBMIT_TYPE_FLOW.equals(submitType)) {
            // 发起流程
            ActWorkflowBatchDTO actWorkflowBatchDTO = new ActWorkflowBatchDTO();
            List<ActWorkflowStartDTO> list = new ArrayList<>();

            ActWorkflowStartDTO dto = new ActWorkflowStartDTO();
            dto.setProcessDefinitionKey("scrapCancelNew");
            dto.setBusinessKey(applyNoList.get(0));
            dto.setCompleteFirstTask(Boolean.TRUE);
            // 下一节点执行人单位（下节点接收机构code）
            dto.setNextExecuteUserCompanyCode(model.getReceiveCompanyCode());
            list.add(dto);

            actWorkflowBatchDTO.setProcess(list);
            processTaskDTOS = cmWorkflowService.startBatch(actWorkflowBatchDTO);
            this.buildRoleList(processTaskDTOS, roleListNext, roleListAll);
            instanceId = processTaskDTOS.get(0).getProcessInstance().getId();
            nextTaskId = processTaskDTOS.get(0).getNextTask().get(0).getId();
            taskName[0] = processTaskDTOS.get(0).getNextTask().get(0).getName();
            workflowResultDtos = commonService.buildWorkFlowInfo(processTaskDTOS);
            nextUserIds = workflowResultDtos.get(0).getNextExecutorUserIds();
            this.buildRoleList(processTaskDTOS, roleListNext, roleListAll);
        }

        JgScrapCancelEq jgRelationEquip = new JgScrapCancelEq();
        JgScrapCancel jgScrapCancel = new JgScrapCancel();
        BeanUtils.copyProperties(model, jgScrapCancel);
        String applyNo = applyNoList.get(0);
        LambdaQueryWrapper<OtherInfo> otherLambda = new QueryWrapper<OtherInfo>().lambda();
        otherLambda.eq(OtherInfo::getRecord, deviceMap.get("SEQUENCE_NBR"));
        OtherInfo otherInfo = otherInfoMapper.selectOne(otherLambda);
        if (!ObjectUtils.isEmpty(otherInfo)) {
            String supervisoryCode = otherInfo.getSupervisoryCode();
            jgScrapCancel.setSupervisoryCode(supervisoryCode);
        }
        jgScrapCancel.setApplyNo(applyNo);
        jgScrapCancel.setCreateDate(new Date());
        jgScrapCancel.setNextExecuteIds(String.join(",", roleListNext));
        jgScrapCancel.setInstanceStatus(String.join(",", roleListAll));
        jgScrapCancel.setPromoter(reginParams.getUserModel().getUserId());
        jgScrapCancel.setNextTaskId(Objects.isNull(workflowResultDtos) ? null : workflowResultDtos.get(0).getNextTaskId());
        jgRelationEquip.setEquId((String) deviceMap.get("SEQUENCE_NBR"));
        jgRelationEquip.setEquipTransferId(applyNo);
        if (!StringUtils.isEmpty(instanceId)) {
            jgScrapCancel.setInstanceId(instanceId);
            jgScrapCancel.setNextTaskId(nextTaskId);
            jgScrapCancel.setNextExecuteUserIds(nextUserIds);
            jgScrapCancel.setAuditStatus(String.valueOf(WorkFlowStatusEnum.CANCEL_RECEIVE.getPass()));
        } else {
            jgScrapCancel.setAuditStatus(String.valueOf(WorkFlowStatusEnum.CANCEL_SUBMIT.getPass()));
        }
        jgScrapCancel.setUseUnitCode(reginParams.getCompany().getCompanyCode());
        jgScrapCancel.setUseUnitName(reginParams.getCompany().getCompanyName());
        jgScrapCancel.setCreateUserId(RequestContext.getExeUserId());
        this.save(jgScrapCancel);
        // 新增代办
        this.createTaskModel(jgScrapCancel, taskName[0], submitType, nextUserIds);
        jgRelationEquip.setEquipTransferId(String.valueOf(jgScrapCancel.getSequenceNbr()));
        jgScrapCancelEqService.save(jgRelationEquip);
        String equListName = EquipmentClassifityEnum.getNameByCode(jgScrapCancel.getEquList());
        jgScrapCancel.setEquListDesc(equListName);
        jgScrapCancel.setCancelTypeDesc(getRegistrationClass(jgScrapCancel.getCancelType()));

        commonService.saveExecuteFlowData2Redis(instanceId, buildInstanceRuntimeData(jgScrapCancel));
        save2HisData(noticeParams, equipId, jgRelationEquip, jgScrapCancel);
        return jgScrapCancel;
    }

    private void save2HisData(Map<String, Object> noticeParams, String equipId, JgScrapCancelEq jgRelationEquip, JgScrapCancel jgScrapCancel) {
        noticeParams.put("record", equipId);
        commonService.saveOrUpdateHistory(jgScrapCancel.getCancelTypeDesc(), new JSONObject(noticeParams), jgRelationEquip.getEquId(), jgScrapCancel.getSequenceNbr().toString());
    }

    private void createTaskModel(JgScrapCancel scrapCancel, String taskName, String submitType, String nextUserIds) {
        ReginParams reginParams = this.getSelectedOrgInfo();
        TaskModelDto taskModelDto = new TaskModelDto();
        if ("1".equals(submitType)) {
            taskModelDto.setFlowCreateDate(scrapCancel.getCreateDate());
            taskModelDto.setTaskName(taskName);
            taskModelDto.setTaskCode(scrapCancel.getApplyNo());
            taskModelDto.setTaskContent(this.buildTaskContent(scrapCancel.getEquList(), scrapCancel.getSupervisoryCode(), scrapCancel.getCancelType(), scrapCancel.getApplyNo()));
            taskModelDto.setTaskDesc("");
            taskModelDto.setTaskType(businessTypeJudgment(scrapCancel.getCancelType()).getCode());
            taskModelDto.setTaskTypeLabel(businessTypeJudgment(scrapCancel.getCancelType()).getName());
            taskModelDto.setRelationId(scrapCancel.getInstanceId());
            taskModelDto.setExecuteUserIds(nextUserIds);
            FlowStatusEnum flowStatusEnum = this.getTaskStatus(submitType);
            taskModelDto.setTaskStatus(flowStatusEnum.getCode());
            taskModelDto.setTaskStatusLabel(flowStatusEnum.getName());
            taskModelDto.setFlowStatus(this.getTaskStatusByName(scrapCancel.getAuditStatus()));
            taskModelDto.setFlowStatusLabel(scrapCancel.getAuditStatus());
            taskModelDto.setStartUserId(scrapCancel.getCreateUserId());
            taskModelDto.setFlowCode(scrapCancel.getNextTaskId());
            taskModelDto.setStartUser(reginParams.getUserModel().getRealName());
            taskModelDto.setStartUserCompanyName(scrapCancel.getUseUnitName());
            taskModelDto.setNextExecuteUser(scrapCancel.getNextExecuteIds());
            taskModelDto.setStartDate(scrapCancel.getCreateDate() == null ? new Date() : scrapCancel.getCreateDate());
            TaskMessageDto taskMessageDto = new TaskMessageDto();
            BeanUtils.copyProperties(scrapCancel, taskMessageDto);
            taskModelDto.setModel(taskMessageDto);
        } else {
            TaskMessageDto taskMessageDto = new TaskMessageDto();
            BeanUtils.copyProperties(scrapCancel, taskMessageDto);
            taskModelDto.setModel(taskMessageDto);
            taskModelDto.setTaskContent(this.buildTaskContent(scrapCancel.getEquList(), scrapCancel.getSupervisoryCode(), scrapCancel.getCancelType(), scrapCancel.getApplyNo()));
            taskModelDto.setTaskCode(scrapCancel.getApplyNo());
            taskModelDto.setTaskType(businessTypeJudgment(scrapCancel.getCancelType()).getCode());
            taskModelDto.setNextExecuteUser(scrapCancel.getNextExecuteIds());
            taskModelDto.setRelationId(taskMessageDto.getSequenceNbr() + "");
        }
        commonService.buildTaskModel(Collections.singletonList(taskModelDto));
    }

    private void buildRoleList(List<ProcessTaskDTO> processTasks, List<String> roleListNext, List<String> roleListAll) {
        processTasks.forEach(p -> {
            p.getNextCandidateGroups().values().forEach(e -> {
                roleListNext.addAll(e);
                roleListAll.addAll(e);
            });
            roleListAll.addAll(p.getCandidateGroups());
        });
    }

    /**
     * 摘要构建
     *
     * @return 摘要
     */
    private String buildTaskContent(String equList, String supervisoryCode, String cancelType, String applyNo) {
        //    来自电梯【X3100-123456】【移装注销】的业务办理【申请单号：ABCD0000001】
        String type = "1".equals(cancelType) ? "报废注销" : "移装注销";
        String equListName = EquipmentClassifityEnum.getNameByCode(equList);
        return String.format(template, equListName, Objects.isNull(supervisoryCode) ? "无" : supervisoryCode, type, applyNo);
    }

    public void deleteBatch(List<Long> ids) {
        if (!ids.isEmpty()) {
            for (Long id : ids) {
                LambdaQueryWrapper<JgScrapCancel> lambda = new QueryWrapper<JgScrapCancel>().lambda();
                lambda.eq(JgScrapCancel::getSequenceNbr, id);
                JgScrapCancel jgScrapCancel = this.baseMapper.selectOne(lambda);
                // 删除代办消息
                commonService.deleteTaskModel(String.valueOf(jgScrapCancel.getSequenceNbr()));
                // 更新jgScrapCancel数据
                jgScrapCancel.setIsDelete(true);
                this.updateById(jgScrapCancel);
            }
        }
    }

    public JgScrapCancelDto updateInfo(String submitType, JgScrapCancelDto jgScrapCancelDto, String op, JSONObject pageData) {

        if (Objects.isNull(jgScrapCancelDto) || StringUtils.isEmpty(submitType)) {
            throw new IllegalArgumentException("参数不能为空");
        }
        // 字段转换
        this.convertField(jgScrapCancelDto);
        List<String> roleListNext = new ArrayList<>();
        List<String> roleListAll = new ArrayList<>();
        if (SUBMIT_TYPE_FLOW.equals(submitType)) {
            // 更新并提交
            // 发起流程
            if (!StringUtils.hasText(jgScrapCancelDto.getInstanceId())) {
                // 未进流程直接发起并执行

                List<ProcessTaskDTO> processTasks;
                ActWorkflowBatchDTO actWorkflowBatchDTO = new ActWorkflowBatchDTO();
                List<ActWorkflowStartDTO> list = new ArrayList<>();
                ActWorkflowStartDTO dto = new ActWorkflowStartDTO();
                dto.setProcessDefinitionKey("scrapCancelNew");
                dto.setBusinessKey(jgScrapCancelDto.getApplyNo());
                dto.setCompleteFirstTask(true);
                dto.setNextExecuteUserCompanyCode(jgScrapCancelDto.getReceiveCompanyCode());
                list.add(dto);
                actWorkflowBatchDTO.setProcess(list);
                processTasks = cmWorkflowService.startBatch(actWorkflowBatchDTO);
                String instanceId = processTasks.get(0).getProcessInstance().getId();
                String nextTaskId = processTasks.get(0).getNextTask().get(0).getId();
                String taskName = processTasks.get(0).getNextTask().get(0).getName();
                this.buildRoleList(processTasks, roleListNext, roleListAll);
                List<WorkflowResultDto> workflowResultDtos = commonService.buildWorkFlowInfo(processTasks);
                String nextUserIds = workflowResultDtos.get(0).getNextExecutorUserIds();
                jgScrapCancelDto.setInstanceStatus(String.join(",", roleListAll));
                jgScrapCancelDto.setInstanceId(instanceId);
                jgScrapCancelDto.setNextExecuteIds(String.join(",", roleListNext));
                jgScrapCancelDto.setNextTaskId(nextTaskId);
                jgScrapCancelDto.setNextExecuteUserIds(nextUserIds);
                jgScrapCancelDto.setAuditStatus(WorkFlowStatusEnum.CANCEL_RECEIVE.getPass());
                // 创建待办
                JgScrapCancel bean = new JgScrapCancel();
                BeanUtil.copyProperties(jgScrapCancelDto, bean);
                commonService.deleteTaskModel(String.valueOf(jgScrapCancelDto.getSequenceNbr()));
                createTaskModel(bean, taskName, "1", nextUserIds);
            } else {
                // 已经在流程中，执行一步
                ProcessTaskDTO processTaskDTO = submit(jgScrapCancelDto);
                String nextTaskId = processTaskDTO.getNextTask().get(0).getId();
                String taskName = processTaskDTO.getNextTask().get(0).getName();
                this.buildRoleList(Collections.singletonList(processTaskDTO), roleListNext, roleListAll);
                List<WorkflowResultDto> workflowResultDtos = commonService.buildWorkFlowInfo(Collections.singletonList(processTaskDTO));
                String nextUserIds = workflowResultDtos.get(0).getNextExecutorUserIds();
                // 查询下节点任务
                if (!ObjectUtils.isEmpty(jgScrapCancelDto.getInstanceStatus())) {
                    jgScrapCancelDto.setInstanceStatus(jgScrapCancelDto.getInstanceStatus() + "," + String.join("", roleListNext));
                } else {
                    jgScrapCancelDto.setInstanceStatus(String.join(",", roleListAll));
                }
                jgScrapCancelDto.setPromoter(RequestContext.getExeUserId());
                jgScrapCancelDto.setNextExecuteIds(String.join(",", roleListNext));
                jgScrapCancelDto.setAuditStatus(String.valueOf(WorkFlowStatusEnum.CANCEL_RECEIVE.getPass()));
                jgScrapCancelDto.setNextTaskId(nextTaskId);
                // 更新下一步可执行人
                jgScrapCancelDto.setNextExecuteUserIds(nextUserIds);
                JgScrapCancel jgScrapCancel = new JgScrapCancel();
                BeanUtils.copyProperties(jgScrapCancelDto, jgScrapCancel);
                updateTaskModel(jgScrapCancelDto, "0");
                createTaskModel(jgScrapCancel, taskName, "1", nextUserIds);
            }
            JgScrapCancel cancel = new JgScrapCancel();
            BeanUtils.copyProperties(jgScrapCancelDto, cancel);
            this.updateById(cancel);
            JgScrapCancel jgScrapCancel = new JgScrapCancel();
            BeanUtils.copyProperties(jgScrapCancelDto, jgScrapCancel, "useUnitName", "useUnitName");
            LambdaUpdateWrapper<JgScrapCancelEq> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(JgScrapCancelEq::getEquipTransferId, jgScrapCancel.getSequenceNbr());
            JgScrapCancelEq jgScrapCancelEq = new JgScrapCancelEq();
            jgScrapCancelEq.setEquId(jgScrapCancelDto.getRecord());
            jgScrapCancelEqMapper.update(jgScrapCancelEq, updateWrapper);

            commonService.saveExecuteFlowData2Redis(jgScrapCancel.getInstanceId(), buildInstanceRuntimeData(jgScrapCancel));
        } else {
            if (!ObjectUtils.isEmpty(jgScrapCancelDto.getSEQUENCE_NBR()) && !"null".equals(jgScrapCancelDto.getSEQUENCE_NBR())) {
                LambdaQueryWrapper<OtherInfo> otherLambda = new QueryWrapper<OtherInfo>().lambda();
                otherLambda.eq(OtherInfo::getRecord, jgScrapCancelDto.getSEQUENCE_NBR());
                OtherInfo otherInfo = otherInfoMapper.selectOne(otherLambda);
                String supervisoryCode = otherInfo.getSupervisoryCode();
                jgScrapCancelDto.setSupervisoryCode(supervisoryCode);
            }
            // 更新操作
            JgScrapCancel bean = new JgScrapCancel();
            BeanUtils.copyProperties(jgScrapCancelDto, bean);
            bean.setCancelCertificate(JSON.toJSONString(jgScrapCancelDto.getCancelCertificateList()));
            this.updateById(bean);
            LambdaUpdateWrapper<JgScrapCancelEq> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(JgScrapCancelEq::getEquipTransferId, jgScrapCancelDto.getSequenceNbr());
            JgScrapCancelEq jgScrapCancelEq = new JgScrapCancelEq();
            jgScrapCancelEq.setEquId(jgScrapCancelDto.getRecord());
            jgScrapCancelEqMapper.update(jgScrapCancelEq, updateWrapper);
        }
        commonService.saveOrUpdateHistory(getRegistrationClass(jgScrapCancelDto.getCancelType()), pageData, jgScrapCancelDto.getRecord(), jgScrapCancelDto.getSequenceNbr().toString());
        return jgScrapCancelDto;
    }

    private String getRegistrationClass (String cancelType){
        return "1".equals(cancelType) ? "报废注销" : "移装注销";
    }

    private void executeOneStep(JgScrapCancelDto jgScrapCancelDto, String taskName, String nextUserIds, String operate) {
        // 先更新之前的待办
        TaskV2Model taskV2Model = updateTaskModel(jgScrapCancelDto, operate);
        taskV2Model.setTaskDesc("");
        taskV2Model.setTaskContent(this.buildTaskContent(jgScrapCancelDto.getEquList(), jgScrapCancelDto.getSupervisoryCode(), jgScrapCancelDto.getCancelType(), jgScrapCancelDto.getApplyNo()));
        taskV2Model.setTaskName(taskName);
        taskV2Model.setTaskCode(jgScrapCancelDto.getApplyNo());
        taskV2Model.setRelationId(jgScrapCancelDto.getInstanceId());
        FlowStatusEnum flowStatusEnum = this.getTaskStatus(operate);
        taskV2Model.setTaskStatus(flowStatusEnum.getCode());
        taskV2Model.setTaskStatusLabel(flowStatusEnum.getName());
        taskV2Model.setFlowStatus(this.getTaskStatusByName(jgScrapCancelDto.getAuditStatus()));
        taskV2Model.setFlowStatusLabel(jgScrapCancelDto.getAuditStatus());
        taskV2Model.setTaskType(businessTypeJudgment(jgScrapCancelDto.getCancelType()).getCode());
        taskV2Model.setStartUser(jgScrapCancelDto.getRecUserName());
        taskV2Model.setTaskTypeLabel(businessTypeJudgment(jgScrapCancelDto.getCancelType()).getName());
        taskV2Model.setStartDate(jgScrapCancelDto.getCreateDate());
        taskV2Model.setStartUserId(jgScrapCancelDto.getCreateUserId());
        taskV2Model.setStartUserCompanyName(jgScrapCancelDto.getUseUnitName());
        taskV2Model.setExecuteUserIds(nextUserIds);
        taskV2Model.setFlowCode(jgScrapCancelDto.getNextTaskId());
        TaskModelDto modelDto = new TaskModelDto();
        BeanUtil.copyProperties(taskV2Model, modelDto);
        modelDto.setNextExecuteUser(jgScrapCancelDto.getNextExecuteIds());
        TaskMessageDto taskMessageDto = new TaskMessageDto();
        BeanUtils.copyProperties(jgScrapCancelDto, taskMessageDto);
        modelDto.setModel(taskMessageDto);
        modelDto.setPageType(this.getPageTypeForReject(operate, jgScrapCancelDto.getAuditStatus()));
        commonService.buildTaskModel(Collections.singletonList(modelDto));
    }

    private Integer getTaskStatusByName(String auditStatus) {
        return commonService.getDictionaryCodeByName(auditStatus);
    }

    private String getPageTypeForReject(String operate, String auditStatus) {
        // 驳回
        if ("1".equals(operate)) {
            // 且驳回到的节点为使用单位提交 则可编辑
            if (WorkFlowStatusEnum.CANCEL_SUBMIT.getPass().equals(auditStatus) || WorkFlowStatusEnum.CANCEL_SUBMIT.getReject().equals(auditStatus) || WorkFlowStatusEnum.CANCEL_SUBMIT.getRollBack().equals(auditStatus)) {
                return "edit";
            }
            return "look";
        }
        return "look";
    }

    private TaskV2Model updateTaskModel(JgScrapCancelDto jgScrapCancelDto, String operate) {
        Map<String, Object> params = new HashMap<>();
        FlowStatusEnum flowStatusEnum = this.getTaskStatus(operate);
        params.put("relationId", jgScrapCancelDto.getInstanceId());
        params.put("taskStatus", flowStatusEnum.getCode());
        params.put("taskStatusLabel", flowStatusEnum.getName());
        params.put("flowStatus", this.getTaskStatusByName(jgScrapCancelDto.getAuditStatus()));
        params.put("flowStatusLabel", jgScrapCancelDto.getAuditStatus());
        params.put("model", jgScrapCancelDto);
        return commonService.updateTaskModel(params);
    }

    private FlowStatusEnum getTaskStatus(String operate) {
        if ("0".equals(operate)) {
            return FlowStatusEnum.TO_BE_FINISHED;
        } else {
            return FlowStatusEnum.REJECTED;
        }
    }

    public ProcessTaskDTO submit(JgScrapCancelDto jgScrapCancelDto) {
        JgScrapCancel model = this.getById(jgScrapCancelDto.getSequenceNbr());
        // 组装信息
        String op = "提交";
        TaskResultDTO dto = new TaskResultDTO();
        dto.setResultCode("approvalStatus");
        dto.setTaskId(jgScrapCancelDto.getNextTaskId());
        HashMap<String, Object> map = new HashMap<>();
        map.put("approvalStatus", op);
        dto.setNextExecuteUserCompanyCode(model.getReceiveCompanyCode());
        dto.setVariable(map);
        return cmWorkflowService.completeOrReject(jgScrapCancelDto.getNextTaskId(), dto, op);
    }


    public Map<String, Object> queryBySequenceNbr(Long sequenceNbr) {
        Map<String, Object> resultMap = new HashMap<>();
        JgScrapCancel scrapCancel = this.baseMapper.selectById(sequenceNbr);
        Map<String, Object> beanMap = BeanUtil.beanToMap(scrapCancel, false, true);
        beanMap.put("cancelCertificateList", JSON.parse(scrapCancel.getCancelCertificate()));
        beanMap.put("otherAccessories", JSON.parse(scrapCancel.getOtherAccessories()));
        if(scrapCancel.getAuditStatus().equals(FlowStatusEnum.TO_BE_FINISHED.getName())){
            // 完成状态查询历史表
            JSONObject jsonObject = commonService.queryHistoryData(sequenceNbr);
            // 兼容老数据
            if(jsonObject == null){
                // 老数据逻辑
                fillRuntimeData(sequenceNbr, resultMap);
            } else {
                CommonServiceImpl.formatTime2StrDateForEquip(jsonObject);
                // 新数据逻辑
                resultMap.putAll(jsonObject);
            }
            resultMap.putAll(beanMap);
        } else {
            // 其他状态显示实时数据
            fillRuntimeData(sequenceNbr, resultMap);
            resultMap.putAll(beanMap);
        }
        resultMap.put("receiveOrgCode", scrapCancel.getReceiveCompanyCode() + '_' + scrapCancel.getReceiveOrgName());
        return new HashMap<String, Object>() {{
            this.put(PAGE_KEY, resultMap);
        }};
    }

    private void fillRuntimeData(Long sequenceNbr, Map<String, Object> resultMap) {
        JgScrapCancelEq jgScrapCancelEq = jgScrapCancelEqMapper.selectOne(new LambdaQueryWrapper<JgScrapCancelEq>().eq(JgScrapCancelEq::getEquipTransferId, sequenceNbr));
        if (!ObjectUtils.isEmpty(jgScrapCancelEq)) {
            Map<String, Object> map = idxBizJgRegisterInfoService.getDetailFieldCamelCaseByRecord(jgScrapCancelEq.getEquId());
            resultMap.putAll(map);
        }
    }


    @Transactional
    public void revocation(String instanceId, String nextTaskId) {
        String lockKey = CommonServiceImpl.buildJgExecuteLockKey(instanceId);
        RLock lock = redissonClient.getLock(lockKey);
        try {
            boolean isLocked = lock.tryLock(0, 180, TimeUnit.SECONDS);
            // 解决并发问题：多个人同时操作一个流程（并发执行通过、驳回、撤回）
            if (!isLocked) {
                throw new BadRequest("当前流程已经被执行！请重新打开页面查看并执行！");
            }
            // 流程执行时，状态及权限校验
            commonService.checkForRevocationFlow(nextTaskId, instanceId);

            ReginParams reginParams = this.getSelectedOrgInfo();
            LambdaQueryWrapper<JgScrapCancel> lambda = new QueryWrapper<JgScrapCancel>().lambda();
            lambda.eq(JgScrapCancel::getInstanceId, instanceId);
            JgScrapCancel jgScrapCancel = this.baseMapper.selectOne(lambda);
            ProcessTaskDTO processTaskDTO = cmWorkflowService.rollBack(instanceId);
            WorkflowResultDto workflowResultDto = commonService.buildWorkFlowInfo(Collections.singletonList(processTaskDTO)).get(0);
            if (!FlowStatusEnum.TO_BE_FINISHED.getName().equals(workflowResultDto.getNextTaskName())) {
                jgScrapCancel.setAuditStatus(Objects.requireNonNull(WorkFlowStatusEnum.getMessage(workflowResultDto.getNextTaskCode())).getRollBack());
            }
            jgScrapCancel.setNextTaskId(workflowResultDto.getNextTaskId());
            List<WorkflowResultDto> workflowResultDtos = commonService.buildWorkFlowInfo(Collections.singletonList(processTaskDTO));
            // 更新下一步可执行人
            String nextUserIds = workflowResultDtos.get(0).getNextExecutorUserIds();
            jgScrapCancel.setNextExecuteUserIds(nextUserIds);
            jgScrapCancel.setPromoter(reginParams.getUserModel().getUserId());
            jgScrapCancel.setNextExecuteIds(workflowResultDto.getNextExecutorRoleIds());
            this.updateById(jgScrapCancel);

            // 删除待办
            JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(jgScrapCancel));
            jsonObject.put("nextTaskId", jgScrapCancel.getNextTaskId());
            jsonObject.put("nextExecuteUser", jgScrapCancel.getNextExecuteIds());
            jsonObject.put("taskType", businessTypeJudgment(jgScrapCancel.getCancelType()).getCode());
            jsonObject.put("flowStatus", this.getTaskCodeByName(jgScrapCancel.getAuditStatus()));
            jsonObject.put("flowStatusLabel", jgScrapCancel.getAuditStatus());
            // 判断撤回后当前的节点，如果当前节点为提交节点则页面可编辑
            jsonObject.put("pageType", this.getPageTypeByCurrentNode(jgScrapCancel.getAuditStatus()));
            commonService.rollbackTask(instanceId, jsonObject);

            // redis流程实时数据更新
            commonService.saveExecuteFlowData2Redis(instanceId, this.buildInstanceRuntimeData(jgScrapCancel));
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    private Integer getTaskCodeByName(String auditStatus) {
        return commonService.getDictionaryCodeByName(auditStatus);
    }

    private String getPageTypeByCurrentNode(String auditStatus) {
        if (WorkFlowStatusEnum.CANCEL_SUBMIT.getPass().equals(auditStatus) || WorkFlowStatusEnum.CANCEL_SUBMIT.getReject().equals(auditStatus) || WorkFlowStatusEnum.CANCEL_SUBMIT.getRollBack().equals(auditStatus)) {
            return "edit";
        } else {
            return "look";
        }
    }

    @Transactional
    public void flowExecute(String equList, Long id, String instanceId, String operate, String comment, String nextTaskId) {
        String lockKey = CommonServiceImpl.buildJgExecuteLockKey(instanceId);
        RLock lock = redissonClient.getLock(lockKey);
        try {
            boolean isLocked = lock.tryLock(0, 180, TimeUnit.SECONDS);
            // 解决并发问题：多个人同时操作一个流程（并发执行通过、驳回、撤回）
            if (!isLocked) {
                throw new BadRequest("当前流程已经被执行！请重新打开页面查看并执行！");
            }
            // 流程执行时，状态及权限校验
            commonService.checkForExecuteFlow(nextTaskId, instanceId);

            JgScrapCancel jgScrapCancel = this.getBaseMapper().selectById(id);
            String taskId = jgScrapCancel.getNextTaskId();
            // 组装信息
            TaskResultDTO dto = new TaskResultDTO();
            dto.setResultCode("approvalStatus");
            dto.setTaskId(taskId);
            dto.setComment(comment);
            HashMap<String, Object> map = new HashMap<>();
            map.put("approvalStatus", operate);
            if (!ObjectUtils.isEmpty(jgScrapCancel.getInstanceStatus()) && (jgScrapCancel.getInstanceStatus().equals(WorkFlowStatusEnum.CANCEL_SUBMIT.getReject()) || jgScrapCancel.getInstanceStatus().equals(WorkFlowStatusEnum.CANCEL_SUBMIT.getRollBack()))) {
                map.put("approvalStatus", "提交");
            }
            dto.setVariable(map);
            // 下一节点执行人单位（下节点接收机构code）
            dto.setNextExecuteUserCompanyCode(this.getNextUserOrgCode(operate, jgScrapCancel));
            // 执行流程
            ProcessTaskDTO processTaskDTO = cmWorkflowService.completeOrReject(taskId, dto, operate);
            // 更新下一步执行人、创建待办
            updateExecuteIds(equList, instanceId, id, operate, processTaskDTO);

            // redis流程实时数据更新
            commonService.saveExecuteFlowData2Redis(instanceId, this.buildInstanceRuntimeData(jgScrapCancel));
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    public InstanceRuntimeData buildInstanceRuntimeData(JgScrapCancel jgScrapCancel) {
        return InstanceRuntimeData.builder()
                .nextExecuteUserIds(jgScrapCancel.getNextExecuteUserIds())
                .promoter(jgScrapCancel.getPromoter())
                .nextTaskId(jgScrapCancel.getNextTaskId())
                .build();
    }

    public void updateExecuteIds(String equList, String instanceId, Long sequenceNbr, String operate, ProcessTaskDTO processTaskDTO) {
        List<String> roleListNext = new ArrayList<>();
        List<String> roleListAll = new ArrayList<>();
        String taskCode = FlowStatusEnum.TO_BE_FINISHED.getName();
        String taskName = "";
        String nextTaskId = "";
        JgScrapCancel jgScrapCancel = this.getBaseMapper().selectById(sequenceNbr);
        jgScrapCancel.setEquList(equList);
        if (processTaskDTO != null && processTaskDTO.getNextTask() != null && !processTaskDTO.getNextTask().isEmpty()) {
            taskCode = processTaskDTO.getNextTask().get(0).getKey();
            taskName = processTaskDTO.getNextTask().get(0).getName();
            nextTaskId = processTaskDTO.getNextTask().get(0).getId();
        }
        if (!FlowStatusEnum.TO_BE_FINISHED.getName().equals(taskCode)) {
            this.buildRoleList(Collections.singletonList(processTaskDTO), roleListNext, roleListAll);
            List<WorkflowResultDto> workflowResultDtos = commonService.buildWorkFlowInfo(Collections.singletonList(processTaskDTO));
            String nextUserIds = workflowResultDtos.get(0).getNextExecutorUserIds();
            jgScrapCancel.setNextExecuteIds(String.join(",", roleListNext));
            jgScrapCancel.setPromoter(RequestContext.getExeUserId());
            jgScrapCancel.setInstanceId(instanceId);
            jgScrapCancel.setNextTaskId(nextTaskId);
            // 更新下一步可执行人
            jgScrapCancel.setNextExecuteUserIds(nextUserIds);
            if (!ObjectUtils.isEmpty(jgScrapCancel.getInstanceStatus())) {
                jgScrapCancel.setInstanceStatus(jgScrapCancel.getInstanceStatus() + "," + String.join(",", roleListNext));
            } else {
                jgScrapCancel.setInstanceStatus(String.join(",", roleListNext));
            }
            if ("0".equals(operate)) {
                // 通过操作
                jgScrapCancel.setAuditStatus(Objects.requireNonNull(WorkFlowStatusEnum.getMessage(taskCode)).getPass());
            } else {
                // 驳回操作
                jgScrapCancel.setAuditStatus(Objects.requireNonNull(WorkFlowStatusEnum.getMessage(taskCode)).getReject());
                jgScrapCancel.setPromoter(null);
            }
            JgScrapCancelDto scrapCancelDto = new JgScrapCancelDto();
            BeanUtils.copyProperties(jgScrapCancel, scrapCancelDto);
            // 更新上一步待办、创建待办
            executeOneStep(scrapCancelDto, taskName, nextUserIds, operate);
        } else {
            // 完成时 下一步骤可执行人清空
            jgScrapCancel.setNextExecuteUserIds("");
            jgScrapCancel.setNextTaskId(nextTaskId);
            // 修改业务信息
            updateInfoOther(jgScrapCancel);
            JgScrapCancelDto scrapCancelDto = new JgScrapCancelDto();
            BeanUtils.copyProperties(jgScrapCancel, scrapCancelDto);
            // 更新代办
            updateTaskModel(scrapCancelDto, operate);
        }
        this.getBaseMapper().updateById(jgScrapCancel);
    }

    public void updateInfoOther(JgScrapCancel jgScrapCancel) {
        LambdaQueryWrapper<JgScrapCancelEq> lambdaEq = new QueryWrapper<JgScrapCancelEq>().lambda();
        lambdaEq.eq(JgScrapCancelEq::getEquipTransferId, jgScrapCancel.getSequenceNbr());
        JgScrapCancelEq jgScrapCancelEq = jgScrapCancelEqMapper.selectOne(lambdaEq);

//        ResponseModel<String> responseModel = tzsServiceFeignClient.useRegistrationCode(idxBizJgOtherInfoMapper.getSupervisoryCodeByEquipmentCode(jgScrapCancelEq.getEquId()));
//        String newUseRegistrationCertificateNumber = responseModel.getResult().split("-")[0];

        Map<String, Map<String, Object>> resultMap = new HashMap<>();
        Map<String, Object> map1 = new HashMap<>();
//        map1.put("USE_ORG_CODE", newUseRegistrationCertificateNumber);
        if (CancelTypeEnum.SCRAPPED.getCode().equals(jgScrapCancel.getCancelType())) {
            IdxBizJgUseInfo idxBizJgUseInfo = new IdxBizJgUseInfo();
            idxBizJgUseInfo.setEquState(String.valueOf(EquimentEnum.BAOFEI.getCode()));
            LambdaQueryWrapper<IdxBizJgUseInfo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(IdxBizJgUseInfo::getRecord, jgScrapCancelEq.getEquId());
            idxBizJgUseInfoMapper.update(idxBizJgUseInfo, wrapper);
            map1.put("EQU_STATE", String.valueOf(EquimentEnum.BAOFEI.getCode()));
        } else {
            SuperviseInfo superviseInfo = new SuperviseInfo();
            superviseInfo.setOrgBranchCode("");
            superviseInfo.setOrgBranchName("");
            LambdaQueryWrapper<SuperviseInfo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SuperviseInfo::getRecord, jgScrapCancelEq.getEquId());
            superviseInfoMapper.update(superviseInfo, wrapper);
            map1.put("ORG_BRANCH_CODE", "");
            map1.put("ORG_BRANCH_NAME", "");
        }
        resultMap.put(jgScrapCancelEq.getEquId(), map1);
        try {
            tzsServiceFeignClient.commonUpdateEsDataByIds(resultMap);
        } catch (Exception e) {
            e.printStackTrace();
        }
        jgScrapCancel.setAuditStatus(FlowStatusEnum.TO_BE_FINISHED.getName());
        jgScrapCancel.setAuditPassDate(new Date());
    }

    public String getNextUserOrgCode(String operate, JgScrapCancel jgScrapCancel) {
        String code = null;
        if ("0".equals(operate)) {
            code = jgScrapCancel.getReceiveCompanyCode();
        } else {
            // 驳回
            if (WorkFlowStatusEnum.CANCEL_RECEIVE.getPass().equals(jgScrapCancel.getAuditStatus()) ||
                    WorkFlowStatusEnum.CANCEL_RECEIVE.getReject().equals(jgScrapCancel.getAuditStatus()) ||
                    WorkFlowStatusEnum.CANCEL_RECEIVE.getRollBack().equals(jgScrapCancel.getAuditStatus())) {
                code = jgScrapCancel.getUseUnitCode();
            }
        }
        return code == null ? jgScrapCancel.getReceiveCompanyCode() : code;
    }

}