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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
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.google.common.collect.Lists;
import com.yeejoin.amos.boot.biz.common.annotation.FieldMapping;
import com.yeejoin.amos.boot.biz.common.annotation.ResultFieldMapping;
import com.yeejoin.amos.boot.biz.common.bo.CompanyBo;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.enums.TcmUnitTypeEnum;
import com.yeejoin.amos.boot.biz.common.utils.RedisKey;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.boot.module.common.api.service.ICompensateFlowDataOfRedis;
import com.yeejoin.amos.boot.module.common.biz.refresh.DataRefreshEvent;
import com.yeejoin.amos.boot.module.jg.api.dto.*;
import com.yeejoin.amos.boot.module.jg.api.entity.*;
import com.yeejoin.amos.boot.module.jg.api.enums.BusinessTypeEnum;
import com.yeejoin.amos.boot.module.jg.api.enums.CompanyTypeEnum;
import com.yeejoin.amos.boot.module.jg.api.enums.VehicleApanageEnum;
import com.yeejoin.amos.boot.module.jg.api.enums.WorkFlowStatusEnum;
import com.yeejoin.amos.boot.module.jg.api.mapper.JgChangeVehicleRegistrationUnitMapper;
import com.yeejoin.amos.boot.module.jg.api.service.IJgChangeVehicleRegistrationUnitService;
import com.yeejoin.amos.boot.module.jg.api.vo.SortVo;
import com.yeejoin.amos.boot.module.jg.biz.config.LocalBadRequest;
import com.yeejoin.amos.boot.module.jg.biz.context.EquipUsedCheckStrategyContext;
import com.yeejoin.amos.boot.module.jg.biz.context.FlowingEquipRedisContext;
import com.yeejoin.amos.boot.module.jg.biz.edit.permission.FillingEditPermForCurrentUser;
import com.yeejoin.amos.boot.module.jg.biz.event.publisher.EventPublisher;
import com.yeejoin.amos.boot.module.jg.biz.feign.TzsServiceFeignClient;
import com.yeejoin.amos.boot.module.jg.biz.utils.CodeUtil;
import com.yeejoin.amos.boot.module.ymt.api.entity.*;
import com.yeejoin.amos.boot.module.ymt.api.enums.ApplicationFormTypeEnum;
import com.yeejoin.amos.boot.module.ymt.api.enums.EquipmentEnum;
import com.yeejoin.amos.boot.module.ymt.api.enums.FlowStatusEnum;
import com.yeejoin.amos.boot.module.ymt.api.mapper.IdxBizJgOtherInfoMapper;
import com.yeejoin.amos.boot.module.ymt.api.mapper.IdxBizJgUseInfoMapper;
import com.yeejoin.amos.boot.module.ymt.api.mapper.TzBaseEnterpriseInfoMapper;
import com.yeejoin.amos.component.feign.model.FeignClientResult;
import com.yeejoin.amos.component.feign.utils.FeignUtil;
import com.yeejoin.amos.feign.privilege.Privilege;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.amos.feign.privilege.model.CompanyModel;
import com.yeejoin.amos.feign.systemctl.Systemctl;
import com.yeejoin.amos.feign.systemctl.model.DictionarieValueModel;
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 io.seata.spring.annotation.GlobalTransactional;
import org.apache.commons.lang3.StringUtils;
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.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.rdbms.orm.entity.BaseEntity;
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.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.yeejoin.amos.boot.module.jg.api.enums.VehicleApanageEnum.XIAN_YANG;
import static com.yeejoin.amos.boot.module.jg.api.enums.VehicleApanageEnum.XI_XIAN;
import static com.yeejoin.amos.boot.module.jg.biz.service.impl.JgChangeRegistrationNameServiceImpl.DB_BATCH_SIZE;

/**
 * 单位变更登记服务实现类
 *
 * @author system_generator
 * @date 2024-07-10
 */
@Service
public class JgChangeVehicleRegistrationUnitServiceImpl extends BaseService<JgChangeVehicleRegistrationUnitDto, JgChangeVehicleRegistrationUnit, JgChangeVehicleRegistrationUnitMapper> implements IJgChangeVehicleRegistrationUnitService, ICompensateFlowDataOfRedis<JgChangeVehicleRegistrationUnit> {
    private static final String SUBMIT_TYPE_FLOW = "1";
    private static final String PROCESS_DEFINITION_KEY = "vehicleGasCylinderChange";
    private final List<String> NOT_FLOWING_STATE = Arrays.asList("使用单位待提交", "一级受理已驳回", "使用单位已撤回", "已作废", "已完成");
    private static final String BUSINESS_NAME = "车用气瓶变更";
    private static final String template = "发起【车用气瓶变更登记】业务申请，【申请单号：%s】";
    @Autowired
    JgRegistrationHistoryServiceImpl jgRegistrationHistoryService;
    @Autowired
    CommonServiceImpl commonServiceImpl;
    @Autowired
    CmWorkflowServiceImpl cmWorkflowService;
    @Autowired
    RedisUtils redisUtils;
    @Autowired
    private CommonServiceImpl commonService;
    @Autowired
    TzsServiceFeignClient tzsServiceFeignClient;
    @Autowired
    private JgUseRegistrationManageServiceImpl jgUseRegistrationManageService;
    @Autowired
    private JgChangeVehicleRegistrationUnitEqServiceImpl jgChangeVehicleRegistrationUnitEqService;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private JgCertificateChangeRecordServiceImpl jgCertificateChangeRecordService;
    @Autowired
    private JgCertificateChangeRecordEqServiceImpl jgCertificateChangeRecordEqService;
    @Autowired
    private IdxBizJgRegisterInfoServiceImpl idxBizJgRegisterInfoService;
    @Autowired
    private IdxBizJgOtherInfoMapper otherInfoMapper;

    @Autowired
    private IdxBizJgUseInfoMapper jgUseInfoMapper;

    private volatile Map<String, Object> fillingMediumMap;
    @Autowired
    private IdxBizJgUseInfoServiceImpl idxBizJgUseInfoServiceImpl;

    @Autowired
    private IdxBizJgSupervisionInfoServiceImpl idxBizJgSupervisionInfoService;

    @Autowired
    private TzBaseEnterpriseInfoMapper tzBaseEnterpriseInfoMapper;

    @Autowired
    private EventPublisher eventPublisher;

    @Autowired
    private JgResumeInfoServiceImpl jgResumeInfoService;

    @Autowired
    private JgResumeInfoEqServiceImpl jgResumeInfoEqService;

    @Autowired
    private CodeUtil codeUtil;

    public void changeData(JgChangeVehicleRegistrationUnit dto, CompanyBo company) {
        if (!ObjectUtils.isEmpty(dto.getReceiveCompanyCode())) {
            // 接收单位信息
            String[] splitMaintenanceUnitCode = dto.getReceiveCompanyCode().split("_");
            dto.setReceiveCompanyCode(splitMaintenanceUnitCode[0]);
            dto.setReceiveOrgName(splitMaintenanceUnitCode[1]);
            dto.setReceiveOrgCode(splitMaintenanceUnitCode[0]);
            dto.setReceiveCompanyOrgCode(commonService.getOneCompany(dto.getReceiveCompanyCode()).getOrgCode());
        }
        if (!ObjectUtils.isEmpty(dto.getUseUnitCreditCode())) {
            // 使用单位
            String[] splitMaintenanceUnitCode = dto.getUseUnitCreditCode().split("_");
            dto.setUseUnitCreditCode(splitMaintenanceUnitCode[0]);
            dto.setUseUnitName(splitMaintenanceUnitCode[1]);
        }
        if (!ObjectUtils.isEmpty(dto.getNewUseUnitCreditCode())) {
            // 新使用单位
            if ("个人主体".equals(company.getCompanyType())) {
                dto.setNewUseUnitCreditCode(company.getCompanyCode().split("_")[1]);
                dto.setNewUseUnitName(company.getCompanyName().split("_")[1]);
            } else {
                dto.setNewUseUnitName(company.getCompanyName());
                dto.setNewUseUnitCreditCode(company.getCompanyCode());
            }
        }
        if (!ObjectUtils.isEmpty(dto.getOrgBranchCode())) {
            // 属地监管部门
            String[] splitMaintenanceUnitCode = dto.getOrgBranchCode().split("_");
            dto.setOrgBranchCode(splitMaintenanceUnitCode[0]);
            dto.setOrgBranchName(splitMaintenanceUnitCode[1]);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class, timeoutMills = 600000)
    public List<JgChangeVehicleRegistrationUnit> saveMessage(JSONObject map, ReginParams reginParams) {
        try {
            CompanyBo company = reginParams.getCompany();
            JgChangeVehicleRegistrationUnit dto = new JgChangeVehicleRegistrationUnit();
            if (!ValidationUtil.isEmpty(map.get("changeCertificateList"))) {
                dto.setChangeCertificate(JSON.toJSONString(map.get("changeCertificateList")));
            }
            if (!ObjectUtils.isEmpty(map.get("submit")) && SUBMIT_TYPE_FLOW.equals(map.get("submit").toString())) {
                if (map.containsKey("dataList")) {
                    List<Map<String, Object>> equipList = new ArrayList<>();
                    JSONArray objects = JSONObject.parseArray(JSON.toJSONString(map.get("dataList")));
                    objects.forEach(data -> {
                        Map<String, Object> equ = new HashMap<>();
                        JSONObject object = JSONObject.parseObject(data.toString());
                        equ.put("record", object.get("record"));
                        equipList.add(equ);
                    });
                    this.repeatUsedEquipCheck(equipList,
                            CompanyTypeEnum.INDIVIDUAL.getName().equals(company.getCompanyType()) ?
                                    company.getCompanyCode().split("_")[1] :
                                    company.getCompanyCode());
                }
            }
            String estateUnitSeq = MapUtil.getStr(map,"estateUnitSeq");
            Map<String, String> propertyUnitInfo = commonServiceImpl.queryTcmUnitInfoBySeq(estateUnitSeq, TcmUnitTypeEnum.CQ.getCode());
            map.put("estateUnitCreditCode", propertyUnitInfo.get("unitCode"));
            map.put("estateUnitName", propertyUnitInfo.get("unitName"));
            if (!map.containsKey("sequenceNbr")) {
                // 新增
                BeanUtil.copyProperties(map, dto);
                dto.setCreateDate(new Date());
                dto.setCreateUserId(reginParams.getUserModel().getUserId());
                dto.setCreateUserName(reginParams.getUserModel().getRealName());
                dto.setRecDate(new Date());
                dto.setRecUserId(reginParams.getUserModel().getUserId());
                changeData(dto, reginParams.getCompany());
                if (map.containsKey("useRegistrationCode") && !ObjectUtils.isEmpty(map.get("useRegistrationCode"))) {
                    dto.setUseRegistCode(map.get("useRegistrationCode").toString());
                }
                ResponseModel<List<String>> listResponseModel = tzsServiceFeignClient.applicationFormCode(ApplicationFormTypeEnum.getCode.get(String.valueOf(map.get("businessCode"))), 1);
                if (!ObjectUtils.isEmpty(listResponseModel)) {
                    dto.setApplyNo(listResponseModel.getResult().get(0));
                    dto.setApplyDate(new Date());
                }
                dto.setStatus("使用单位待提交");
                this.save(dto);
            } else {
                // 更新
                JgChangeVehicleRegistrationUnit updateDto = this.getById(Long.parseLong(map.get("sequenceNbr").toString()));
                BeanUtil.copyProperties(map, updateDto);
                if (!ValidationUtil.isEmpty(map.get("changeCertificateList"))) {
                    updateDto.setChangeCertificate(JSON.toJSONString(map.get("changeCertificateList")));
                }
                changeData(updateDto, reginParams.getCompany());
                this.updateById(updateDto);
                BeanUtil.copyProperties(updateDto, dto);
            }
            // 更新业务关联设备表
            saveChangeVehicleEq(dto, map);
            // 更新历史表信息
            saveHistory(dto, map);
            // 是否发起流程
            if (!ObjectUtils.isEmpty(map.get("submit")) && SUBMIT_TYPE_FLOW.equals(map.get("submit").toString())) {
                // 删除暂存代办
                commonServiceImpl.deleteTasksByRelationId(String.valueOf(dto.getSequenceNbr()));
                String instanceId = "";
                if (!ObjectUtils.isEmpty(map.get("instanceId"))) {
                    instanceId = map.get("instanceId").toString();
                } else {
                    // 启动并执行流程
                    ActWorkflowBatchDTO actWorkflowBatchDTO = new ActWorkflowBatchDTO();
                    ActWorkflowStartDTO workflowDto = new ActWorkflowStartDTO();
                    ArrayList<ActWorkflowStartDTO> list = new ArrayList<>();
                    workflowDto.setProcessDefinitionKey(PROCESS_DEFINITION_KEY);
                    workflowDto.setBusinessKey("1");
                    workflowDto.setCompleteFirstTask(Boolean.TRUE);
                    // 接受机构
                    workflowDto.setNextExecuteUserCompanyCode(dto.getReceiveCompanyCode());
                    list.add(workflowDto);
                    actWorkflowBatchDTO.setProcess(list);
                    List<ProcessTaskDTO> processTaskDTOS = cmWorkflowService.startBatch(actWorkflowBatchDTO);
                    List<WorkflowResultDto> resultDto = commonServiceImpl.buildWorkFlowInfo(processTaskDTOS);
                    if (!ObjectUtils.isEmpty(resultDto) && !ObjectUtils.isEmpty(resultDto.get(0))) {
                        WorkflowResultDto workflowResultDto = resultDto.get(0);
                        updateData(dto.getSequenceNbr(), "0", workflowResultDto, Boolean.TRUE);
                    }
                }
                if (!ObjectUtils.isEmpty(instanceId)) {
                    // 执行流程
                    flowExecute(dto.getSequenceNbr(), instanceId, "0", "", String.valueOf(map.get("nextTaskId")));
                }
            } else {
                if (ObjectUtils.isEmpty(map.get("instanceId"))) {
                    ArrayList<TaskModelDto> list = new ArrayList<>();
                    TaskModelDto taskDto = new TaskModelDto();
                    TaskMessageDto taskMessageDto = new TaskMessageDto();
                    BeanUtil.copyProperties(dto, taskMessageDto);
                    // 数据参数
                    taskDto.setModel(taskMessageDto);
                    // 摘要
                    taskDto.setTaskContent(String.format(template, dto.getApplyNo()));
                    // 申请单号
                    taskDto.setTaskCode(dto.getApplyNo());
                    // 业务类型
                    taskDto.setTaskType(String.valueOf(BusinessTypeEnum.JG_VEHICLE_GAS_CYLINDER_CHANGE.getCode()));
                    // 业务主键
                    taskDto.setRelationId(String.valueOf(dto.getSequenceNbr()));
                    taskDto.setNextExecuteUser("");
                    list.add(taskDto);
                    commonServiceImpl.buildTaskModel(list);
                }
            }
            return Collections.singletonList(dto);
        } catch (BadRequest | LocalBadRequest e) {
            log.error(e.getMessage(), e);
            this.rollBackForDelRedisData();
            throw e;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            this.rollBackForDelRedisData();
            throw new BadRequest("保存失败！");
        } finally {
            FlowingEquipRedisContext.clean();
        }
    }

    private void repeatUsedEquipCheck(List<Map<String, Object>> equipList, String companyCode) {
        equipList.forEach(equipMap -> EquipUsedCheckStrategyContext.getUsedStrategy(PROCESS_DEFINITION_KEY)
                .equipRepeatUsedCheck(String.valueOf(equipMap.get("record")), companyCode));
    }

    /**
     * 删除 redis校验重复引用设备的数据
     */
    private void delRepeatUseEquipData(JgChangeVehicleRegistrationUnit notice) {
        if (NOT_FLOWING_STATE.contains(notice.getStatus())) {
            LambdaQueryWrapper<JgChangeVehicleRegistrationUnitEq> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(JgChangeVehicleRegistrationUnitEq::getUnitChangeId, notice.getSequenceNbr());
            List<JgChangeVehicleRegistrationUnitEq> noticeEqList = jgChangeVehicleRegistrationUnitEqService.list(queryWrapper);
            noticeEqList.forEach(noticeEq -> EquipUsedCheckStrategyContext.getUsedStrategy(PROCESS_DEFINITION_KEY)
                    .delDataForCheckEquipRepeatUsed(Collections.singletonList(noticeEq.getEquId()), notice.getNewUseUnitCreditCode()));
        }
    }

    private void rollBackForDelRedisData() {
        FlowingEquipRedisContext.getContext().forEach(e -> {
            EquipUsedCheckStrategyContext.getUsedStrategy(PROCESS_DEFINITION_KEY)
                    .delDataForCheckWithKey(e.getData(), e.getRedisKey());
        });
    }

    public Page<Map<String, Object>> getPage(
            Page<JgChangeVehicleRegistrationUnit> page, String sort, JgChangeVehicleRegistrationUnitDto dto, String type, ReginParams reginParams, String client) {

        CompanyBo company = reginParams.getCompany();
        String companyCode = company.getCompanyCode().contains("_") ? company.getCompanyCode().split("_")[1] : company.getCompanyCode();
        type = "jgLook".equals(client) ? null : type;
        String orgCode = "jgLook".equals(client) ? company.getOrgCode() : null;
        String currentUserId = reginParams.getUserModel().getUserId();
        SortVo sortMap = commonService.sortFieldConversion(sort);
        return this.getBaseMapper().getPage(page, sortMap, dto, type, companyCode, currentUserId, dto.getRoleIds(), orgCode);
    }

    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class, timeoutMills = 600000)
    public void flowExecute(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);
            JgChangeVehicleRegistrationUnit jgChangeVehicleRegistrationUnit = this.getBaseMapper().selectById(id);
            // 组装信息
            TaskResultDTO dto = new TaskResultDTO();
            dto.setResultCode("approvalStatus");
            dto.setTaskId(jgChangeVehicleRegistrationUnit.getNextTaskId());
            dto.setComment(comment);
            HashMap<String, Object> map = new HashMap<>();
            map.put("approvalStatus", operate);
            if (jgChangeVehicleRegistrationUnit.getStatus().equals(WorkFlowStatusEnum.USE_SUBMIT.getReject()) || jgChangeVehicleRegistrationUnit.getStatus().equals(WorkFlowStatusEnum.USE_SUBMIT.getRollBack())) {
                map.put("approvalStatus", "提交");
            }
            dto.setVariable(map);
            // 接受机构
            if ("1".equals(operate) && WorkFlowStatusEnum.USE_RECEIVE.getPass().equals(jgChangeVehicleRegistrationUnit.getStatus())) {
                // 驳回到使用单位
                dto.setNextExecuteUserCompanyCode(jgChangeVehicleRegistrationUnit.getNewUseUnitCreditCode());
            } else {
                dto.setNextExecuteUserCompanyCode(jgChangeVehicleRegistrationUnit.getReceiveCompanyCode());
            }
            ProcessTaskDTO complete = cmWorkflowService.completeOrReject(jgChangeVehicleRegistrationUnit.getNextTaskId(), dto, operate);
            ArrayList<ProcessTaskDTO> processTaskDTOS = new ArrayList<>();
            processTaskDTOS.add(complete);
            List<WorkflowResultDto> resultDto = commonServiceImpl.buildWorkFlowInfo(processTaskDTOS);
            if (!ObjectUtils.isEmpty(resultDto) && !ObjectUtils.isEmpty(resultDto.get(0))) {
                WorkflowResultDto workflowResultDto = resultDto.get(0);
                updateData(jgChangeVehicleRegistrationUnit.getSequenceNbr(), operate, workflowResultDto, Boolean.FALSE);
            }
            this.delRepeatUseEquipData(jgChangeVehicleRegistrationUnit);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }


    public JgChangeVehicleRegistrationUnit updateData(Long sequenceNbr, String operate, WorkflowResultDto
            workflowResultDto, Boolean isFirst) {
        ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
        String role = workflowResultDto.getNextExecutorRoleIds();
        String taskCode = FlowStatusEnum.TO_BE_FINISHED.getName();
        if (!ObjectUtils.isEmpty(workflowResultDto.getNextTaskCode())) {
            taskCode = workflowResultDto.getNextTaskCode();
        }
        JgChangeVehicleRegistrationUnit jgChangeVehicleRegistrationUnit = this.getBaseMapper().selectById(sequenceNbr);
        jgChangeVehicleRegistrationUnit.setNextTaskId(workflowResultDto.getNextTaskId());
        jgChangeVehicleRegistrationUnit.setNextExecuteUserIds(workflowResultDto.getNextExecutorUserIds());

        if (isFirst) {
            jgChangeVehicleRegistrationUnit.setInstanceStatus(workflowResultDto.getExecutorRoleIds());
            jgChangeVehicleRegistrationUnit.setInstanceId(workflowResultDto.getInstanceId());
        }
        if (!FlowStatusEnum.TO_BE_FINISHED.getName().equals(taskCode)) {
            jgChangeVehicleRegistrationUnit.setNextExecutorIds(role);
            jgChangeVehicleRegistrationUnit.setPromoter(reginParams.getUserModel().getUserId());
            if (!ObjectUtils.isEmpty(jgChangeVehicleRegistrationUnit.getInstanceStatus())) {
                jgChangeVehicleRegistrationUnit.setInstanceStatus(jgChangeVehicleRegistrationUnit.getInstanceStatus() + "," + role);
            } else {
                jgChangeVehicleRegistrationUnit.setInstanceStatus(role);
            }
            if ("0".equals(operate)) {
                // 通过操作
                jgChangeVehicleRegistrationUnit.setStatus(WorkFlowStatusEnum.getMessage(taskCode).getPass());
            } else {
                // 驳回操作
                jgChangeVehicleRegistrationUnit.setStatus(WorkFlowStatusEnum.getMessage(taskCode).getReject());
                jgChangeVehicleRegistrationUnit.setPromoter("");
            }
            if (isFirst) {
                buildTask(jgChangeVehicleRegistrationUnit, workflowResultDto);
            } else {
                // 更新代办状态
                HashMap<String, Object> params = new HashMap<>();
                params.put("relationId", jgChangeVehicleRegistrationUnit.getInstanceId());
                params.put("flowStatus", commonServiceImpl.getDictionaryCodeByName(jgChangeVehicleRegistrationUnit.getStatus()));
                params.put("flowStatusLabel", jgChangeVehicleRegistrationUnit.getStatus());
                params.put("taskStatus", commonServiceImpl.getDictionaryCodeByName(jgChangeVehicleRegistrationUnit.getStatus()));
                params.put("taskStatusLabel", jgChangeVehicleRegistrationUnit.getStatus());
                TaskV2Model taskV2Model = commonServiceImpl.updateTaskModel(params);
                // 创建新的代办
                if (!ObjectUtils.isEmpty(taskV2Model)) {
                    TaskModelDto taskModelDto = new TaskModelDto();
                    BeanUtils.copyProperties(taskV2Model, taskModelDto);
                    TaskMessageDto taskMessageDto = new TaskMessageDto();
                    BeanUtil.copyProperties(jgChangeVehicleRegistrationUnit, taskMessageDto);
                    taskModelDto.setModel(taskMessageDto);
                    taskModelDto.setTaskName(workflowResultDto.getNextTaskName());
                    taskModelDto.setExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
                    taskModelDto.setTaskStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
                    taskModelDto.setNextExecuteUser(workflowResultDto.getNextExecutorRoleIds());
                    taskModelDto.setFlowCode(workflowResultDto.getNextTaskId());
                    if (WorkFlowStatusEnum.USE_SUBMIT.getCode().equals(taskCode) && "1".equals(operate)) {
                        taskModelDto.setPageType("edit");
                    }
                    commonServiceImpl.buildTaskModel(Collections.singletonList(taskModelDto));
                } else {
                    workflowResultDto.setInstanceId(jgChangeVehicleRegistrationUnit.getInstanceId());
                    buildTask(jgChangeVehicleRegistrationUnit, workflowResultDto);
                }
            }
        } else {
            // 流程结束
            jgChangeVehicleRegistrationUnit.setStatus(taskCode);
            jgChangeVehicleRegistrationUnit.setNextExecuteUserIds("");
            jgChangeVehicleRegistrationUnit.setAuditPassDate(new Date());

            LambdaQueryWrapper<JgRegistrationHistory> lambdaSelect = new QueryWrapper<JgRegistrationHistory>().lambda();
            lambdaSelect.eq(JgRegistrationHistory::getCurrentDocumentId, String.valueOf(sequenceNbr));
            lambdaSelect.eq(JgRegistrationHistory::getIsDelete, false);
            // 更新代办
            TaskV2Model taskV2Model = updateAgency(jgChangeVehicleRegistrationUnit);
            // 修改设备信息、添加证、设备流水信息
            saveRecord(jgChangeVehicleRegistrationUnit, taskV2Model);
            // 审核通过发送数据变更消息
            this.sendDataRefreshMsgEquip(jgChangeVehicleRegistrationUnit);
            // 创建设备履历
            this.createResume(jgChangeVehicleRegistrationUnit, taskV2Model.getRoutePath());
        }
        this.getBaseMapper().updateById(jgChangeVehicleRegistrationUnit);
        commonServiceImpl.saveExecuteFlowData2Redis(jgChangeVehicleRegistrationUnit.getInstanceId(), this.buildInstanceRuntimeData(jgChangeVehicleRegistrationUnit));
        return jgChangeVehicleRegistrationUnit;
    }

    private void createResume(JgChangeVehicleRegistrationUnit changeVehicleRegistrationUnit , String routePath) {
        List<JgChangeVehicleRegistrationUnitEq> registrationUnitEqs = getJgChangeVehicleRegistrationUnitEqs(changeVehicleRegistrationUnit);
        JgResumeInfo info = JgResumeInfo.builder().applyNo(changeVehicleRegistrationUnit.getApplyNo())
                .businessType(BusinessTypeEnum.JG_VEHICLE_GAS_CYLINDER_CHANGE.getName())
                .businessId(String.valueOf(changeVehicleRegistrationUnit.getSequenceNbr()))
                .approvalUnit(changeVehicleRegistrationUnit.getReceiveOrgName())
                .approvalUnitCode(changeVehicleRegistrationUnit.getReceiveOrgCode())
                .status("正常")
                .changeContent(BusinessTypeEnum.JG_VEHICLE_GAS_CYLINDER_CHANGE.getName() + "业务办理")
                .routePath(routePath)
                .build();
        jgResumeInfoService.save(info);
        jgResumeInfoEqService.saveBatchResumeEq(registrationUnitEqs.stream()
                .map(eq -> JgResumeInfoEq.builder()
                        .resumeId(String.valueOf(info.getSequenceNbr()))
                        .equId(eq.getEquId())
                        .build())
                .collect(Collectors.toList()));
    }

    private List<JgChangeVehicleRegistrationUnitEq> getJgChangeVehicleRegistrationUnitEqs(JgChangeVehicleRegistrationUnit changeVehicleRegistrationUnit) {
        LambdaQueryWrapper<JgChangeVehicleRegistrationUnitEq> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(JgChangeVehicleRegistrationUnitEq::getUnitChangeId, changeVehicleRegistrationUnit.getSequenceNbr());
        queryWrapper.select(JgChangeVehicleRegistrationUnitEq::getEquId, BaseEntity::getSequenceNbr);
        return jgChangeVehicleRegistrationUnitEqService.list(queryWrapper);
    }

    private void sendDataRefreshMsgEquip(JgChangeVehicleRegistrationUnit vehicleRegistrationUnit) {
        LambdaQueryWrapper<JgChangeVehicleRegistrationUnitEq> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(JgChangeVehicleRegistrationUnitEq::getUnitChangeId, vehicleRegistrationUnit.getSequenceNbr());
        queryWrapper.select(JgChangeVehicleRegistrationUnitEq::getEquId);
        List<String> records = jgChangeVehicleRegistrationUnitEqService.list(queryWrapper).stream().map(JgChangeVehicleRegistrationUnitEq::getEquId).collect(Collectors.toList());
        eventPublisher.publish(new DataRefreshEvent(this, records, DataRefreshEvent.DataType.equipment.name(), DataRefreshEvent.Operation.UPDATE));
    }


    public void updateEsData(List<String> ids, JgChangeVehicleRegistrationUnit
            jgChangeVehicleRegistrationUnit, String useRegistCode) {
        // 更新es
        HashMap<String, Map<String, Object>> objMap = new HashMap<>();
        ids.forEach(item -> {
            HashMap<String, Object> param = new HashMap<>();
            param.put("EQU_STATE", EquipmentEnum.ZAIYONG.getCode().toString());
            param.put("USE_UNIT_NAME", jgChangeVehicleRegistrationUnit.getNewUseUnitName());
            param.put("USE_UNIT_CREDIT_CODE", jgChangeVehicleRegistrationUnit.getNewUseUnitCreditCode());
            // 更新车用气瓶变更登记后，修改气瓶的单位内部编号为车牌号 bug23732
            param.put("USE_INNER_CODE", jgChangeVehicleRegistrationUnit.getNewCarNumber());
            if (!ObjectUtils.isEmpty(useRegistCode)) {
                param.put("USE_ORG_CODE", useRegistCode);
                // 需求调整 监管码一生不再变化
                // LambdaQueryWrapper<IdxBizJgOtherInfo> eq = new QueryWrapper<IdxBizJgOtherInfo>().lambda().eq(IdxBizJgOtherInfo::getRecord, item);
                // IdxBizJgOtherInfo idxBizJgOtherInfo = otherInfoMapper.selectOne(eq);
                // if (!ObjectUtils.isEmpty(idxBizJgOtherInfo)) {
                //     param.put("SUPERVISORY_CODE", idxBizJgOtherInfo.getSupervisoryCode());
                // }
            }

            param.put("ADDRESS", jgChangeVehicleRegistrationUnit.getAddress());
            param.put("ORG_BRANCH_CODE", jgChangeVehicleRegistrationUnit.getOrgBranchCode());
            param.put("ORG_BRANCH_NAME", jgChangeVehicleRegistrationUnit.getOrgBranchName());
            objMap.put(item, param);
        });
        tzsServiceFeignClient.commonUpdateEsDataByIds(objMap);
    }

    @FieldMapping({
            @FieldMapping.FieldMap(
                    sourceField = "estateUnitName",
                    paramIndex = 1,
                    targetField = "estateUnitName",
                    serviceClass = CommonServiceImpl.class,
                    queryMethod = "queryTcmUnitCreditCodeAndNameBySeq",
                    secondParamValue = "CQ"
            )
    })
    public void saveRecord(JgChangeVehicleRegistrationUnit jgChangeVehicleRegistrationUnit, TaskV2Model taskV2Model) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        jgChangeVehicleRegistrationUnit.setAddress(
                Optional.ofNullable(jgChangeVehicleRegistrationUnit.getNewUseUnitCreditCode())
                        .filter(org.apache.commons.lang3.ObjectUtils::isNotEmpty)
                        .map(tzBaseEnterpriseInfoMapper::selectByUseUnitCode)
                        .map(TzBaseEnterpriseInfo::getAddress)
                        .orElse("")
        );
        JgUseRegistrationManage manage = jgUseRegistrationManageService.lambdaQuery()
                .eq(JgUseRegistrationManage::getUseRegistrationCode, jgChangeVehicleRegistrationUnit.getUseRegistCode())
                .eq(JgUseRegistrationManage::getIsDelete, 0)
                .one();
        // 业务流水生成
        JgRegistrationHistory jgRegistrationHistory = jgRegistrationHistoryService.lambdaQuery()
                .eq(JgRegistrationHistory::getCurrentDocumentId, jgChangeVehicleRegistrationUnit.getSequenceNbr())
                .eq(JgRegistrationHistory::getIsDelete, false)
                .one();
        JSONObject jsonObject = JSONObject.parseObject(jgRegistrationHistory.getChangeData());
        JSONArray dataList = JSONObject.parseArray(jsonObject.get("dataList").toString());
        ArrayList<JgCertificateChangeRecordEq> jgCertificateChangeRecordEqs = new ArrayList<>();
        //List<String> collect = jgCertificateChangeRecordEqs.stream().map(JgCertificateChangeRecordEq::getEquId).collect(Collectors.toList());
        List<String> collect = dataList.stream()
                .map(obj -> ((JSONObject) obj).getString("record"))
                .collect(Collectors.toList());

        JgCertificateChangeRecord jgCertificateChangeRecord = new JgCertificateChangeRecord();
        jgCertificateChangeRecord.setApplyNo(jgChangeVehicleRegistrationUnit.getApplyNo());
        jgCertificateChangeRecord.setReceiveOrgName(jgChangeVehicleRegistrationUnit.getReceiveOrgName());
        jgCertificateChangeRecord.setAuditPassDate(new Date());
        jgCertificateChangeRecord.setRegType(BUSINESS_NAME);
        jgCertificateChangeRecord.setRegDate(jgChangeVehicleRegistrationUnit.getApplyDate());
        FeignClientResult<AgencyUserModel> agencyUserModelFeignClientResult = Privilege.agencyUserClient.queryByUserId(jgChangeVehicleRegistrationUnit.getCreateUserId());
        jgCertificateChangeRecord.setChangeContent(jgChangeVehicleRegistrationUnit.getNewUseUnitName() + "的" + agencyUserModelFeignClientResult.getResult().getRealName() + "办理了【" + BUSINESS_NAME + "】," + "单号【" + jgChangeVehicleRegistrationUnit.getApplyNo() +
                "】,原" + jgChangeVehicleRegistrationUnit.getUseUnitName() + "变更为" + jgChangeVehicleRegistrationUnit.getNewUseUnitName() + ",办理日期" + sdf.format(jgChangeVehicleRegistrationUnit.getAuditPassDate()));
        jgCertificateChangeRecord.setRecUserId(jgChangeVehicleRegistrationUnit.getRecUserId());
        jgCertificateChangeRecord.setRecDate(new Date());
        jgCertificateChangeRecord.setCreateDate(new Date());
        jgCertificateChangeRecord.setCreateUserId(jgChangeVehicleRegistrationUnit.getCreateUserId());
        jgCertificateChangeRecord.setCertificateNo(manage.getCertificateNo());
        jgCertificateChangeRecord.setUseUnitCreditCode(jgChangeVehicleRegistrationUnit.getNewUseUnitCreditCode());
        jgCertificateChangeRecord.setUseUnitName(jgChangeVehicleRegistrationUnit.getNewUseUnitName());
        jgCertificateChangeRecord.setEquCategory(manage.getEquCategory());
        jgCertificateChangeRecord.setReceiveCompanyCode(jgChangeVehicleRegistrationUnit.getReceiveCompanyCode());
        jgCertificateChangeRecord.setRoutePath(taskV2Model.getRoutePath());
        if ("0".equals(jgChangeVehicleRegistrationUnit.getChangeType()) && !ObjectUtils.isEmpty(collect)) {
            // 区外变更
            // 生成使用登记证编号,根据行政审批局单位code获取行政区划code
            String receiveCompanyCode = codeUtil.getCityRegionCode(jgChangeVehicleRegistrationUnit.getReceiveCompanyCode());
            CompanyModel receiveCompanyResult = Privilege.companyClient.queryByCompanyCode(receiveCompanyCode).getResult();
            //查询到局级
            // 如果不是局级公司，则查询其上级公司信息
            if (!"prefecture-level".equals(receiveCompanyResult.getLevel())) {
                CompanyModel receiveParentResult = Privilege.companyClient.seleteOne(receiveCompanyResult.getParentId()).getResult();
                receiveCompanyCode = receiveParentResult.getCompanyCode();
            }
            // 生成新的使用登记证编号
            String code = this.generateVehicleUseRegistrationCode(receiveCompanyCode, manage.getEquDefineCode());
            manage.setUseRegistrationCode(code);
            manage.setRegistrationType("0");
            // 更新设备使用登记证信息
            LambdaQueryWrapper<IdxBizJgRegisterInfo> lambda = new QueryWrapper<IdxBizJgRegisterInfo>().lambda();
            lambda.in(IdxBizJgRegisterInfo::getRecord, collect);
            IdxBizJgRegisterInfo registerInfo = new IdxBizJgRegisterInfo();
            registerInfo.setUseOrgCode(code);
            idxBizJgRegisterInfoService.update(registerInfo, lambda);
            // 使用登记证下设备更新监管码， 需求调整 监管码一生不再变化
            // collect.forEach(a -> {
            //     createCode(jgChangeVehicleRegistrationUnit, manage.getEquDefineCode(), a);
            // });
            // 更新es数据
            updateEsData(collect, jgChangeVehicleRegistrationUnit, code);
        }

        // 更新使用信息
        LambdaQueryWrapper<IdxBizJgUseInfo> lambda = new QueryWrapper<IdxBizJgUseInfo>().lambda();
        lambda.in(IdxBizJgUseInfo::getRecord, collect);
        IdxBizJgUseInfo useInfo = new IdxBizJgUseInfo();
        // 产权单位信息
        if (!StringUtils.isEmpty(jsonObject.getString("estateUnitName"))) {
            String[] data = String.valueOf(jsonObject.getString("estateUnitName")).split("_");
            // 更新产权单位
            if (data.length > 1) {
                useInfo.setEstateUnitCreditCode(data[0]);
                useInfo.setEstateUnitName(data[1]);
            } else {
                useInfo.setEstateUnitName(MapUtil.getStr(jsonObject, "estateUnitName"));
                useInfo.setEstateUnitCreditCode(MapUtil.getStr(jsonObject, "estateUnitCreditCode"));
            }
        }
        useInfo.setUseUnitName(jgChangeVehicleRegistrationUnit.getNewUseUnitName());
        useInfo.setUseUnitCreditCode(jgChangeVehicleRegistrationUnit.getNewUseUnitCreditCode());
        useInfo.setAddress(jgChangeVehicleRegistrationUnit.getAddress());
        idxBizJgUseInfoServiceImpl.update(useInfo, lambda);

        // 更新监管信息
        IdxBizJgSupervisionInfo supervisionInfo = new IdxBizJgSupervisionInfo();
        LambdaQueryWrapper<IdxBizJgSupervisionInfo> supervisionInfoLambda = new QueryWrapper<IdxBizJgSupervisionInfo>().lambda();
        supervisionInfo.setOrgBranchName(jgChangeVehicleRegistrationUnit.getOrgBranchName());
        supervisionInfo.setOrgBranchCode(jgChangeVehicleRegistrationUnit.getOrgBranchCode());
        supervisionInfoLambda.in(IdxBizJgSupervisionInfo::getRecord, collect);
        idxBizJgSupervisionInfoService.update(supervisionInfo, supervisionInfoLambda);

        // 区内变更
        if ("1".equals(jgChangeVehicleRegistrationUnit.getChangeType()) && !ObjectUtils.isEmpty(collect)) {
            updateEsData(collect, jgChangeVehicleRegistrationUnit, null);
        }
        // 更新车用气瓶变更登记后，修改气瓶的单位内部编号为车牌号 bug23732
        updateCarNumIntoUseInnerCode(jgChangeVehicleRegistrationUnit, collect);
        // 修改证管理信息
        manage.setUseUnitName(jgChangeVehicleRegistrationUnit.getNewUseUnitName());
        manage.setUseUnitCreditCode(jgChangeVehicleRegistrationUnit.getNewUseUnitCreditCode());
        manage.setReceiveCompanyCode(jgChangeVehicleRegistrationUnit.getReceiveOrgCode());
        manage.setReceiveOrgName(jgChangeVehicleRegistrationUnit.getReceiveOrgName());
        manage.setAuditPassDate(new Date());
        manage.setUseUnitAddress(jgChangeVehicleRegistrationUnit.getAddress());
        // 新增新车牌号后，兼容老数据默认新车牌号 与 老的一致
        manage.setCarNumber(jgChangeVehicleRegistrationUnit.getNewCarNumber() != null ? jgChangeVehicleRegistrationUnit.getNewCarNumber() : jgChangeVehicleRegistrationUnit.getCarNumber());
        manage.setVersion(manage.getVersion() + 1);
        manage.setChangeReason(BusinessTypeEnum.JG_VEHICLE_GAS_CYLINDER_CHANGE.getName());
        manage.setSuperviseOrgCode(jgChangeVehicleRegistrationUnit.getOrgBranchCode());
        manage.setSuperviseOrgName(jgChangeVehicleRegistrationUnit.getOrgBranchName());
        manage.setCertificateStatus("已登记");
        jgUseRegistrationManageService.updateById(manage);
        // 保存证流水信息
        jgCertificateChangeRecord.setUseRegistrationCode(manage.getUseRegistrationCode());
        jgCertificateChangeRecordService.save(jgCertificateChangeRecord);
        // 组装设备流水
        dataList.forEach(item -> {
            JSONObject object = JSONObject.parseObject(JSON.toJSONString(item));
            JgCertificateChangeRecordEq jgCertificateChangeRecordEq = new JgCertificateChangeRecordEq();
            jgCertificateChangeRecordEq.setEquId(Objects.toString(object.get("record"),""));
            jgCertificateChangeRecordEq.setChangeRecordId(jgCertificateChangeRecord.getSequenceNbr().toString());
            jgCertificateChangeRecordEq.setProductCode(Objects.toString(object.get("factoryNum"),""));
            jgCertificateChangeRecordEqs.add(jgCertificateChangeRecordEq);
        });

        // 新车牌号写入
        LambdaUpdateWrapper<IdxBizJgRegisterInfo> updateWrapper = new LambdaUpdateWrapper<IdxBizJgRegisterInfo>();
        updateWrapper.in(IdxBizJgRegisterInfo::getRecord, collect);
        updateWrapper.set(IdxBizJgRegisterInfo::getCarNumber, jgChangeVehicleRegistrationUnit.getNewCarNumber() != null ? jgChangeVehicleRegistrationUnit.getNewCarNumber() : jgChangeVehicleRegistrationUnit.getCarNumber());
        idxBizJgRegisterInfoService.update(updateWrapper);
        // 保存设备流水信息
        jgCertificateChangeRecordEqService.saveBatch(jgCertificateChangeRecordEqs);
    }

    private void updateCarNumIntoUseInnerCode(JgChangeVehicleRegistrationUnit jgChangeVehicleRegistrationUnit, List<String> collect) {
        LambdaUpdateWrapper<IdxBizJgUseInfo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.in(IdxBizJgUseInfo::getRecord, collect);
        updateWrapper.set(IdxBizJgUseInfo::getUseInnerCode, jgChangeVehicleRegistrationUnit.getNewCarNumber());
        updateWrapper.set(IdxBizJgUseInfo::getEquState, EquipmentEnum.ZAIYONG.getCode().toString());
        jgUseInfoMapper.update(null, updateWrapper);
    }

    /**
     * 生成监管码
     */
    public void createCode(JgChangeVehicleRegistrationUnit jgChangeVehicleRegistrationUnit, String
            equCategory, String record) {
        Map<String, Object> map = new HashMap<>();
        map.put("cityCode", XI_XIAN.getCode().equals(jgChangeVehicleRegistrationUnit.getVehicleApanage()) ? XIAN_YANG.getCode() : jgChangeVehicleRegistrationUnit.getVehicleApanage());
        map.put("isXiXian", XI_XIAN.getCode().equals(jgChangeVehicleRegistrationUnit.getVehicleApanage()) ? "1" : "0");
        map.put("equCategory", equCategory);
        map.put("countyCode", XI_XIAN.getCode().equals(jgChangeVehicleRegistrationUnit.getVehicleApanage()) ? XIAN_YANG.getCode() : jgChangeVehicleRegistrationUnit.getVehicleApanage());

        // 调用服务创建代码
        ResponseModel<Map<String, Object>> code = tzsServiceFeignClient.createCode(map);
        Map<String, Object> result = code.getResult();

        // 更新其他信息
        if (result != null && !result.isEmpty()) {
            LambdaQueryWrapper<IdxBizJgOtherInfo> lambda = new QueryWrapper<IdxBizJgOtherInfo>().lambda();
            lambda.eq(IdxBizJgOtherInfo::getRecord, record);
            IdxBizJgOtherInfo idxBizJgOtherInfo = new IdxBizJgOtherInfo();
            idxBizJgOtherInfo.setSupervisoryCode(String.valueOf(result.get("superviseCode")));
            otherInfoMapper.update(idxBizJgOtherInfo, lambda);
        }
    }

    /**
     * 根据车辆属地生成使用登记证
     *
     * @param receiveCompanyCode 车辆属地
     * @return String
     */
    private String generateVehicleUseRegistrationCode(String receiveCompanyCode, String equDefineCode) {
        // 构建设备种类简称
        String useRegistration = String.format("瓶%s%s", equDefineCode.substring(1, 3), VehicleApanageEnum.of(receiveCompanyCode));
        String useRegistrationCode;
        JgUseRegistrationManage jgUseRegistrationManage;
        do {
            ResponseModel<String> stringResponseModel = tzsServiceFeignClient.useRegistrationCode(useRegistration);
            useRegistrationCode = stringResponseModel.getResult();
            // 查询是否已有相同登记证号的记录
            jgUseRegistrationManage = jgUseRegistrationManageService.getBaseMapper().selectOne(
                    new LambdaQueryWrapper<JgUseRegistrationManage>()
                            .eq(JgUseRegistrationManage::getUseRegistrationCode, useRegistrationCode)
                            .eq(JgUseRegistrationManage::getIsDelete, 0)
                            .eq(JgUseRegistrationManage::getCertificateStatus, "已登记")
            );
        } while (jgUseRegistrationManage != null);
        return useRegistrationCode;
    }

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

    private TaskV2Model updateAgency(JgChangeVehicleRegistrationUnit jgChangeVehicleRegistrationUnit) {
        // 更新代办状态
        HashMap<String, Object> params = new HashMap<>();
        params.put("relationId", jgChangeVehicleRegistrationUnit.getInstanceId());
        params.put("flowStatus", commonServiceImpl.getDictionaryCodeByName(jgChangeVehicleRegistrationUnit.getStatus()));
        params.put("flowStatusLabel", jgChangeVehicleRegistrationUnit.getStatus());
        params.put("taskStatus", FlowStatusEnum.TO_BE_FINISHED.getCode());
        params.put("taskStatusLabel", FlowStatusEnum.TO_BE_FINISHED.getName());
        TaskMessageDto taskMessageDto = new TaskMessageDto();
        BeanUtil.copyProperties(jgChangeVehicleRegistrationUnit, taskMessageDto);
        params.put("model", taskMessageDto);
        return commonServiceImpl.updateTaskModel(params);
    }

    public void buildTask(JgChangeVehicleRegistrationUnit jgChangeVehicleRegistrationUnit, WorkflowResultDto
            workflowResultDto) {
        // 代办消息
        ArrayList<TaskModelDto> list = new ArrayList<>();
        TaskModelDto dto = new TaskModelDto();
        dto.setTaskType(String.valueOf(BusinessTypeEnum.JG_VEHICLE_GAS_CYLINDER_CHANGE.getCode()));
        dto.setTaskTypeLabel(BusinessTypeEnum.JG_VEHICLE_GAS_CYLINDER_CHANGE.getName());
        dto.setFlowCreateDate(jgChangeVehicleRegistrationUnit.getCreateDate());
        dto.setTaskName(workflowResultDto.getNextTaskName());
        dto.setTaskCode(workflowResultDto.getNextTaskCode());
        dto.setRelationId(workflowResultDto.getInstanceId());
        dto.setExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
        dto.setTaskStatus(commonServiceImpl.getDictionaryCodeByName(WorkFlowStatusEnum.getMessage(workflowResultDto.getNextTaskCode()).getPass()));
        dto.setTaskStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
        dto.setFlowStatus(commonServiceImpl.getDictionaryCodeByName(jgChangeVehicleRegistrationUnit.getStatus()));
        dto.setFlowStatusLabel(jgChangeVehicleRegistrationUnit.getStatus());
        dto.setStartUserId(jgChangeVehicleRegistrationUnit.getCreateUserId());
        dto.setStartUser(jgChangeVehicleRegistrationUnit.getCreateUserName());
        dto.setStartUserCompanyName(jgChangeVehicleRegistrationUnit.getNewUseUnitName());
        dto.setStartDate(new Date());
        jgChangeVehicleRegistrationUnit.setInstanceId(workflowResultDto.getInstanceId());
        jgChangeVehicleRegistrationUnit.setNextExecutorIds(workflowResultDto.getNextExecutorRoleIds());
        TaskMessageDto taskMessageDto = new TaskMessageDto();
        BeanUtil.copyProperties(jgChangeVehicleRegistrationUnit, taskMessageDto);
        dto.setTaskContent(String.format(template, jgChangeVehicleRegistrationUnit.getApplyNo()));
        dto.setModel(taskMessageDto);
        dto.setNextExecuteUser(workflowResultDto.getNextExecutorRoleIds());
        dto.setFlowCode(jgChangeVehicleRegistrationUnit.getNextTaskId());
        list.add(dto);
        commonServiceImpl.buildTaskModel(list);
    }

    public void saveHistory(JgChangeVehicleRegistrationUnit dto, JSONObject map) {
        JgRegistrationHistory jgRegistrationHistory = new JgRegistrationHistory();
        LambdaQueryWrapper<JgRegistrationHistory> lambda = new QueryWrapper<JgRegistrationHistory>().lambda();
        lambda.eq(JgRegistrationHistory::getCurrentDocumentId, dto.getSequenceNbr());
        lambda.eq(JgRegistrationHistory::getRegistrationClass, BUSINESS_NAME);
        lambda.eq(JgRegistrationHistory::getIsDelete, false);
        Integer integer = jgRegistrationHistoryService.getBaseMapper().selectCount(lambda);
        if (integer > 0) {
            jgRegistrationHistory.setChangeData(JSON.toJSONString(map));
            jgRegistrationHistoryService.update(jgRegistrationHistory, lambda);
        } else {
            jgRegistrationHistory.setChangeData(JSON.toJSONString(map));
            jgRegistrationHistory.setStatus("new");
            jgRegistrationHistory.setRegistrationClass(BUSINESS_NAME);
            jgRegistrationHistory.setCurrentDocumentId(dto.getSequenceNbr().toString());
            jgRegistrationHistoryService.save(jgRegistrationHistory);
        }

    }

    public void saveChangeVehicleEq(JgChangeVehicleRegistrationUnit dto, JSONObject map) {
        ArrayList<JgChangeVehicleRegistrationUnitEq> list = new ArrayList<>();
        if (map.containsKey("dataList")) {
            JSONArray objects = JSONObject.parseArray(JSON.toJSONString(map.get("dataList")));
            objects.forEach(data -> {
                JgChangeVehicleRegistrationUnitEq jgChangeVehicleRegistrationUnitEq = new JgChangeVehicleRegistrationUnitEq();
                JSONObject object = JSONObject.parseObject(data.toString());
                jgChangeVehicleRegistrationUnitEq.setUnitChangeId(dto.getSequenceNbr().toString());
                jgChangeVehicleRegistrationUnitEq.setRegistrationCertificate(map.get("useRegistrationCode").toString());
                jgChangeVehicleRegistrationUnitEq.setEquId(object.get("record").toString());
                jgChangeVehicleRegistrationUnitEq.setCreateDate(new Date());
                jgChangeVehicleRegistrationUnitEq.setCreateUserName(dto.getCreateUserName());
                jgChangeVehicleRegistrationUnitEq.setCreateUserId(dto.getCreateUserId());
                jgChangeVehicleRegistrationUnitEq.setRecDate(new Date());
                jgChangeVehicleRegistrationUnitEq.setRecUserId(dto.getRecUserId());
                list.add(jgChangeVehicleRegistrationUnitEq);
            });
        }
        if (!ObjectUtils.isEmpty(list)) {
            LambdaQueryWrapper<JgChangeVehicleRegistrationUnitEq> lambda = new QueryWrapper<JgChangeVehicleRegistrationUnitEq>().lambda();
            lambda.eq(JgChangeVehicleRegistrationUnitEq::getUnitChangeId, dto.getSequenceNbr());
            jgChangeVehicleRegistrationUnitEqService.remove(lambda);
            jgChangeVehicleRegistrationUnitEqService.saveBatch(list);
        }
    }

    /**
     * 分页查询
     */
    public Page<JgChangeVehicleRegistrationUnitDto> queryForJgChangeVehicleRegistrationUnitPage
    (Page<JgChangeVehicleRegistrationUnitDto> page) {
        return this.queryForPage(page, null, false);
    }

    /**
     * 列表查询 示例
     */
    public List<JgChangeVehicleRegistrationUnitDto> queryForJgChangeVehicleRegistrationUnitList() {
        return this.queryForList("", false);
    }


    public Page<JgUseRegistrationManageDto> getUseRegistrationCodeData(Page<JgUseRegistrationManageDto> page,
                                                                       JgUseRegistrationManageDto dto) {
        return jgUseRegistrationManageService.queryUseRegistrationManagePage(page, dto, null);
    }

    @ResultFieldMapping({@ResultFieldMapping.ResultFieldMap(sourceField = "estateUnitCode", targetField = "estateUnitSeq", serviceClass = CommonServiceImpl.class, queryMethod = "queryTcmUnitSeqByCreditCode", secondParamValue = "CQ")})
    public Map<String, Object> getEquList(String useRegistrationCode) {
        HashMap<String, Object> map = new HashMap<>();
        map.put("useRegistrationCode", useRegistrationCode);
        JgUseRegistrationManage registrationManage =
                jgUseRegistrationManageService.lambdaQuery()
                        .eq(JgUseRegistrationManage::getUseRegistrationCode, useRegistrationCode)
                        .eq(JgUseRegistrationManage::getIsDelete, 0)
                        .last("LIMIT 1")
                        .one();
        List<JSONObject> jsonObjects = registrationManage == null ? Collections.emptyList():
                Optional.ofNullable(jgUseRegistrationManageService.queryEquByCertificateSeq(registrationManage.getSequenceNbr())
        ).orElse(Collections.emptyList());
        if (!ObjectUtils.isEmpty(jsonObjects)) {
            List<String> records = jsonObjects.stream().map(a -> String.valueOf(a.get("SEQUENCE_NBR"))).collect(Collectors.toList());
            List<Map<String, Object>> equList = new ArrayList<>();
            Lists.partition(records, DB_BATCH_SIZE).forEach(batch -> {
                List<Map<String, Object>> part = this.getBaseMapper().getEquList(batch);
                equList.addAll(part);
            });
            equList.forEach(a -> {
                if (!ObjectUtils.isEmpty(registrationManage) && !ObjectUtils.isEmpty(registrationManage.getCarNumber())) {
                    a.put("carNumber", registrationManage.getCarNumber());
                }
                if (!ObjectUtils.isEmpty(a.get("chargingMedium"))) {
                    a.put("chargingMedium", getFillingMediumMap().get(a.getOrDefault("chargingMedium", "") + ""));
                }
            });
            String estateUnitName = equList.stream()
                .map(e -> e.get("estateUnitName"))
                .filter(Objects::nonNull)
                .filter(String.class::isInstance)
                .map(String.class::cast)
                .findFirst()
                .orElse("");
            if (!ValidationUtil.isEmpty(estateUnitName) && estateUnitName.contains("_") &&  estateUnitName.split("_").length >= 2) {
                map.put("estateUnitCode", estateUnitName.split("_")[0]);
                map.put("estateUnitName", estateUnitName.split("_")[1]);
            }
            map.put("dataList", equList);
            // 组件回显
            if (!ObjectUtils.isEmpty(registrationManage) && !ObjectUtils.isEmpty(registrationManage.getCarNumber())) {
                map.put("carNumber", registrationManage.getCarNumber());
            }
        }
        return map;
    }

    public Map<String, Object> getFillingMediumMap() {
        if (fillingMediumMap == null) {
            synchronized (this) {
                if (fillingMediumMap == null) {
                    List<DictionarieValueModel> fillingMedium = FeignUtil.remoteCall(() -> Systemctl.dictionarieClient.dictValues("FILLING_MEDIUM"));
                    fillingMediumMap = fillingMedium.stream().collect(Collectors.toMap(DictionarieValueModel::getDictDataKey, DictionarieValueModel::getDictDataValue));
                }
                return fillingMediumMap;
            }
        }
        return fillingMediumMap;

    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteMessage(String sequenceNbr) {
        JgChangeVehicleRegistrationUnit jgChangeVehicleRegistrationUnit = this.baseMapper.selectById(sequenceNbr);
        // 删除代办 + 中止流程
        commonServiceImpl.deleteTaskModel(sequenceNbr, jgChangeVehicleRegistrationUnit.getInstanceId());
        // 删除单子
        this.baseMapper.deleteById(sequenceNbr);
        // 删除单子对应eq
        jgChangeVehicleRegistrationUnitEqService.remove(new LambdaQueryWrapper<JgChangeVehicleRegistrationUnitEq>()
                .eq(JgChangeVehicleRegistrationUnitEq::getUnitChangeId, sequenceNbr));
        // 删除单子对应历史表数据
        jgRegistrationHistoryService.remove(new LambdaQueryWrapper<JgRegistrationHistory>()
                .eq(JgRegistrationHistory::getCurrentDocumentId, sequenceNbr));
        return Boolean.TRUE;
    }

    @ResultFieldMapping({
            @ResultFieldMapping.ResultFieldMap(sourceField = "useUnitCreditCode", targetField = "useUnitSeq", serviceClass = CommonServiceImpl.class, queryMethod = "queryUnitInfoByCreditCode")
    })
    public Map<String, Object> getDetails(String sequenceNbr, ReginParams selectedOrgInfo) {
        JgChangeVehicleRegistrationUnit registrationUnit = this.getById(sequenceNbr);
        this.doCompensate(registrationUnit);
        JgRegistrationHistory history = jgRegistrationHistoryService.lambdaQuery()
                .eq(JgRegistrationHistory::getCurrentDocumentId, sequenceNbr)
                .eq(JgRegistrationHistory::getRegistrationClass, BUSINESS_NAME)
                .eq(JgRegistrationHistory::getIsDelete, false)
                .one();
        if (!ObjectUtils.isEmpty(history) && !ObjectUtils.isEmpty(history.getChangeData())) {
            JSONObject object = JSONObject.parseObject(history.getChangeData());
            object.put("sequenceNbr", sequenceNbr);
            object.put("applyNo", registrationUnit.getApplyNo());
            object.put("status", registrationUnit.getStatus());
            // 新增新车牌后字段，兼容老数据
            if(registrationUnit.getNewCarNumber() != null){
                object.put("newCarNumber", registrationUnit.getNewCarNumber());
            } else {
                object.put("newCarNumber", registrationUnit.getCarNumber());
            }
            String companyType = selectedOrgInfo.getCompany().getCompanyType();
            // todo 注意顺序1
            new FillingEditPermForCurrentUser(new JSONObject(object), selectedOrgInfo.getCompany(), BusinessTypeEnum.JG_VEHICLE_GAS_CYLINDER_CHANGE).getData();
            // todo 注意顺序2
            if ("个人主体".equals(companyType)) {
                object.put("companyType", "person");
            } else {
                object.put("companyType", "company");
            }
            //  todo 注意顺序3
            object.put("companyType2", CommonServiceImpl.getCompanyType(selectedOrgInfo.getCompany()));
            object.put("havingPermission", registrationUnit.getNextExecuteUserIds() != null && registrationUnit.getNextExecuteUserIds().contains(RequestContext.getExeUserId()));
            object.put("receiveCompanyCode", registrationUnit.getReceiveCompanyCode() + "_" + registrationUnit.getReceiveOrgName());
            object.put("receiveOrgCode", registrationUnit.getReceiveOrgCode() + "_" + registrationUnit.getReceiveOrgName());
            return object;
        } else {
            return new HashMap<>();
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void withdraw(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("当前流程已经被执行！请重新打开页面查看并执行！");
            }
            // 撤回校验
            commonServiceImpl.checkForRevocationFlow(nextTaskId, instanceId);

            JgChangeVehicleRegistrationUnit jgChangeVehicleRegistrationUnit = new JgChangeVehicleRegistrationUnit();
            ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
            ProcessTaskDTO processTaskDTO = cmWorkflowService.rollBack(instanceId);
            ArrayList<ProcessTaskDTO> processTaskDTOS = new ArrayList<>();
            processTaskDTOS.add(processTaskDTO);
            List<WorkflowResultDto> resultDto = commonServiceImpl.buildWorkFlowInfo(processTaskDTOS);
            String taskCode = "";
            String roles = "";
            if (!ObjectUtils.isEmpty(resultDto) && !ObjectUtils.isEmpty(resultDto.get(0))) {
                taskCode = resultDto.get(0).getNextTaskCode();
                roles = resultDto.get(0).getNextExecutorRoleIds();
                jgChangeVehicleRegistrationUnit.setNextTaskId(resultDto.get(0).getNextTaskId());
                jgChangeVehicleRegistrationUnit.setNextExecuteUserIds(resultDto.get(0).getNextExecutorUserIds());
            }
            LambdaQueryWrapper<JgChangeVehicleRegistrationUnit> lambda = new QueryWrapper<JgChangeVehicleRegistrationUnit>().lambda();
            lambda.eq(JgChangeVehicleRegistrationUnit::getInstanceId, instanceId);
            if (!ObjectUtils.isEmpty(taskCode)) {
                jgChangeVehicleRegistrationUnit.setStatus(WorkFlowStatusEnum.getMessage(taskCode).getRollBack());
            }
            jgChangeVehicleRegistrationUnit.setPromoter(reginParams.getUserModel().getUserId());
            jgChangeVehicleRegistrationUnit.setNextExecutorIds(roles);
            this.update(jgChangeVehicleRegistrationUnit, lambda);
            LambdaQueryWrapper<JgChangeVehicleRegistrationUnit> queryWrapper = new QueryWrapper<JgChangeVehicleRegistrationUnit>().lambda();
            queryWrapper.eq(JgChangeVehicleRegistrationUnit::getInstanceId, instanceId);
            JgChangeVehicleRegistrationUnit data = this.baseMapper.selectOne(queryWrapper);
            // 设备信息
            JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(data));
            jsonObject.put("nextTaskId", data.getNextTaskId());
            jsonObject.put("nextExecuteUser", data.getNextExecutorIds());
            jsonObject.put("taskType", BusinessTypeEnum.JG_VEHICLE_GAS_CYLINDER_CHANGE.getCode());
            jsonObject.put("flowStatus", commonServiceImpl.getDictionaryCodeByName(jgChangeVehicleRegistrationUnit.getStatus()));
            jsonObject.put("flowStatusLabel", jgChangeVehicleRegistrationUnit.getStatus());
            jsonObject.put("pageType", "look");
            //如果创建人等于当前人则打开编辑页面
            if (taskCode.equals(WorkFlowStatusEnum.USE_SUBMIT.getCode())) {
                jsonObject.put("pageType", "edit");
            }
            // 撤回删除代办
            commonServiceImpl.rollbackTask(instanceId, jsonObject);
            // redis流程实时数据更新
            commonServiceImpl.saveExecuteFlowData2Redis(instanceId, this.buildInstanceRuntimeData(data));
            this.delRepeatUseEquipData(data);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    @Override
    public boolean beforeCheck(JgChangeVehicleRegistrationUnit jgChangeVehicleRegistrationUnit) {
        return jgChangeVehicleRegistrationUnit.getInstanceId() != null && !jgChangeVehicleRegistrationUnit.getStatus().equals(FlowStatusEnum.TO_BE_FINISHED.getName()) &&!jgChangeVehicleRegistrationUnit.getStatus().equals(FlowStatusEnum.TO_BE_DISCARD.getName());
    }

    @Override
    public void compensate(JgChangeVehicleRegistrationUnit jgChangeVehicleRegistrationUnit) {
        commonService.saveExecuteFlowData2Redis(jgChangeVehicleRegistrationUnit.getInstanceId(), this.buildInstanceRuntimeData(jgChangeVehicleRegistrationUnit));
    }
}