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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapBuilder;
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.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
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.controller.BaseController;
import com.yeejoin.amos.boot.biz.common.utils.RedisKey;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.boot.biz.common.utils.SnowflakeIdUtil;
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.mapper.JgCertificateReplenishMapper;
import com.yeejoin.amos.boot.module.jg.api.service.IJgCertificateReplenishService;
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.feign.TzsServiceFeignClient;
import com.yeejoin.amos.boot.module.jg.biz.utils.FileExporter;
import com.yeejoin.amos.boot.module.ymt.api.entity.EquipmentCategory;
import com.yeejoin.amos.boot.module.ymt.api.entity.IdxBizJgFactoryInfo;
import com.yeejoin.amos.boot.module.ymt.api.enums.ApplicationFormTypeEnum;
import com.yeejoin.amos.boot.module.ymt.api.enums.FlowStatusEnum;
import com.yeejoin.amos.boot.module.ymt.api.mapper.EquipmentCategoryMapper;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
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 lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
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 javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 使用登记表补证服务实现类
 *
 * @author system_generator
 * @date 2025-03-19
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class JgCertificateReplenishServiceImpl extends BaseService<JgCertificateReplenishDto, JgCertificateReplenish, JgCertificateReplenishMapper> implements IJgCertificateReplenishService {
    public static final String IDX_BIZ_VIEW_JG_ALL = "idx_biz_view_jg_all";
    public static final String equUseAddress = "equUseAddress";
    public static final String useRegistrationCode = "useRegistrationCode";
    public static final String whetherVehicleCylinder = "WHETHER_VEHICLE_CYLINDER";
    public static final String manageType = "manageType";
    public static final String USE_ORG_CODE = "USE_ORG_CODE";
    public static final String STATUS = "STATUS";
    public static final String record = "record";
    public static final String SEQUENCE_NBR = "SEQUENCE_NBR";
    public static final String FORM_DATA = "formData";
    public static final String EQU_LISTS = "equLists";
    public static final String EQU_LIST_CODE = "equListCode";
    public static final String RECEIVE_ORG_CODE = "receiveOrgCode";
    public static final String RECEIVE_ORG_NAME = "receiveOrgName";
    public static final String APPLICATION_FORM_FILE = "applicationFormFile";
    public static final String OTHER_ACCESSORIES = "otherAccessories";
    public static final String SAFETY_MANAGER_ID = "safetyManagerId";
    public static final String APPROVAL_STATUS = "approvalStatus";
    public static final String SAFETY_MANAGER_NAME = "safetyManagerName";
    public static final String LOSS_DAMAGE_TIME = "lossDamageTime";
    public static final String MODEL = "model";
    public static final String PROCESS_ADVICE = "processAdvice";
    public static final String IS_COMPANY = "isCompany";
    public static final String APPLY_STATUS = "applyStatus";
    public static final String APPLY_NO = "applyNo";
    public static final String APPLICATION_FORM_FILE_URL = "applicationFormFileUrl";
    private final List<String> NOT_FLOWING_STATE = Arrays.asList("6610", "6614", "6615", "6617", "6616");
    private final List<String> ATTACHMENT_FIELD = Arrays.asList(APPLICATION_FORM_FILE, OTHER_ACCESSORIES);
    private static final String EQUIP_TRANSFER_PROCESS_KEY = "certReplenish";
    private final Map<String, Function<JSONObject, Object>> actionMap = new HashMap<>();
    /**
     * 通过
     */
    public static final String APPROVED = "APPROVED";
    /**
     * 驳回
     */
    public static final String REJECTED = "REJECTED";
    /**
     * 提交
     */
    public static final String SUBMITTED = "SUBMITTED";
    /**
     * 暂存
     */
    public static final String DRAFT = "DRAFT";
    /**
     * 保存
     */
    public static final String UPDDATE_NOT_SUBMIT = "SAVE_NOT_SUBMIT";
    /**
     * 保存提交
     */
    public static final String UPDDATE_SUBMIT = "SAVE_SUBMIT";
    /**
     * 是否要提交 true :提交进入审批 false：暂存单据
     */
    public static final String SHOULD_SUBMIT = "SHOULD_SUBMIT";
    private final CommonServiceImpl commonService;
    private final JgUseRegistrationManageServiceImpl registrationManageService;
    private final TzsServiceFeignClient tzsServiceFeignClient;
    private final RedisUtils redisUtils;
    private final SnowflakeIdUtil sequence;
    private final RedissonClient redissonClient;
    private final CmWorkflowServiceImpl cmWorkflowService;
    private final EquipmentCategoryMapper equipmentCategoryMapper;
    private final JgCertificateReplenishEqServiceImpl certificateReplenishEqService;
    private final JgRegistrationHistoryServiceImpl jgRegistrationHistoryService;
    private final JgCertificateChangeRecordServiceImpl certificateChangeRecordService;
    private final JgCertificateChangeRecordEqServiceImpl certificateChangeRecordEqService;
    private final IdxBizJgFactoryInfoServiceImpl idxBizJgFactoryInfoService;
    private final JgCertificateReplenishMapper jgCertificateReplenishMapper;
    private final  JgResumeInfoServiceImpl jgResumeInfoService;

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

    @PostConstruct
    public void init() {
        actionMap.put(APPROVED, this::approved);
        actionMap.put(REJECTED, this::rejected);
        actionMap.put(SUBMITTED, this::submitted);
        actionMap.put(DRAFT, this::draft);
        actionMap.put(UPDDATE_NOT_SUBMIT, this::updateNotsubmit);
        actionMap.put(UPDDATE_SUBMIT, this::updateSubmit);
    }

    @GlobalTransactional(rollbackFor = Exception.class)
    public Object updateSubmit(JSONObject jsonObject) {
        JgCertificateReplenish certRep = this.buildUpdateCertRep(jsonObject, FlowStatusEnum.TO_BE_PROCESSED);
        if (!StringUtils.hasText(certRep.getInstanceId())) {
            // 未进流程直接发起并执行
            List<WorkflowResultDto> workflowResultDtos = this.startWorkFlow(certRep.getReceiveOrgCode(), certRep.getApplyNo());
            WorkflowResultDto workflowResultDto = workflowResultDtos.get(0);
            certRep.setInstanceId(workflowResultDto.getInstanceId());
            certRep.setNextExecuteIds(String.join(",", workflowResultDto.getNextExecutorUserIds()));
            certRep.setNextTaskId(workflowResultDto.getNextTaskId());
            certRep.setNextExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
            // 创建待办
            this.buildTask(certRep, workflowResultDtos);
            commonService.deleteTasksByRelationId(String.valueOf(certRep.getSequenceNbr()));
        } else {
            // 已经在流程中，执行一步
            ProcessTaskDTO processTaskDTO = this.submit(certRep);
            List<WorkflowResultDto> workflowResultDtos = commonService.buildWorkFlowInfo(Collections.singletonList(processTaskDTO));
            String nextUserIds = workflowResultDtos.get(0).getNextExecutorUserIds();
            certRep.setPromoter(RequestContext.getExeUserId());
            certRep.setNextTaskId(processTaskDTO.getNextTask().get(0).getId());
            // 更新下一步可执行人
            certRep.setNextExecuteUserIds(nextUserIds);
            commonService.deleteTasksByRelationId(certRep.getInstanceId());
            createTaskModel(certRep, processTaskDTO, nextUserIds);
        }
        commonService.saveExecuteFlowData2Redis(certRep.getInstanceId(), buildInstanceRuntimeData(certRep));
        certRep.setApplicationFormFileUrl(Objects.toString(this.getCertReplenishFormUrl(jsonObject, certRep.getApplyNo()).get(APPLICATION_FORM_FILE_URL)));
        this.updateById(certRep);
        this.updateCertRepEqs(jsonObject);
        return certRep;
    }

    private void createTaskModel(JgCertificateReplenish certRep, ProcessTaskDTO processTaskDTO, String nextUserIds) {
        TaskModelDto taskModelDto = new TaskModelDto();
        taskModelDto.setFlowCreateDate(certRep.getCreateDate());
        taskModelDto.setTaskCode(certRep.getApplyNo());
        taskModelDto.setTaskName(processTaskDTO.getNextTask().get(0).getName());
        taskModelDto.setRelationId(certRep.getInstanceId());
        taskModelDto.setExecuteUserIds(nextUserIds);
        taskModelDto.setTaskContent(String.format("来自%s的业务办理，【申请单号：%s】", certRep.getEquList(), certRep.getApplyNo()));
        taskModelDto.setTaskDesc("");
        taskModelDto.setTaskStatus(Integer.valueOf(certRep.getApplyStatus()));
        taskModelDto.setTaskStatusLabel(FlowStatusEnum.getNameByType(Long.parseLong(certRep.getApplyStatus())));
        taskModelDto.setStartUserId(certRep.getCreateUserId());
        taskModelDto.setFlowCode(certRep.getNextTaskId());
        taskModelDto.setFlowStatus(FlowStatusEnum.TO_BE_PROCESSED.getCode());
        taskModelDto.setFlowStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
        taskModelDto.setTaskType(BusinessTypeEnum.JG_REPLACEMENT_REGISTRATION.getCode());
        taskModelDto.setTaskTypeLabel(BusinessTypeEnum.JG_REPLACEMENT_REGISTRATION.getName());
        taskModelDto.setStartUser(certRep.getCreateUserName());
        taskModelDto.setStartUserCompanyName(certRep.getUseUnitName());
        taskModelDto.setNextExecuteUser(certRep.getNextExecuteIds());
        taskModelDto.setStartDate(new Date());
        TaskMessageDto taskMessageDto = new TaskMessageDto();
        BeanUtils.copyProperties(certRep, taskMessageDto);
        taskModelDto.setModel(taskMessageDto);
        commonService.buildTaskModel(Collections.singletonList(taskModelDto));
    }

    private TaskV2Model updateTaskModel(JgCertificateReplenish certRep) {
        Map<String, Object> params = new HashMap<>();
        params.put("relationId", certRep.getInstanceId());
        params.put("taskStatus", certRep.getApplyStatus());
        params.put("taskStatusLabel", FlowStatusEnum.getNameByType(Long.parseLong(certRep.getApplyStatus())));
        params.put("flowStatus", certRep.getApplyStatus());
        params.put("flowStatusLabel", FlowStatusEnum.getNameByType(Long.parseLong(certRep.getApplyStatus())));
        params.put("model", certRep);
        return commonService.updateTaskModel(params);
    }

    public Object updateNotsubmit(JSONObject jsonObject) {
        JgCertificateReplenish certRep = this.buildUpdateCertRep(jsonObject, FlowStatusEnum.TO_BE_SUBMITTED);
        certRep.setApplicationFormFileUrl(Objects.toString(this.getCertReplenishFormUrl(jsonObject, certRep.getApplyNo()).get(APPLICATION_FORM_FILE_URL)));
        this.updateById(certRep);
        this.updateCertRepEqs(jsonObject);
        return certRep;
    }

    private void updateCertRepEqs(JSONObject jsonObject) {
        Long certRepSeq = Long.parseLong(jsonObject.getString("sequenceNbr"));
        certificateReplenishEqService.remove(new LambdaQueryWrapper<JgCertificateReplenishEq>().eq(JgCertificateReplenishEq::getCertificateReplenishId, certRepSeq));
        JSONArray equLists = jsonObject.getJSONArray(EQU_LISTS);
        this.saveCertRepEqs(certRepSeq, equLists);
    }

    private JgCertificateReplenish buildUpdateCertRep(JSONObject jsonObject, FlowStatusEnum flowStatusEnum) {
        JgCertificateReplenish certRep = JSONObject.parseObject(jsonObject.toJSONString(), JgCertificateReplenish.class);
        String[] safetyManager = Objects.toString(jsonObject.get(SAFETY_MANAGER_ID)).split("_");
        this.setEquClassification(certRep);
        certRep.setApplyStatus(Objects.toString(flowStatusEnum.getCode()));
        Optional.ofNullable(jsonObject.get(APPLICATION_FORM_FILE)).ifPresent(x -> certRep.setApplicationFormFile(JSONObject.toJSONString(x)));
        Optional.ofNullable(jsonObject.get(OTHER_ACCESSORIES)).ifPresent(x -> certRep.setOtherAccessories(JSONObject.toJSONString(x)));
        certRep.setSafetyManagerName(safetyManager[1]);
        return certRep;
    }

    /**
     * 发起补证申请
     *
     * @return
     */
    @GlobalTransactional(rollbackFor = Exception.class)
    public List<JgCertificateReplenish> save(JSONObject jsonObj) {
        try {
            Function<JSONObject, Object> processor = actionMap.getOrDefault(jsonObj.getString(SHOULD_SUBMIT), this::draft);
            JgCertificateReplenish certRep = (JgCertificateReplenish) processor.apply(jsonObj);
            // 创建历史数据
            this.saveOrUpdateHisDataBatch(jsonObj, certRep.getSequenceNbr().toString());
            return Collections.singletonList(certRep);
        } 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();
        }
    }

    @GlobalTransactional(rollbackFor = Exception.class)
    public Object updateCertRep(String actionKey, JSONObject jsonObject) {
        try {
            Function<JSONObject, Object> processor = actionMap.getOrDefault(actionKey, this::updateNotsubmit);
            JgCertificateReplenish certRep = (JgCertificateReplenish) processor.apply(jsonObject);
            // 更新历史数据
            this.saveOrUpdateHisDataBatch(jsonObject, certRep.getSequenceNbr().toString());
            return Collections.singletonList(certRep);
        } 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();
        }
    }

    public void accept(String actionKey, JSONObject model) {
        JgCertificateReplenishDto certRepDto = JSONObject.parseObject(model.toJSONString(), JgCertificateReplenishDto.class);
        String instanceId = certRepDto.getInstanceId();
        String nextTaskId = certRepDto.getNextTaskId();
        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);
            Function<JSONObject, Object> processor = actionMap.getOrDefault(actionKey, this::rejected);
            JgCertificateReplenish certRep = (JgCertificateReplenish) processor.apply(model);
            commonService.saveExecuteFlowData2Redis(instanceId, this.buildInstanceRuntimeData(certRep));
            this.saveOrUpdateHisDataBatch(model, certRep.getSequenceNbr().toString());
            this.delRepeatUseEquipData(certRep.getSequenceNbr(), certRep.getApplyStatus(), certRep.getUseUnitCode());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }

    }

    public Object draft(JSONObject jsonObj) {
        Long sequenceNbr = sequence.nextId();
        JSONArray equLists = jsonObj.getJSONArray(EQU_LISTS);
        this.saveCertRepEqs(sequenceNbr, equLists);
        JgCertificateReplenish certRep = this.buildCertRep(sequenceNbr, jsonObj, new WorkflowResultDto(), FlowStatusEnum.TO_BE_SUBMITTED);
        certRep.setApplicationFormFileUrl(Objects.toString(this.getCertReplenishFormUrl(jsonObj, certRep.getApplyNo()).get(APPLICATION_FORM_FILE_URL)));
        this.save(certRep);
        this.createNewTodo(certRep, new WorkflowResultDto(), new TaskV2Model(), FlowStatusEnum.TO_BE_SUBMITTED);
        return certRep;
    }

    public void saveOrUpdateHisDataBatch(JSONObject jsonObj, String sequenceNbr) {
        jsonObj.put(SAFETY_MANAGER_NAME, jsonObj.getString(SAFETY_MANAGER_ID).split("_")[1]);
        commonService.saveOrUpdateHistory(BusinessTypeEnum.JG_REPLACEMENT_REGISTRATION.getName(), jsonObj, null, sequenceNbr);
    }

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

    public JgCertificateReplenish buildCertRep(Long sequenceNbr, JSONObject jsonObj, WorkflowResultDto workflowResultDto, FlowStatusEnum flowStatusEnum) {
        CompanyBo company = getSelectedOrgInfo().getCompany();
        AgencyUserModel userModel = getSelectedOrgInfo().getUserModel();
        boolean isCompany = company.getLevel().equals(BaseController.COMPANY_TYPE_COMPANY);
        String useUnitCode = "";
        String useUnitName = "";
        if (isCompany) {
            useUnitCode = CompanyTypeEnum.INDIVIDUAL.getName().equals(company.getCompanyType()) ? company.getCompanyCode().split("_")[1] : company.getCompanyCode();
            useUnitName = CompanyTypeEnum.INDIVIDUAL.getName().equals(company.getCompanyType()) ? company.getCompanyName().split("_")[1] : company.getCompanyName();
        }
        JgCertificateReplenishDto dto = JSON.parseObject(JSONObject.toJSONString(jsonObj), JgCertificateReplenishDto.class);
        Date date = new Date();
        String[] receiveOrg = Objects.toString(jsonObj.get(RECEIVE_ORG_CODE)).split("_");
        String[] safetyManager = Objects.toString(jsonObj.get(SAFETY_MANAGER_ID)).split("_");
        JgCertificateReplenish certRep = new JgCertificateReplenish();
        BeanUtil.copyProperties(dto, certRep);
        certRep.setSequenceNbr(sequenceNbr);
        this.setEquClassification(certRep);
        certRep.setApplyNo(dto.getApplyNo());
        certRep.setApplyDate(date);
        certRep.setLossDamageTime(dto.getLossDamageTime());
        certRep.setInstanceId(workflowResultDto.getInstanceId());
        certRep.setNextTaskId(workflowResultDto.getNextTaskId());
        certRep.setPromoter(RequestContext.getExeUserId());
        certRep.setNextExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
        certRep.setNextExecuteIds(String.join(",", workflowResultDto.getNextExecutorRoleIds()));
        certRep.setApplyStatus(Objects.toString(flowStatusEnum.getCode()));
        certRep.setReceiveOrgCode(receiveOrg[0]);
        certRep.setReceiveOrgName(receiveOrg[1]);
        certRep.setUseUnitCode(useUnitCode);
        certRep.setUseUnitName(useUnitName);
        Optional.ofNullable(jsonObj.get(APPLICATION_FORM_FILE)).ifPresent(x -> certRep.setApplicationFormFile(JSONObject.toJSONString(x)));
        Optional.ofNullable(jsonObj.get(OTHER_ACCESSORIES)).ifPresent(x -> certRep.setOtherAccessories(JSONObject.toJSONString(x)));
        certRep.setSafetyManagerName(safetyManager[1]);
        certRep.setIsDelete(Boolean.FALSE);
        certRep.setCreateDate(date);
        certRep.setRecDate(date);
        certRep.setCreateUserId(userModel.getUserId());
        certRep.setCreateUserName(userModel.getRealName());
        return certRep;
    }

    public void saveCertRepEqs(Long sequenceNbr, JSONArray equLists) {
        ArrayList<JgCertificateReplenishEq> replenishEqs = new ArrayList<>();
        equLists.forEach(equ -> {
            JSONObject equObj = JSONObject.parseObject(JSON.toJSONString(equ));
            JgCertificateReplenishEq certRepEq = new JgCertificateReplenishEq();
            certRepEq.setSequenceNbr(sequence.nextId());
            certRepEq.setCertificateReplenishId(sequenceNbr.toString());
            certRepEq.setEquId(equObj.getString(record));
            replenishEqs.add(certRepEq);
        });
        certificateReplenishEqService.saveBatch(replenishEqs);
    }

    private void setEquClassification(JgCertificateReplenish certRep) {
        String equListCode = certRep.getEquListCode();
        String equCategoryCode = certRep.getEquCategoryCode();
        Optional.ofNullable(equListCode).ifPresent(code -> certRep.setEquList(equipmentCategoryMapper.selectOne(new LambdaQueryWrapper<EquipmentCategory>().eq(EquipmentCategory::getCode, code)).getName()));
        Optional.ofNullable(equCategoryCode).ifPresent(code -> certRep.setEquCategory(equipmentCategoryMapper.selectOne(new LambdaQueryWrapper<EquipmentCategory>().eq(EquipmentCategory::getCode, code)).getName()));
    }

    public Object submitted(JSONObject jsonObj) {
        Long sequenceNbr = sequence.nextId();
        JgCertificateReplenishDto model = JSON.parseObject(JSONObject.toJSONString(jsonObj), JgCertificateReplenishDto.class);
        // 校验设备在流程中
        CompanyBo company = getSelectedOrgInfo().getCompany();
        model.getEquLists().forEach(device -> EquipUsedCheckStrategyContext.getUsedStrategy(EQUIP_TRANSFER_PROCESS_KEY).equipRepeatUsedCheck(String.valueOf(device.get(SEQUENCE_NBR)), CompanyTypeEnum.INDIVIDUAL.getName().equals(company.getCompanyType()) ? company.getCompanyCode().split("_")[1] : company.getCompanyCode()));
        // 启动工作流
        List<WorkflowResultDto> workflowResultList = this.startWorkFlow(model.getReceiveOrgCode().split("_")[0], model.getApplyNo());
        WorkflowResultDto workflowResultDto = workflowResultList.get(0);
        JgCertificateReplenish certRep = this.buildCertRep(sequenceNbr, jsonObj, workflowResultDto, FlowStatusEnum.TO_BE_PROCESSED);
        commonService.saveExecuteFlowData2Redis(workflowResultDto.getInstanceId(), buildInstanceRuntimeData(certRep));
        // 代办
        this.buildTask(certRep, workflowResultList);
        certRep.setApplicationFormFileUrl(Objects.toString(this.getCertReplenishFormUrl(jsonObj, certRep.getApplyNo()).get(APPLICATION_FORM_FILE_URL)));
        this.save(certRep);
        this.saveCertRepEqs(certRep.getSequenceNbr(), jsonObj.getJSONArray(EQU_LISTS));
        return certRep;
    }

    public Object rejected(JSONObject jsonObj) {
        JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(jsonObj));
        JgCertificateReplenish certRep = this.baseMapper.selectById(Objects.toString(jsonObject.get("sequenceNbr")));
        certRep.setProcessAdvice(jsonObject.getString(PROCESS_ADVICE));
        TaskResultDTO workDto = new TaskResultDTO();
        workDto.setResultCode(APPROVAL_STATUS);
        workDto.setTaskId(certRep.getNextTaskId());
        HashMap<String, Object> commMap = new HashMap<>();
        if (certRep.getApplyStatus().equals("6614") || certRep.getApplyStatus().equals("6615")) {
            commMap.put(APPROVAL_STATUS, "提交");
        } else {
            commMap.put(APPROVAL_STATUS, 1);
        }
        workDto.setNextExecuteUserCompanyCode(certRep.getUseUnitCode());
        workDto.setVariable(commMap);
        workDto.setComment(certRep.getProcessAdvice());
        ProcessTaskDTO processTaskDTO = cmWorkflowService.completeOrReject(certRep.getNextTaskId(), workDto, "1");
        // 提取节点等信息
        WorkflowResultDto workflowResultDto = commonService.buildWorkFlowInfo(Collections.singletonList(processTaskDTO)).get(0);
        certRep.setPromoter("");
        certRep.setApplyStatus(String.valueOf(FlowStatusEnum.REJECTED.getCode()));
        certRep.setNextTaskId(workflowResultDto.getNextTaskId());
        certRep.setNextExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
        // 上个代办改为驳回
        TaskV2Model taskV2Model = this.updateLastTodo(certRep, FlowStatusEnum.REJECTED);
        this.createNewTodo(certRep, workflowResultDto, taskV2Model, FlowStatusEnum.REJECTED);
        return this.updateById(certRep) ? certRep : null;
    }

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

    public Object approved(JSONObject jsonObj) {
        // 获取当前日期（不包含时间）
        LocalDate today = LocalDate.now();
        JgCertificateReplenish certRep = this.baseMapper.selectById(Objects.toString(jsonObj.get("sequenceNbr")));
        certRep.setProcessAdvice(jsonObj.getString(PROCESS_ADVICE));
        TaskResultDTO workDto = new TaskResultDTO();
        workDto.setResultCode(APPROVAL_STATUS);
        workDto.setTaskId(certRep.getNextTaskId());
        HashMap<String, Object> commMap = new HashMap<>();
        if (certRep.getApplyStatus().equals("6614") || certRep.getApplyStatus().equals("6615")) {
            commMap.put(APPROVAL_STATUS, "提交");
        } else {
            commMap.put(APPROVAL_STATUS, 0);
        }
        workDto.setNextExecuteUserCompanyCode(certRep.getReceiveOrgCode());
        workDto.setVariable(commMap);
        workDto.setComment(certRep.getProcessAdvice());
        ProcessTaskDTO processTaskDTO = cmWorkflowService.completeOrReject(certRep.getNextTaskId(), workDto, "0");
        // 提取节点等信息
        WorkflowResultDto workflowResultDto = commonService.buildWorkFlowInfo(Collections.singletonList(processTaskDTO)).get(0);
        certRep.setPromoter(getSelectedOrgInfo().getUserModel().getUserId());
        certRep.setProcessAdvice(certRep.getProcessAdvice());
        TaskV2Model taskV2Model = new TaskV2Model();
        if (StringUtils.isEmpty(workflowResultDto.getNextExecutorRoleIds())) {
            certRep.setApplyStatus(String.valueOf(FlowStatusEnum.TO_BE_FINISHED.getCode()));
            certRep.setPromoter("");
            certRep.setNextTaskId(null);
            // 上个代办改为已办
            taskV2Model = this.updateLastTodo(certRep, FlowStatusEnum.TO_BE_FINISHED);
            this.createResume(certRep, taskV2Model.getRoutePath());
        } else {
            certRep.setNextExecuteIds(workflowResultDto.getNextExecutorRoleIds());
            certRep.setPromoter(RequestContext.getExeUserId());
            certRep.setApplyStatus(String.valueOf(FlowStatusEnum.TO_BE_PROCESSED.getCode()));
            certRep.setNextTaskId(workflowResultDto.getNextTaskId());
            certRep.setInstanceId(workflowResultDto.getInstanceId());
            // 上个代办改为已办
            taskV2Model = this.updateLastTodo(certRep, FlowStatusEnum.TO_BE_FINISHED);
            // 创建新的代办
            this.createNewTodo(certRep, workflowResultDto, taskV2Model, FlowStatusEnum.TO_BE_PROCESSED);
        }
        certRep.setNextTaskId("");
        certRep.setAcceptDate(Date.from(today.atStartOfDay(ZoneId.systemDefault()).toInstant()));
        certRep.setReissueDate(Date.from(today.atStartOfDay(ZoneId.systemDefault()).toInstant()));
        this.updateManageWithPass(certRep);
        this.saveManageRecord(certRep,taskV2Model);
        return this.updateById(certRep) ? certRep : null;
    }

    private void createResume(JgCertificateReplenish certificateReplenish, String routePath) {
        List<JgCertificateReplenishEq> replenishEqs = certificateReplenishEqService.getBaseMapper().selectList(new LambdaQueryWrapper<JgCertificateReplenishEq>()
                .eq(JgCertificateReplenishEq::getCertificateReplenishId, certificateReplenish.getSequenceNbr()));
        jgResumeInfoService.saveBatchResume(replenishEqs.stream().map(eq-> JgResumeInfoDto.builder().applyNo(certificateReplenish.getApplyNo())
                .businessType(BusinessTypeEnum.JG_REPLACEMENT_REGISTRATION.getName())
                .businessId(String.valueOf(certificateReplenish.getSequenceNbr()))
                .equId(eq.getEquId())
                .approvalUnit(certificateReplenish.getReceiveOrgName())
                .approvalUnitCode(certificateReplenish.getReceiveOrgCode())
                .status("正常")
                .changeContent(BusinessTypeEnum.JG_REPLACEMENT_REGISTRATION.getName() + "业务办理")
                .routePath(routePath)
                .build()).collect(Collectors.toList())
        );
    }

    public void saveManageRecord(JgCertificateReplenish certRep, TaskV2Model taskV2Model) {
        Long certChangeRecordSeq = sequence.nextId();
        JgCertificateChangeRecord changeRecord = new JgCertificateChangeRecord()
                .setApplyNo(certRep.getApplyNo())
                .setReceiveOrgName(certRep.getReceiveOrgName())
                .setAuditPassDate(certRep.getAcceptDate())
                .setRegType(BusinessTypeEnum.JG_REPLACEMENT_REGISTRATION.getName())
                .setRegDate(certRep.getCreateDate())
                .setChangeContent(this.buildVoidRecordContent(certRep))// 变更内容
                .setUseRegistrationCode(certRep.getUseRegistrationCode())// 使用登记编号
                .setReceiveCompanyCode(certRep.getReceiveOrgCode())// 接收机构公司代码
                .setUseUnitCreditCode(certRep.getUseUnitCode())// 使用单位统一信用代码
                .setUseUnitName(certRep.getUseUnitName())// 使用单位名称
                .setCreateDate(new Date())
                .setRoutePath(taskV2Model.getRoutePath())
                .setEquCategory(certRep.getEquCategoryCode());
        changeRecord.setSequenceNbr(certChangeRecordSeq);
        certificateChangeRecordService.save(changeRecord);
        List<JgCertificateReplenishEq> replenishEqs = certificateReplenishEqService.getBaseMapper().selectList(new LambdaQueryWrapper<JgCertificateReplenishEq>()
                .eq(JgCertificateReplenishEq::getCertificateReplenishId, certRep.getSequenceNbr()));
        replenishEqs.forEach(eq -> {
            IdxBizJgFactoryInfo factoryInfo = idxBizJgFactoryInfoService.getOne(new LambdaQueryWrapper<IdxBizJgFactoryInfo>().eq(IdxBizJgFactoryInfo::getRecord, eq.getEquId()));
            JgCertificateChangeRecordEq changeRecordEq = new JgCertificateChangeRecordEq()
                    .setChangeRecordId(String.valueOf(certChangeRecordSeq))// 登记证记录主键
                    .setEquId(eq.getEquId())// 设备主键
                    .setProductCode(factoryInfo.getFactoryNum());
            certificateChangeRecordEqService.save(changeRecordEq);
        });
    }

    /**
     * 证变更内容
     *
     * @param obj JgCertificateReplenish
     * @return result
     */
    private String buildVoidRecordContent(JgCertificateReplenish obj) {
        // xxx单位的xx 办理了【补证登记】 ，单号【BZDJ202407050001】，申请日期2024-07-05
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日");
        return obj.getUseUnitName() + "的" + obj.getCreateUserName() + "办理了【" + BusinessTypeEnum.JG_REPLACEMENT_REGISTRATION.getName() + "】，" +
                "单号【" + obj.getApplyNo() + "】，申请日期" + simpleDateFormat.format(obj.getRecDate());
    }

    public void updateManageWithPass(JgCertificateReplenish certRep) {
        registrationManageService.update(new LambdaUpdateWrapper<JgUseRegistrationManage>()
                .eq(JgUseRegistrationManage::getUseRegistrationCode, certRep.getUseRegistrationCode())
                .set(JgUseRegistrationManage::getReceiveCompanyCode, certRep.getReceiveOrgCode())
                .set(JgUseRegistrationManage::getReceiveOrgName, certRep.getReceiveOrgName())
                .set(JgUseRegistrationManage::getReissueDate, certRep.getReissueDate()));
    }

    /**
     * 上个代办改为已办
     *
     * @param certRep
     * @return 代办信息
     */
    private TaskV2Model updateLastTodo(JgCertificateReplenish certRep, FlowStatusEnum statusEnum) {
        return commonService.updateTaskModel(MapBuilder.<String, Object>create()
                .put("taskStatus", statusEnum.getCode())
                .put("taskStatusLabel", statusEnum.getName())
                .put("flowStatus", statusEnum.getCode())
                .put("flowStatusLabel", statusEnum.getName())
                .put("relationId", certRep.getInstanceId())
                .put("model", certRep)
                .build());
    }

    /**
     * 创建新代办
     */
    private void createNewTodo(JgCertificateReplenish certRep, WorkflowResultDto workflowResultDto, TaskV2Model taskV2Model, FlowStatusEnum statusEnum) {
        TaskMessageDto taskMessageDto = new TaskMessageDto();
        BeanUtil.copyProperties(certRep, taskMessageDto);

        TaskModelDto taskModelDto = TaskModelDto.builder()
                .flowCreateDate(taskV2Model.getFlowCreateDate())
                .taskName(workflowResultDto.getNextTaskName())
                .taskCode(taskV2Model.getTaskCode())
                .taskType(BusinessTypeEnum.JG_REPLACEMENT_REGISTRATION.getCode())
                .taskTypeLabel(BusinessTypeEnum.JG_REPLACEMENT_REGISTRATION.getName())
                .relationId(Objects.isNull(certRep.getInstanceId()) ? Objects.toString(certRep.getSequenceNbr()) : certRep.getInstanceId())
                .executeUserIds(workflowResultDto.getNextExecutorUserIds())
                .taskStatusLabel(statusEnum.getName()).flowStatus(statusEnum.getCode())
                .flowCode(workflowResultDto.getNextTaskId())
                .flowStatusLabel(statusEnum.getName())
                .taskContent(String.format("来自%s的业务办理，【申请单号：%s】", certRep.getEquList(), certRep.getApplyNo()))
                .taskDesc("")
                .startUserId(taskV2Model.getStartUserId())
                .startUserCompanyName(certRep.getUseUnitName())
                .startUser(taskV2Model.getStartUser())
                .startDate(taskV2Model.getStartDate())
                .pageType(statusEnum.getCode() == 6614 ? "edit" : "look")
                .model(taskMessageDto)
                .nextExecuteUser(workflowResultDto.getNextExecutorRoleIds())
                .build();
        commonService.buildTaskModel(Collections.singletonList(taskModelDto));
    }

    /**
     * 启动工作流
     *
     * @return 工作流信息
     */
    private List<WorkflowResultDto> startWorkFlow(String receiveOrgCode, String applyNo) {
        ActWorkflowBatchDTO actWorkflowBatchDTO = new ActWorkflowBatchDTO();
        ActWorkflowStartDTO workflowStartDTO = new ActWorkflowStartDTO();
        workflowStartDTO.setProcessDefinitionKey(EQUIP_TRANSFER_PROCESS_KEY);
        workflowStartDTO.setBusinessKey(applyNo);
        workflowStartDTO.setCompleteFirstTask(Boolean.TRUE);
        workflowStartDTO.setNextExecuteUserCompanyCode(receiveOrgCode);
        actWorkflowBatchDTO.setProcess(Collections.singletonList(workflowStartDTO));
        List<ProcessTaskDTO> processTaskDTOS = cmWorkflowService.startBatch(actWorkflowBatchDTO);
        return commonService.buildWorkFlowInfo(processTaskDTOS);
    }

    /**
     * 插入代办
     */
    private void buildTask(JgCertificateReplenish certRep, List<WorkflowResultDto> workflowResultList) {
        if (BeanUtil.isEmpty(certRep) || CollectionUtils.isEmpty(workflowResultList)) {
            return;
        }
        List<TaskModelDto> taskModelList = new ArrayList<>();
        TaskModelDto taskModelDto = this.buildTaskModelDto(certRep, workflowResultList.get(0));
        taskModelList.add(taskModelDto);
        commonService.buildTaskModel(taskModelList);
    }


    /**
     * 组装代办消息
     *
     * @param certRep           单据信息
     * @param workflowResultDto 工作流返回信息
     * @return 代办信息
     */
    private TaskModelDto buildTaskModelDto(JgCertificateReplenish certRep, WorkflowResultDto workflowResultDto) {
        TaskMessageDto taskMessageDto = new TaskMessageDto();
        BeanUtil.copyProperties(certRep, taskMessageDto);
        return TaskModelDto.builder()
                .flowCreateDate(certRep.getCreateDate())
                .startUserId(certRep.getCreateUserId())
                .taskName(workflowResultDto.getNextTaskName())
                .taskCode(certRep.getApplyNo())
                .taskType(BusinessTypeEnum.JG_REPLACEMENT_REGISTRATION.getCode())
                .taskTypeLabel(BusinessTypeEnum.JG_REPLACEMENT_REGISTRATION.getName())
                .relationId(workflowResultDto.getInstanceId())
                .executeUserIds(workflowResultDto.getNextExecutorUserIds())
                .taskStatus(FlowStatusEnum.TO_BE_PROCESSED.getCode())
                .taskStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName())
                .flowStatus(FlowStatusEnum.TO_BE_PROCESSED.getCode())
                .flowCode(workflowResultDto.getNextTaskId())
                .flowStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName())
                .taskContent(String.format("来自%s的业务办理，【申请单号：%s】", certRep.getEquList(), certRep.getApplyNo()))
                .taskDesc("")
                .startUser(certRep.getCreateUserName())
                .startUserCompanyName(certRep.getUseUnitName())
                .startDate(certRep.getCreateDate())
                .model(taskMessageDto)
                .nextExecuteUser(certRep.getNextExecuteIds())
                .build();

    }

    /**
     * 分页查询
     */
    public Page<JgCertificateReplenish> queryForJgCertificateReplenishPage(Page<JgCertificateReplenish> page, JgCertificateReplenishDto dto, String sort, String client) {
        ReginParams reginParams = getSelectedOrgInfo();
        CompanyBo company = reginParams.getCompany();
        String companyCode = company.getCompanyCode();
        String orgCode = "jgLook".equals(client) ? reginParams.getCompany().getOrgCode() : null;
        String type = "jgLook".equals(client) ? null : company.getLevel().equals(BaseController.COMPANY_TYPE_COMPANY) ? "enterprise" : "supervision";
        SortVo sortMap = commonService.sortFieldConversion(sort);
        if("enterprise".equals(type)){
            String useUnitCode = CompanyTypeEnum.INDIVIDUAL.getName().equals(company.getCompanyType()) ? company.getCompanyCode().split("_")[1] : company.getCompanyCode();
            dto.setUseUnitCode(useUnitCode);
        }
        Page<JgCertificateReplenish> replenishIPage = jgCertificateReplenishMapper.queryForPage(page, sortMap, dto, type, companyCode, orgCode);
        Page<JgCertificateReplenish> result = new Page<>();
        result.setRecords(replenishIPage.getRecords().stream().peek(item -> {
            item.setApplyStatusDes(FlowStatusEnum.getNameByType(Long.parseLong(item.getApplyStatus())));
            item.setIsCompany(company.getLevel().equals(BaseController.COMPANY_TYPE_COMPANY));
            item.setApplicationReason("0".equals(item.getApplicationReason()) ? "遗失" : "损毁");
        }).collect(Collectors.toList()));
        result.setTotal(replenishIPage.getTotal());
        return result;
    }

    /**
     * 补证申请表生成
     *
     * @param jsonObject
     * @return
     */
    @Override
    public Map<String, Object> getCertReplenishFormUrl(JSONObject jsonObject, String applyNo) {
        if (StringUtils.isEmpty(applyNo)) {
            ResponseModel<List<String>> listResponseModel = tzsServiceFeignClient.applicationFormCode(ApplicationFormTypeEnum.BZDJ.getCode(), 1);
            if (!listResponseModel.getResult().isEmpty()) {
                applyNo = listResponseModel.getResult().get(0);
            }
        }
        JSONObject formData = this.writeCertReplenishFormData(jsonObject, applyNo);
        String wordPath = "CertificateReplenish.ftl";
        String fileName = "使用登记证补证申请表_";
        File pdfFile = null;
        try {
            pdfFile = commonService.wordToPdf(fileName, wordPath, formData);
            return MapBuilder.<String, Object>create().put(APPLICATION_FORM_FILE_URL, commonService.uploadFile(pdfFile, "certificateReplenishFiles")).put("applyNo", applyNo).build();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            try {
                assert pdfFile != null;
                Files.deleteIfExists(pdfFile.toPath());
            } catch (Exception e) {
                log.error("文件找不到，删除失败：{}", e);
            }
        }
    }

    /**
     * 补证pdf流生成
     *
     * @param jsonObject
     * @param response
     */
    @Override
    public void getCertReplenishFormStream(JSONObject jsonObject, HttpServletResponse response) {
        JSONObject jsonObj = jsonObject.getJSONObject(FORM_DATA);
        JSONObject formData = this.writeCertReplenishFormData(jsonObj, jsonObj.getString(APPLY_NO));
        String wordPath = "CertificateReplenish.ftl";
        String fileName = "使用登记证补证申请表_";
        File pdfFile;
        try {
            pdfFile = commonService.wordToPdf(fileName, wordPath, formData);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        try {
            byte[] bytes = CommonServiceImpl.file2byte(pdfFile);
            String docTitle = pdfFile.getName();
            FileExporter.exportFile(FileExporter.FileType.valueOf("pdf"), docTitle, bytes, response);
        } catch (Exception e) {
            log.error("pdf文件转换失败：{}", e);
        } finally {
            try {
                Files.deleteIfExists(pdfFile.toPath());
            } catch (Exception e) {
                log.error("文件找不到，删除失败：{}", e);
            }
        }
    }

    private JSONObject writeCertReplenishFormData(JSONObject jsonObject, String applyNo) {
        JSONArray equLists = jsonObject.getJSONArray(EQU_LISTS);
        JSONObject result = new JSONObject();
        result.put("applyNo", applyNo);
        result.put("useUnitName", jsonObject.getString("useUnitName"));
        result.put("manageType", Objects.toString(jsonObject.get(manageType),"set"));
        result.put("whetherVehicleCylinder", Objects.toString(jsonObject.get(whetherVehicleCylinder),"0"));
        result.put("equCategoryCode", jsonObject.getString("equCategoryCode"));
        result.put("equUseAddress", jsonObject.getString("equUseAddress"));
        result.put("applicationReason", jsonObject.getString("applicationReason"));
        result.put("lossDamageTime", jsonObject.getString("lossDamageTime").substring(0, 10));
        result.put("safetyManagerName", jsonObject.getString("safetyManagerId").split("_")[1]);
        result.put("safetyManagerPhone", jsonObject.getString("safetyManagerPhone"));
        JSONArray equListsAfterAssembly = new JSONArray();
        for (int i = 0; i < equLists.size(); i++) {
            JSONObject item = equLists.getJSONObject(i);
            equListsAfterAssembly.add(MapBuilder.<String, Object>create().put("index", i + 1).put("productName", item.getString("PRODUCT_NAME")).put("equCode", item.getString("EQU_CODE")).put("useRegistrationCode", item.getString("USE_ORG_CODE")).put("factoryNum", item.getString("FACTORY_NUM")).build());
        }
        result.put(EQU_LISTS, equListsAfterAssembly);
        result.put("handler", getSelectedOrgInfo().getUserModel().getRealName());
        result.put("applicationDateYear", LocalDate.now().getYear());
        result.put("applicationDateMonth", LocalDate.now().getMonthValue());
        result.put("applicationDateDay", LocalDate.now().getDayOfMonth());
        return result;
    }

    /**
     * 根据证的sequenceNbr 批量查询证下面的所有设备
     *
     * @param sequenceNbr
     * @return
     */
    public Map<String, Object> queryEquByCertSeq(String sequenceNbr) {
        JgUseRegistrationManage registrationManage = registrationManageService.getBaseMapper()
                .selectOne(new LambdaQueryWrapper<JgUseRegistrationManage>()
                        .eq(JgUseRegistrationManage::getSequenceNbr, sequenceNbr)
                        .eq(JgUseRegistrationManage::getIsDelete, 0)
                        .select(JgUseRegistrationManage::getUseRegistrationCode,JgUseRegistrationManage::getUseUnitAddress,
                                JgUseRegistrationManage::getEquUseAddress,JgUseRegistrationManage::getManageType));
        HashMap<String, Object> result = new HashMap<>();
        if (ValidationUtil.isEmpty(registrationManage)) {
            return result;
        }
        List<JSONObject> list = queryEquByCert(registrationManage.getUseRegistrationCode());
        result.put(EQU_LISTS, list);
        result.put("whetherVehicleCylinder", list.stream().findFirst().map(j -> j.get(whetherVehicleCylinder))
                .orElse("0"));
        result.put(useRegistrationCode, registrationManage.getUseRegistrationCode());
        result.put(manageType, registrationManage.getManageType());
        result.put(equUseAddress, "unit".equals(registrationManage.getManageType())
                        ? registrationManage.getUseUnitAddress() : registrationManage.getEquUseAddress());
        return result;
    }

    private List<JSONObject> queryEquByCert(String useRegistrationCode) {
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(USE_ORG_CODE, useRegistrationCode);
        boolQuery.must(termQueryBuilder);
        BoolQueryBuilder meBuilder = QueryBuilders.boolQuery();
        meBuilder.should(QueryBuilders.matchQuery(STATUS, "已认领"));
        meBuilder.should(QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery(STATUS)));
        meBuilder.should(QueryBuilders.boolQuery().must(QueryBuilders.matchPhraseQuery(STATUS, "")));
        meBuilder.minimumShouldMatch(1);
        boolQuery.must(meBuilder);
        List<JSONObject> equipmentLists = Collections.emptyList();
        try {
            equipmentLists = registrationManageService.searchResponse(IDX_BIZ_VIEW_JG_ALL, boolQuery, hit -> JSONObject.parseObject(hit.getSourceAsString(), JSONObject.class)).stream().map(item -> {
                JSONObject newItem = new JSONObject(item);
                newItem.put(record, Objects.toString(newItem.get(SEQUENCE_NBR), ""));
                return newItem;
            }).collect(Collectors.toList());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return equipmentLists;
    }

    /**
     * 撤回
     *
     * @param dto
     */
    @GlobalTransactional(rollbackFor = Exception.class)
    public void cancel(JgCertificateReplenishDto dto) {
        String instanceId = dto.getInstanceId();
        String nextTaskId = dto.getNextTaskId();
        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);
            JgCertificateReplenish certRep = baseMapper.selectById(dto.getSequenceNbr());
            // 回滚工作流
            ProcessTaskDTO processTaskDTO = cmWorkflowService.rollBack(instanceId);
            WorkflowResultDto workflowResultDto = commonService.buildWorkFlowInfo(Collections.singletonList(processTaskDTO)).get(0);
            certRep.setPromoter("");
            certRep.setNextExecuteIds(workflowResultDto.getNextExecutorRoleIds());
            certRep.setNextExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
            certRep.setApplyStatus(String.valueOf(FlowStatusEnum.ROLLBACK.getCode()));
            certRep.setNextTaskId(workflowResultDto.getNextTaskId());
            baseMapper.updateById(certRep);
            JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(certRep));
            jsonObject.put("nextExecuteUser", certRep.getNextExecuteIds());
            jsonObject.put("taskType", BusinessTypeEnum.JG_REPLACEMENT_REGISTRATION.getCode());
            jsonObject.put("taskTypeLabel", BusinessTypeEnum.JG_REPLACEMENT_REGISTRATION.getName());
            jsonObject.put("flowStatus", FlowStatusEnum.ROLLBACK.getCode());
            jsonObject.put("flowStatusLabel", FlowStatusEnum.ROLLBACK.getName());
            commonService.rollbackTask(certRep.getInstanceId(), jsonObject);
            commonService.saveExecuteFlowData2Redis(instanceId, this.buildInstanceRuntimeData(certRep));
            this.delRepeatUseEquipData(certRep.getSequenceNbr(), certRep.getApplyStatus(), certRep.getUseUnitCode());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    /**
     * 删除redis校验重复引用设备的数据
     */
    private void delRepeatUseEquipData(Long id, String status, String companyCode) {
        List<JgCertificateReplenishEq> list = certificateReplenishEqService.lambdaQuery().eq(JgCertificateReplenishEq::getCertificateReplenishId, id).list();
        // 获取单位变更设备列表
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        List<String> records = list.stream().map(JgCertificateReplenishEq::getEquId).collect(Collectors.toList());
        if (NOT_FLOWING_STATE.contains(status)) {
            EquipUsedCheckStrategyContext.getUsedStrategy(EQUIP_TRANSFER_PROCESS_KEY).delDataForCheckEquipRepeatUsed(records, companyCode);
        }
    }

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

    public Map<String, Object> queryBySequenceNbr(Long sequenceNbr) {
        JgCertificateReplenish certRep = baseMapper.selectById(sequenceNbr);
        CompanyBo company = getSelectedOrgInfo().getCompany();
        boolean isCompany = company.getLevel().equals(BaseController.COMPANY_TYPE_COMPANY);
        if (FlowStatusEnum.TO_BE_FINISHED.getCode() == Integer.parseInt(certRep.getApplyStatus())) {
            // 已完成状态显示历史数据
            JSONObject jsonObject = commonService.queryHistoryData(sequenceNbr);
            jsonObject.put(IS_COMPANY, isCompany);
            jsonObject.put(APPLY_STATUS, FlowStatusEnum.TO_BE_FINISHED.getCode());
            ATTACHMENT_FIELD.forEach(item -> jsonObject.put(item, JSONObject.parse(jsonObject.getString(item))));
            jsonObject.put(APPLICATION_FORM_FILE_URL, certRep.getApplicationFormFileUrl());
            jsonObject.put(RECEIVE_ORG_CODE, certRep.getReceiveOrgCode());
            jsonObject.put(RECEIVE_ORG_NAME, certRep.getReceiveOrgName());
            return jsonObject;
        } else {
            ObjectMapper mapper = new ObjectMapper();
            Map<String, Object> result = mapper.convertValue(certRep, new TypeReference<Map<String, Object>>() {
            });
            result.put(EQU_LISTS, this.queryEquByCert(certRep.getUseRegistrationCode()));
            result.put(LOSS_DAMAGE_TIME, certRep.getLossDamageTime());
            JSONObject jsonObject = commonService.queryHistoryData(sequenceNbr);
            result.put(SAFETY_MANAGER_ID, jsonObject.get(SAFETY_MANAGER_ID));
            result.put(IS_COMPANY, isCompany);
            ATTACHMENT_FIELD.forEach(item -> result.put(item, JSONObject.parse(jsonObject.getString(item))));
            result.put(APPLICATION_FORM_FILE_URL, certRep.getApplicationFormFileUrl());
            return result;
        }
    }

    public Boolean removeCertRepBySequenceNbr(Long sequenceNbr) {
        JgCertificateReplenish certRep = this.baseMapper.selectById(sequenceNbr);
        commonService.deleteTaskModel(sequenceNbr.toString(), certRep.getInstanceId());
        this.getBaseMapper().update(null, new LambdaUpdateWrapper<JgCertificateReplenish>().eq(JgCertificateReplenish::getSequenceNbr, sequenceNbr).set(JgCertificateReplenish::getIsDelete, true));
        certificateReplenishEqService.getBaseMapper().update(null, new LambdaUpdateWrapper<JgCertificateReplenishEq>().eq(JgCertificateReplenishEq::getCertificateReplenishId, sequenceNbr).set(JgCertificateReplenishEq::getIsDelete, true));
        jgRegistrationHistoryService.getBaseMapper().update(null, new LambdaUpdateWrapper<JgRegistrationHistory>().eq(JgRegistrationHistory::getCurrentDocumentId, sequenceNbr).set(JgRegistrationHistory::getIsDelete, true));
        return Boolean.TRUE;
    }

    @GlobalTransactional(rollbackFor = Exception.class)
    public JgCertificateReplenish voidApplication(Long sequenceNbr, String cancelReason) {
        JgCertificateReplenish certRep = this.baseMapper.selectById(sequenceNbr);
        String oldApplyStatus = certRep.getApplyStatus();
        certRep.setApplyStatus(String.valueOf(FlowStatusEnum.TO_BE_DISCARD.getCode()));
        certRep.setCancelReason(cancelReason);
        certRep.setCancelDate(new Date());
        certRep.setCancelUserId(RequestContext.getExeUserId());
        certRep.setNextExecuteUserIds(null);
        certRep.setPromoter(null);
        this.updateById(certRep);
        this.processElseDataByStatus(Objects.requireNonNull(FlowStatusEnum.getEumByCode(Integer.parseInt(oldApplyStatus))), certRep);
        return certRep;
    }

    private void processElseDataByStatus(FlowStatusEnum oldApplyStatus, JgCertificateReplenish certRep) {
        switch (oldApplyStatus) {
            // 待提交
            case TO_BE_SUBMITTED:
                // 删除暂存时生成的待办
                commonService.deleteTaskModel(certRep.getSequenceNbr() + "", certRep.getInstanceId());
                break;
            // 已完成
            case TO_BE_FINISHED:
                // 1.删除写入到证管理表的补证日期
                this.deleteCertManageReissueDate(certRep);
                break;
            // 流程中（驳回、撤回等）
            default:
                // 删除待办
                commonService.deleteTaskModel(certRep.getSequenceNbr() + "", certRep.getInstanceId());
                // 清空redis
                this.delRepeatUseEquipData(certRep.getSequenceNbr(), certRep.getApplyStatus(), certRep.getUseUnitCode());
        }
    }

    private void deleteCertManageReissueDate(JgCertificateReplenish certRep) {
        registrationManageService.update(new LambdaUpdateWrapper<JgUseRegistrationManage>()
                .eq(JgUseRegistrationManage::getUseRegistrationCode, certRep.getUseRegistrationCode())
                .set(JgUseRegistrationManage::getReissueDate, null));
    }

}