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

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.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.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.utils.RedisKey;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.boot.module.jg.api.dto.*;
import com.yeejoin.amos.boot.module.jg.api.entity.*;
import com.yeejoin.amos.boot.module.jg.api.enums.BusinessTypeEnum;
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.biz.feign.TzsServiceFeignClient;
import com.yeejoin.amos.boot.module.jg.biz.service.ICommonService;
import com.yeejoin.amos.boot.module.ymt.api.entity.IdxBizJgOtherInfo;
import com.yeejoin.amos.boot.module.ymt.api.entity.IdxBizJgRegisterInfo;
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.IdxBizJgOtherInfoMapper;
import com.yeejoin.amos.feign.privilege.Privilege;
import com.yeejoin.amos.feign.privilege.model.CompanyModel;
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.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.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;

/**
 * 单位变更登记服务实现类
 *
 * @author system_generator
 * @date 2024-07-10
 */
@Service
public class JgChangeVehicleRegistrationUnitServiceImpl extends BaseService<JgChangeVehicleRegistrationUnitDto, JgChangeVehicleRegistrationUnit, JgChangeVehicleRegistrationUnitMapper> implements IJgChangeVehicleRegistrationUnitService {
    private static final String SUBMIT_TYPE_FLOW = "1";
    private static final String PROCESS_DEFINITION_KEY = "vehicleGasCylinderChange";
    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
    ICommonService commonService;
    @Autowired
    TzsServiceFeignClient tzsServiceFeignClient;
    @Autowired
    private JgUseRegistrationManageServiceImpl jgUseRegistrationManageService;
    @Autowired
    private JgVehicleInformationServiceImpl jgVehicleInformationService;
    @Autowired
    private JgChangeVehicleRegistrationUnitEqServiceImpl jgChangeVehicleRegistrationUnitEqService;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private JgCertificateChangeRecordServiceImpl jgCertificateChangeRecordService;
    @Autowired
    private JgCertificateChangeRecordEqServiceImpl jgCertificateChangeRecordEqService;
    @Autowired
    private IdxBizJgRegisterInfoServiceImpl idxBizJgRegisterInfoService;
    @Autowired
    private IdxBizJgOtherInfoMapper otherInfoMapper;

    public void changeData(JgChangeVehicleRegistrationUnit dto) {
        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())) {
            // 新使用单位
            String[] splitMaintenanceUnitCode = dto.getNewUseUnitCreditCode().split("_");
            dto.setNewUseUnitCreditCode(splitMaintenanceUnitCode[0]);
            dto.setNewUseUnitName(splitMaintenanceUnitCode[1]);
        }
        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) {
        JgChangeVehicleRegistrationUnit dto = new JgChangeVehicleRegistrationUnit();
        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);
            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);
            changeData(updateDto);
            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);
    }

    public Page<Map<String, Object>> getPage(Page<JgChangeVehicleRegistrationUnit> page, JgChangeVehicleRegistrationUnitDto dto, String type, ReginParams reginParams) {
        String orgCode = reginParams.getCompany().getCompanyCode();
        String currentUserId = reginParams.getUserModel().getUserId();
        return this.getBaseMapper().getPage(page, dto, type, orgCode, currentUserId, dto.getRoleIds());
    }

    @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);
            }
        } 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));
            JgRegistrationHistory jgRegistrationHistory = jgRegistrationHistoryService.getBaseMapper().selectOne(lambdaSelect);
            JSONObject historyData = JSONObject.parseObject(jgRegistrationHistory.getChangeData());
            // 更新代办
            TaskV2Model taskV2Model = updateAgency(jgChangeVehicleRegistrationUnit);
            // 修改设备信息、添加证、设备流水信息
            saveRecord(jgChangeVehicleRegistrationUnit, taskV2Model);

        }
        this.getBaseMapper().updateById(jgChangeVehicleRegistrationUnit);
        commonServiceImpl.saveExecuteFlowData2Redis(jgChangeVehicleRegistrationUnit.getInstanceId(), this.buildInstanceRuntimeData(jgChangeVehicleRegistrationUnit));
        return jgChangeVehicleRegistrationUnit;
    }

    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("USE_UNIT_NAME", jgChangeVehicleRegistrationUnit.getNewUseUnitName());
            param.put("USE_UNIT_CREDIT_CODE", jgChangeVehicleRegistrationUnit.getNewUseUnitCreditCode());
            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());
                }
            }
            objMap.put(item, param);
        });
        tzsServiceFeignClient.commonUpdateEsDataByIds(objMap);
    }

    public void saveRecord(JgChangeVehicleRegistrationUnit jgChangeVehicleRegistrationUnit, TaskV2Model taskV2Model) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        JgUseRegistrationManage manage = jgUseRegistrationManageService.lambdaQuery().eq(JgUseRegistrationManage::getUseRegistrationCode, jgChangeVehicleRegistrationUnit.getUseRegistCode()).one();
        // 业务流水生成
        JgRegistrationHistory jgRegistrationHistory = jgRegistrationHistoryService.lambdaQuery().eq(JgRegistrationHistory::getCurrentDocumentId, jgChangeVehicleRegistrationUnit.getSequenceNbr()).one();
        JSONObject jsonObject = JSONObject.parseObject(jgRegistrationHistory.getChangeData());
        JSONArray dataList = JSONObject.parseArray(jsonObject.get("dataList").toString());
        ArrayList<JgCertificateChangeRecordEq> jgCertificateChangeRecordEqs = new ArrayList<>();
        JgCertificateChangeRecord jgCertificateChangeRecord = new JgCertificateChangeRecord();
        jgCertificateChangeRecord.setApplyNo(jgChangeVehicleRegistrationUnit.getApplyNo());
        jgCertificateChangeRecord.setReceiveOrgName(jgChangeVehicleRegistrationUnit.getReceiveOrgName());
        jgCertificateChangeRecord.setAuditPassDate(new Date());
        jgCertificateChangeRecord.setRegType(BUSINESS_NAME);
        jgCertificateChangeRecord.setRegDate(jgChangeVehicleRegistrationUnit.getApplyDate());
        jgCertificateChangeRecord.setChangeContent(jgChangeVehicleRegistrationUnit.getCreateUserName() + "办理了【" + 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.setUseRegistrationCode(jgChangeVehicleRegistrationUnit.getUseRegistCode());
        jgCertificateChangeRecord.setCertificateNo(manage.getCertificateNo());
        jgCertificateChangeRecord.setUseUnitCreditCode(jgChangeVehicleRegistrationUnit.getNewUseUnitCreditCode());
        jgCertificateChangeRecord.setUseUnitName(jgChangeVehicleRegistrationUnit.getNewUseUnitName());
        jgCertificateChangeRecord.setEquCategory(manage.getEquCategory());
        jgCertificateChangeRecord.setReceiveCompanyCode(jgChangeVehicleRegistrationUnit.getReceiveCompanyCode());
        jgCertificateChangeRecord.setRoutePath(taskV2Model.getRoutePath());
        // 保存证流水信息
        jgCertificateChangeRecordService.save(jgCertificateChangeRecord);
        // 组装设备流水
        dataList.forEach(item -> {
            JSONObject object = JSONObject.parseObject(JSON.toJSONString(item));
            JgCertificateChangeRecordEq jgCertificateChangeRecordEq = new JgCertificateChangeRecordEq();
            jgCertificateChangeRecordEq.setEquId(object.get("record").toString());
            jgCertificateChangeRecordEq.setChangeRecordId(jgCertificateChangeRecord.getSequenceNbr().toString());
            jgCertificateChangeRecordEq.setProductCode(object.get("factoryNum").toString());
            jgCertificateChangeRecordEqs.add(jgCertificateChangeRecordEq);
        });
        // 保存设备流水信息
        jgCertificateChangeRecordEqService.saveBatch(jgCertificateChangeRecordEqs);

        List<String> collect = jgCertificateChangeRecordEqs.stream().map(JgCertificateChangeRecordEq::getEquId).collect(Collectors.toList());
        if ("0".equals(jgChangeVehicleRegistrationUnit.getChangeType()) && !ObjectUtils.isEmpty(collect)) {
            // 区外变更
            // 生成使用登记证编号
            String receiveCompanyCode = 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);
            // 更新设备使用登记证信息
            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);
        }
        // 区内变更
        if ("1".equals(jgChangeVehicleRegistrationUnit.getChangeType()) && !ObjectUtils.isEmpty(collect)) {
            updateEsData(collect, jgChangeVehicleRegistrationUnit, null);
        }
        // 修改证管理信息
        manage.setUseUnitName(jgChangeVehicleRegistrationUnit.getNewUseUnitName());
        manage.setAuditPassDate(new Date());
        jgUseRegistrationManageService.updateById(manage);
    }

    /**
     * 生成监管码
     */
    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));
        // 调用服务端获取注册码
        ResponseModel<String> stringResponseModel = tzsServiceFeignClient.useRegistrationCode(useRegistration);
        return stringResponseModel.getResult();
    }

    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.getUseUnitName());
        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);
        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.queryForJgUseRegistrationManagePage(page, dto, null);
    }

    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).one();
        List<JSONObject> jsonObjects = jgUseRegistrationManageService.queryEquByCertificateSeq(registrationManage.getSequenceNbr());
        if (!ObjectUtils.isEmpty(jsonObjects)) {
//            JgVehicleInformation information = jgVehicleInformationService.lambdaQuery().eq(JgVehicleInformation::getUseRegistrationCode, useRegistrationCode).one();
            List<String> records = jsonObjects.stream().map(a -> String.valueOf(a.get("SEQUENCE_NBR"))).collect(Collectors.toList());
            List<Map<String, Object>> equList = this.getBaseMapper().getEquList(records);
            equList.forEach(a -> {
                if (!ObjectUtils.isEmpty(registrationManage) && !ObjectUtils.isEmpty(registrationManage.getCarNumber())) {
                    a.put("carNumber", registrationManage.getCarNumber());
                }
            });
            map.put("dataList", equList);
            // 组件回显
            if (!ObjectUtils.isEmpty(registrationManage) && !ObjectUtils.isEmpty(registrationManage.getCarNumber())) {
                map.put("carNumber", registrationManage.getCarNumber());
            }
        }
        return map;
    }

    @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;
    }

    public Map<String, Object> getDetails(String sequenceNbr) {
        JgChangeVehicleRegistrationUnit registrationUnit = this.getById(sequenceNbr);
        JgRegistrationHistory history = jgRegistrationHistoryService.lambdaQuery().eq(JgRegistrationHistory::getCurrentDocumentId, sequenceNbr).eq(JgRegistrationHistory::getRegistrationClass, BUSINESS_NAME).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());
            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));
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }
}