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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapBuilder;
import cn.hutool.core.text.CharSequenceUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.entity.DataDictionary;
import com.yeejoin.amos.boot.biz.common.service.impl.DataDictionaryServiceImpl;
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.workflow.feign.WorkflowFeignService;
import com.yeejoin.amos.boot.module.common.api.dto.AttachmentDto;
import com.yeejoin.amos.boot.module.jyjc.api.entity.*;
import com.yeejoin.amos.boot.module.jyjc.api.enums.BizTypeEnum;
import com.yeejoin.amos.boot.module.jyjc.api.enums.DocumentEnum;
import com.yeejoin.amos.boot.module.jyjc.api.enums.ResultStatusEnum;
import com.yeejoin.amos.boot.module.jyjc.api.enums.ResultTypeEnum;
import com.yeejoin.amos.boot.module.jyjc.api.mapper.JyjcInspectionApplicationEquipMapper;
import com.yeejoin.amos.boot.module.jyjc.api.mapper.JyjcInspectionApplicationMapper;
import com.yeejoin.amos.boot.module.jyjc.api.model.*;
import com.yeejoin.amos.boot.module.jyjc.api.service.IJyjcInspectionApplicationService;
import com.yeejoin.amos.boot.module.jyjc.biz.event.InspectionApplicationPushEvent;
import com.yeejoin.amos.boot.module.jyjc.biz.event.publisher.EventPublisher;
import com.yeejoin.amos.boot.module.jyjc.biz.feign.JgFeignClient;
import com.yeejoin.amos.boot.module.jyjc.biz.feign.TzsServiceFeignClient;
import com.yeejoin.amos.boot.module.jyjc.biz.service.TaskModelServiceImpl;
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.component.feign.model.FeignClientResult;
import com.yeejoin.amos.feign.systemctl.model.TaskV2Model;
import com.yeejoin.amos.feign.workflow.Workflow;
import com.yeejoin.amos.feign.workflow.model.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import org.typroject.tyboot.core.foundation.exception.BaseException;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.rdbms.service.BaseService;

import java.util.*;
import java.util.stream.Collectors;


/**
 * 服务实现类
 *
 * @author system_generator
 * @date 2023-12-14
 */
@Service
@Slf4j
public class JyjcInspectionApplicationServiceImpl extends BaseService<JyjcInspectionApplicationModel, JyjcInspectionApplication, JyjcInspectionApplicationMapper> implements IJyjcInspectionApplicationService {

    @Autowired
    private JyjcInspectionResultServiceImpl inspectionResultService;
    @Autowired
    private JyjcInspectionApplicationEquipServiceImpl applicationEquipService;
    @Autowired
    TzsServiceFeignClient tzsServiceFeignClient;
    @Autowired
    private WorkflowHelper workflowHelper;

    @Autowired
    EventPublisher eventPublisher;
    /**
     * 分页查询
     */

    @Autowired
    JyjcInspectionApplicationAttachmentServiceImpl jyjcInspectionApplicationAttachmentService;
    @Autowired
    JyjcInspectionApplicationEquipServiceImpl jyjcInspectionApplicationEquipService;
    @Autowired
    JyjcInspectionApplicationPushLogServiceImpl jyjcInspectionApplicationPushLogService;

    @Autowired
    JyjcOpeningApplicationServiceImpl jyjcOpeningApplicationService;
    @Autowired
    WorkflowFeignService workflowFeignService;
    @Autowired
    CommonserviceImpl commonservice;
    @Autowired
    CmWorkflowServiceImpl cmWorkflowService;
    @Value("classpath:/json/bizTypeInfo.json")
    private Resource bizTypeInfo;

    @Autowired
    private JyjcInspectionApplicationEquipMapper jyjcInspectionApplicationEquipMapper;

    @Autowired
    JgFeignClient jgFeignClient;
    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    TaskModelServiceImpl taskModelService;

    @Autowired
    DataDictionaryServiceImpl dataDictionaryService;

    @Autowired
    EquipmentCategoryMapper equipmentCategoryMapper;

    @Autowired
    JyjcOpeningApplicationServiceImpl openingApplicationService;

    @Transactional(rollbackFor = Exception.class)
    public JyjcInspectionApplicationModel save(@RequestBody JSONObject obj) {
        ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);

        //接口通用 部分页面按钮无法分开配置类型 所以根据业务情况 将带有工作流实例id的数据 接口类型设置为2 走编辑逻辑
        JyjcInspectionApplicationModel model = JSONObject.parseObject(JSON.toJSONString(obj), JyjcInspectionApplicationModel.class);
        model.setEquip((List<Map<String, Object>>) obj.get("equip"));
        if (CharSequenceUtil.isNotEmpty(model.getProcessInstanceId()) && model.getOperationType().equals("0")) {
            model.setOperationType("2");
        }

        ArrayList<String> roleListAll = new ArrayList<>();
        ArrayList<String> roleListNext = new ArrayList<>();
        if (!model.getOperationType().equals("2")) {
            String taskName = "";
            if (model.getOperationType().equals("0")) {  // 工作台提交逻辑、详情页面保存并提交逻辑
                List<ProcessTaskDTO> processTasks = new ArrayList<>();
                ActWorkflowBatchDTO actWorkflowBatchDTO = new ActWorkflowBatchDTO();
                List<ActWorkflowStartDTO> list = new ArrayList<>();
                ActWorkflowStartDTO dto = new ActWorkflowStartDTO();
                dto.setProcessDefinitionKey(model.getProcessKey());
                dto.setBusinessKey(String.valueOf(new Date().getTime()));
                dto.setCompleteFirstTask(true);
                list.add(dto);
                actWorkflowBatchDTO.setProcess(list);
                String[] inspectionUnit = model.getInspectionUnitCode().split("_");
                if(inspectionUnit.length == 2){
                    model.setInspectionUnitCode(inspectionUnit[0]);
                    model.setInspectionUnitName(inspectionUnit[1]);
                }
                dto.setNextExecuteUserCompanyCode(model.getInspectionUnitCode());
                processTasks = cmWorkflowService.startBatch(actWorkflowBatchDTO);
                String instanceId = processTasks.get(0).getProcessInstance().getId();
                String nextTaskId = processTasks.get(0).getNextTask().get(0).getId();
                taskName = processTasks.get(0).getNextTask().get(0).getName();
                this.buildRoleList(processTasks, roleListNext, roleListAll);
                List<WorkflowResultDto> workflowResultDtos = taskModelService.buildWorkFlowInfo(processTasks);
                String nextUserIds = workflowResultDtos.get(0).getNextExecutorUserIds();
                String nextExcuteIds = workflowResultDtos.get(0).getNextExecutorRoleIds();
                model.setProcessInstanceId(instanceId);
                model.setInstanceId(instanceId);
                if (!org.springframework.util.ObjectUtils.isEmpty(model.getWorkflowRole())) {
                    model.setWorkflowRole(model.getWorkflowRole() + "," + nextExcuteIds);
                } else {
                    model.setWorkflowRole(nextExcuteIds);
                }
                model.setNextExecuteIds(nextExcuteIds);
                model.setNextTaskId(nextTaskId);
                model.setNextTaskName(taskName);
                model.setNextExecuteUserIds(nextUserIds);
                model.setStatus(String.valueOf(FlowStatusEnum.TO_SUBMITTED.getCode())); //6611 对应数据字典 检验流程状态 待受理
            } else if (model.getOperationType().equals("1")) {  //  工作台暂存、详情保存逻辑
                String[] inspectionUnit = model.getInspectionUnitCode().split("_");
                if(inspectionUnit.length == 2){
                    model.setInspectionUnitCode(inspectionUnit[0]);
                    model.setInspectionUnitName(inspectionUnit[1]);
                }
                model.setStatus(String.valueOf(FlowStatusEnum.TO_BE_SUBMITTED.getCode()));
            }

            LambdaQueryWrapper<JyjcOpeningApplication> wa = new LambdaQueryWrapper<JyjcOpeningApplication>().eq(JyjcOpeningApplication::getUnitCode, model.getInspectionUnitCode()).eq(JyjcOpeningApplication::getStatus, FlowStatusEnum.TO_BE_FINISHED.getCode());
            List<JyjcOpeningApplication> jyjcOpeningApplications = jyjcOpeningApplicationService.getBaseMapper().selectList(wa);
            if (CollectionUtils.isNotEmpty(jyjcOpeningApplications)) {
                //检验检测结果方式
                if (jyjcOpeningApplications.get(0).getResultType() != null) {
                    model.setResultType(jyjcOpeningApplications.get(0).getResultType());
                    // 报检时冗余检验检测机构厂商编号，推送厂商报检信息时需要
                    model.setDockingUnitCode(jyjcOpeningApplications.get(0).getDockingUnitCode());
                }
            }

            List<String> codes = tzsServiceFeignClient.applicationFormCode(ApplicationFormTypeEnum.JY.getCode(), 1).getResult();

            model.setApplicationNo(codes.get(0));
            model.setApplicationDate(new Date());
            model.setPromoter(reginParams.getUserModel().getUserId());
            model.setApplicationUnitName(reginParams.getCompany().getCompanyName());

            jyjcInspectionApplicationEquipService.getBaseMapper().deleteByApplicationSeq(model.getSequenceNbr());
            List<JyjcInspectionApplicationEquip> equipInfos = new ArrayList<>();
            if (null != model.getEquip() && model.getEquip().size() > 0) {
                List<JyjcInspectionApplicationEquipDto> equips = JSONObject.parseArray(JSON.toJSONString(model.getEquip()), JyjcInspectionApplicationEquipDto.class);
                for (JyjcInspectionApplicationEquipDto equip : equips) {
                    JyjcInspectionApplicationEquip equipInfo = new JyjcInspectionApplicationEquip();
                    equipInfo.setEquDefine(equip.getEquDefineCode());
                    equipInfo.setEquList(equip.getEquListCode());
                    equipInfo.setEquipUnicode(equip.getSequenceNbr());
                    equipInfo.setEquCategory(equip.getEquCategoryCode());
                    equipInfo.setSupervisoryCode(equip.getSupervisoryCode());
                    equipInfos.add(equipInfo);
                }
                model.setEquList(model.getEquip().get(0).getOrDefault("EQU_LIST", "").toString());
                model.setSupervisoryCode(model.getEquip().get(0).getOrDefault("SUPERVISORY_CODE", "").toString());
            }
            model.setCreateUserId(reginParams.getUserModel().getUserId());
            model.setNumberOfEquip(equipInfos.size());
            if (null == model.getSequenceNbr()) {
                model = this.createWithModel(model);
                if (StringUtils.isNotBlank(model.getProcessInstanceId())) {
                    this.createdTaskModel(model);
                } else {
                    TaskModelDto dto = new TaskModelDto();
                    TaskMessageDto ta = new TaskMessageDto();
                    ta.setInstanceId(model.getProcessInstanceId());
                    ta.setStatus(model.getStatus());
                    ta.setPromoter(model.getPromoter());
                    ta.setNextExecuteUserIds(model.getNextExecuteUserIds());
                    ta.setSequenceNbr(model.getSequenceNbr());
                    ta.setProcessInstanceId(model.getProcessInstanceId());
                    ta.setProcessKey(model.getProcessKey());
                    ta.setCreateUserId(RequestContext.getExeUserId());
                    ta.setNextTaskId(model.getNextTaskId());
                    dto.setModel(ta);
                    //摘要 按原有规则组装
                    dto.setTaskContent("来自" + model.getEquList() + "【" + model.getSupervisoryCode() + "】的业务办理,【申请单号:" + model.getApplicationNo() + "】");
                    //申请单号
                    dto.setTaskCode(model.getApplicationNo());
                    //业务类型枚举code值
                    dto.setTaskType(BizTypeEnum.getNumByCode(model.getBizType()));
                    ////业务主键
                    dto.setRelationId(model.getSequenceNbr() + "");
                    taskModelService.buildTaskModel(Arrays.asList(dto));
                }
            } else {
                model = this.updateWithModel(model);

                if (StringUtils.isNotBlank(model.getProcessInstanceId()) && model.getOperationType().equals("0")) {
                    taskModelService.deleteTaskModel(model.getSequenceNbr() + "");
                    this.createdTaskModel(model);
                } else {

                    String taskContent = "来自" + model.getEquList() + "【" + model.getSupervisoryCode() + "】的业务办理,【申请单号:" + model.getApplicationNo() + "】";
                    taskModelService.updateTaskContentById(MapBuilder.<String, Object>create().put("taskContent", taskContent).
                            put("relationId", model.getSequenceNbr() + "").build());
                }
            }


            //保存报检装备监管码
            for (JyjcInspectionApplicationEquip equipInfo : equipInfos) {
                equipInfo.setApplicationSeq(model.getSequenceNbr());
            }
            applicationEquipService.saveBatch(equipInfos);
            // 附件保存
            List<String> enumNameList = DocumentEnum.getEnumNameList();
            List<JyjcInspectionApplicationAttachmentModel> attachmentModels = new ArrayList<>();
            for (String code : enumNameList) {
                if (obj.containsKey(code)) {
                    JyjcInspectionApplicationAttachment attachments = new JyjcInspectionApplicationAttachment();
                    attachments.setAttachmentType(code);
                    attachments.setAttachmentUrl(JSONObject.toJSONString(obj.get(code)));
                    attachments.setApplicationSeq(model.getSequenceNbr());
                    jyjcInspectionApplicationAttachmentService.getBaseMapper().insert(attachments);
                }
            }
        } else {
            // 保存并提交
            LambdaQueryWrapper<JyjcOpeningApplication> wa = new LambdaQueryWrapper<JyjcOpeningApplication>().eq(JyjcOpeningApplication::getUnitCode, model.getInspectionUnitCode()).eq(JyjcOpeningApplication::getStatus, FlowStatusEnum.TO_BE_FINISHED.getCode());
            List<JyjcOpeningApplication> jyjcOpeningApplications = jyjcOpeningApplicationService.getBaseMapper().selectList(wa);
            if (CollectionUtils.isNotEmpty(jyjcOpeningApplications)) {
                //检验检测结果方式
                if (jyjcOpeningApplications.get(0).getResultType() != null) {
                    model.setResultType(jyjcOpeningApplications.get(0).getResultType());
                    // 报检时冗余检验检测机构厂商编号，推送厂商报检信息时需要
                    model.setDockingUnitCode(jyjcOpeningApplications.get(0).getDockingUnitCode());
                }
            }

            //更新报检装备监管码
            jyjcInspectionApplicationEquipService.getBaseMapper().deleteByApplicationSeq(model.getSequenceNbr());
            if (model.getEquip().size() > 0) {
                List<JyjcInspectionApplicationEquipDto> equips = JSONObject.parseArray(JSON.toJSONString(model.getEquip()), JyjcInspectionApplicationEquipDto.class);
                int num = equips.size();
                model.setNumberOfEquip(num);
                for (JyjcInspectionApplicationEquipDto equip : equips) {
                    JyjcInspectionApplicationEquip equipInfo = new JyjcInspectionApplicationEquip();
                    equipInfo.setEquDefine(equip.getEquDefineCode());
                    equipInfo.setEquList(equip.getEquListCode());
                    equipInfo.setEquipUnicode(equip.getSequenceNbr());
                    equipInfo.setEquCategory(equip.getEquCategoryCode());
                    equipInfo.setApplicationSeq(model.getSequenceNbr());
                    jyjcInspectionApplicationEquipService.save(equipInfo);
                }
                model.setEquList(model.getEquip().get(0).getOrDefault("EQU_LIST", "").toString());
                model.setSupervisoryCode(model.getEquip().get(0).getOrDefault("SUPERVISORY_CODE", "").toString());
            }

            // 附件更新
            List<String> enumNameList = DocumentEnum.getEnumNameList();

            jyjcInspectionApplicationAttachmentService.getBaseMapper().deleteByApplicationSeq(model.getSequenceNbr());
            for (String code : enumNameList) {
                if (obj.containsKey(code)) {
                    JyjcInspectionApplicationAttachment attachments = new JyjcInspectionApplicationAttachment();
                    attachments.setAttachmentType(code);
                    attachments.setAttachmentUrl(JSONObject.toJSONString(obj.get(code)));
                    attachments.setApplicationSeq(model.getSequenceNbr());
                    jyjcInspectionApplicationAttachmentService.getBaseMapper().insert(attachments);
                }
            }
            //6611 对应数据字典 检验流程状态 待受理
            model.setStatus(String.valueOf(FlowStatusEnum.TO_SUBMITTED.getCode()));

            ArrayList<String> roleList = new ArrayList<>();
            String taskId = model.getNextTaskId();
            //组装信息
            TaskResultDTO task = new TaskResultDTO();
            task.setResultCode("approvalStatus");
            task.setTaskId(taskId);
            task.setComment("");
            HashMap<String, Object> map = new HashMap<>();
            map.put("approvalStatus", "提交");
            task.setVariable(map);
            //执行流程
            task.setNextExecuteUserCompanyCode(model.getInspectionUnitCode());
            ProcessTaskDTO processTaskDTO = cmWorkflowService.complete(taskId, task);
            String taskName1 = "";
            String nextTaskId = "";
            this.buildRoleList(Collections.singletonList(processTaskDTO), roleList, roleListAll);
            List<WorkflowResultDto> workflowResultDtos = taskModelService.buildWorkFlowInfo(Collections.singletonList(processTaskDTO));
            String nextUserIds = workflowResultDtos.get(0).getNextExecutorUserIds();
            String executorRoleIds = workflowResultDtos.get(0).getExecutorRoleIds();
            if (processTaskDTO != null && processTaskDTO.getNextTask() != null && processTaskDTO.getNextTask().size() > 0) {
                taskName1 = processTaskDTO.getNextTask().get(0).getName();
                nextTaskId = processTaskDTO.getNextTask().get(0).getId();
            }
            model.setNextExecuteIds(String.join(",", roleList));
            if (!org.springframework.util.ObjectUtils.isEmpty(model.getWorkflowRole())) {
                model.setWorkflowRole(model.getWorkflowRole() + "," + String.join(",", roleList));
            } else {
                model.setWorkflowRole(String.join(",", roleList));
            }
            model.setNextTaskId(nextTaskId);
            model.setPromoter(RequestContext.getExeUserId());
            model.setStatus(String.valueOf(FlowStatusEnum.TO_SUBMITTED.getCode()));
            model.setStatusName(FlowStatusEnum.TO_SUBMITTED.getName());
            model.setNextTaskName(taskName1);
            model.setNextExecuteIds(executorRoleIds);
            model.setNextExecuteUserIds(nextUserIds);
            executeOneStep(model, taskName1, nextUserIds);
            this.updateWithModel(model);
        }
        return this.buildRedundancyField(model);
    }

    private JyjcInspectionApplicationModel buildRedundancyField(JyjcInspectionApplicationModel model) {
        // 冗余前端显示检验检测类型名称
        if (StringUtils.isNotEmpty(model.getInspectionType())) {
            model.setInspectionTypeName(getInspectionTypeName(model.getInspectionType()));
        }
        return model;
    }

    private String getInspectionTypeName(String inspectionType) {
        DataDictionary dictionary = dataDictionaryService.getByCode(inspectionType, "JYJC");
        return dictionary != null ? dictionary.getName() : "";
    }


    @Override
    public Boolean deleteBatchData(List<Long> sequenceNbr) {

//        List<JyjcInspectionApplication> jyjcInspectionApplications = this.getBaseMapper().selectBatchIds(sequenceNbr);
////        long count = jyjcInspectionApplications.stream().filter(e ->
////                e.getStatus().equals(String.valueOf(FlowStatusEnum.TO_BE_FINISHED.getCode()))
////                        || e.getStatus().equals(String.valueOf(FlowStatusEnum.TO_SUBMITTED.getCode()))
////                       ).count();
////
////        if (count > 0) {
////            throw new BadRequest("存在 已完成、待受理状态的报检单 不可删除!");
////        }

        this.deleteBatchSeq(sequenceNbr);
        for (Long seq : sequenceNbr) {
            jyjcInspectionApplicationEquipService.getBaseMapper().deleteByApplicationSeq(seq);
            jyjcInspectionApplicationAttachmentService.getBaseMapper().deleteByApplicationSeq(seq);
            jyjcInspectionApplicationPushLogService.getBaseMapper().deleteByApplicationSeq(seq);
        }
        return true;

    }

    public Page<JyjcInspectionApplicationEquipModel> listByCategory(Page<JyjcInspectionApplicationEquipModel> page, String equipClassify) {
        return getBaseMapper().listByCategory(page, equipClassify);
    }


    public Page<JyjcInspectionApplicationModel> queryForJyjcInspectionApplicationPage(Page<JyjcInspectionApplication> page,
                                                                                      String applicationNo,
                                                                                      String inspectionClassify,
                                                                                      String applicationUnitCode,
                                                                                      String equipClassify,
                                                                                      String inspectionUnitCode,
                                                                                      String applicationUnitName,
                                                                                      String inspectionUnitName,
                                                                                      String applicationDate,
                                                                                      String acceptDate,
                                                                                      String inspectionChargePerson,
                                                                                      String status, String bizType) {

//        return this.getBaseMapper().queryForDataList(page, applicationNo, inspectionClassify, applicationUnitCode, applicationUnitName, equipClassify, inspectionUnitCode, inspectionUnitName, applicationDate, acceptDate, inspectionChargePerson, status, bizType,roleIds);
        return this.getBaseMapper().queryForDataList(page, applicationNo, inspectionClassify, applicationUnitCode, applicationUnitName, equipClassify, inspectionUnitCode, inspectionUnitName, applicationDate, acceptDate, inspectionChargePerson, status, bizType);

    }

    @Override
    public Page<JyjcInspectionApplicationModel> queryForPageList(Page<JyjcInspectionApplication> page, JyjcInspectionApplicationModel model) {
        ReginParams reginParams = JSON.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(),
                RequestContext.getToken())).toString(), ReginParams.class);
        String companyType = reginParams.getCompany().getCompanyType();
        String companyCode = reginParams.getCompany().getCompanyCode();
        String currentUserId = reginParams.getUserModel().getUserId();
        String currentApplicationUnitCode = null;
        String currentInspectionUnitCode = null;
        if (ValidationUtil.isEmpty(companyType)) {
            return new Page<>(0, 10, 0);
        }
        // 判断当前登录人身份（报检机构、接收机构、即时报检又是接收机构、都不是（不存在此情况））
        String identity = this.getCompanyIdentityByType(reginParams.getCompany().getCompanyType());
        if (ValidationUtil.equals("apply", identity)) {
            currentApplicationUnitCode = companyCode;
        }
        if (ValidationUtil.equals("receive", identity)) {
            currentInspectionUnitCode = companyCode;
        }
        if (ValidationUtil.equals("all", identity)) {
            currentApplicationUnitCode = companyCode;
            currentInspectionUnitCode = companyCode;
        }
        Page<JyjcInspectionApplicationModel> resultPage = this.getBaseMapper().selectForPage(page, model, identity, currentApplicationUnitCode, currentInspectionUnitCode, currentUserId);
        return resultPage;
    }

    private String getCompanyIdentityByType(String companyType) {
        // 可发起单位的单位类型（角色与单位类型已绑定，在业务系统增加的账号不会出现角色与的单位类型不匹配场景）
        String[] applyIdentityDefine = {"使用单位", "安装改造维修单位"};
        // 可进行检验检测申请接收的单位类型，在业务系统增加的账号不会出现角色与的单位类型不匹配场景
        String[] receiveIdentityDefine = {"检验检测机构"};
        boolean isApplyIdentityMatch = false;
        boolean isReceiveIdentityMatch = false;
        if (Arrays.stream(applyIdentityDefine).anyMatch(companyType::contains)) {
            isApplyIdentityMatch = true;
        }
        if (Arrays.stream(receiveIdentityDefine).anyMatch(companyType::contains)) {
            isReceiveIdentityMatch = true;
        }
        if (isApplyIdentityMatch && !isReceiveIdentityMatch) {
            return "apply";
        }
        if (!isApplyIdentityMatch && isReceiveIdentityMatch) {
            return "receive";
        }
        if (isApplyIdentityMatch) {
            return "all";
        }
        return "no";
    }

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

    public Map<String, Object> selectBySeq(Long sequenceNbr) {

        JyjcInspectionApplicationModel model = this.getBaseMapper().selectDataBySeq(sequenceNbr);
        Map<String, Object> map = BeanUtil.beanToMap(model);
        List<Map<String, Object>> dataByApplicationSeq = jyjcInspectionApplicationAttachmentService.getBaseMapper().getDataByApplicationSeq(sequenceNbr);
        Map<String, Object> attMap = new HashMap<>();
        for (Map<String, Object> maps : dataByApplicationSeq) {
            List<AttachmentDto> data = JSONArray.parseArray(maps.get("attachment_url").toString(), AttachmentDto.class);
            attMap.put(maps.get("attachment_type").toString(), data);
        }
        LambdaQueryWrapper<JyjcInspectionApplicationEquip> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(JyjcInspectionApplicationEquip::getApplicationSeq, sequenceNbr);
        List<JyjcInspectionApplicationEquip> jyjcInspectionApplicationEquips = jyjcInspectionApplicationEquipMapper.selectList(wrapper);
        String collect = jyjcInspectionApplicationEquips.stream().map(JyjcInspectionApplicationEquip::getEquipUnicode).distinct().collect(Collectors.joining(","));
        HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("number", 1);
        hashMap.put("size", jyjcInspectionApplicationEquips.size());
        hashMap.put("SEQUENCE_NBR", collect);
        FeignClientResult<Page<JSONObject>> response = jgFeignClient.queryForPage(hashMap);
        if (200 == response.getStatus() && ObjectUtils.isNotEmpty(response.getResult())) {
            List<JSONObject> records = response.getResult().getRecords();
            ArrayList<Map<String, Object>> arrayList = new ArrayList<>();
            records.forEach(item -> {
                // item.remove("SEQUENCE_NBR");
                HashMap<String, Object> objectHashMap = new HashMap<>();
                for (Map.Entry<String, Object> stringObjectEntry : item.entrySet()) {
                    objectHashMap.put(stringObjectEntry.getKey(), stringObjectEntry.getValue());
                    String s = stringObjectEntry.getKey().toLowerCase();
                    objectHashMap.put(CharSequenceUtil.toCamelCase(s), stringObjectEntry.getValue());
                    if (stringObjectEntry.getKey().equals("SEQUENCE_NBR")) {
                        objectHashMap.put("record", stringObjectEntry.getValue());
                    }
                }
                arrayList.add(objectHashMap);
            });
            map.put("equip", arrayList);
        }
        map.putAll(attMap);
        return map;
    }

    /**
     * 接收
     *
     * @param params params
     * @return {@link }
     * @throws
     * @author yangyang
     * @date 2023/12/15 15:14
     */
    @Transactional(rollbackFor = Exception.class)
    public void doReceive(Map<String, Object> params) {

        Long sequenceNbr = Long.parseLong(params.get("sequenceNbr") + "");
        LambdaQueryWrapper<JyjcInspectionApplication> lambda = new QueryWrapper<JyjcInspectionApplication>().lambda();
        lambda.eq(JyjcInspectionApplication::getSequenceNbr, sequenceNbr);
        JyjcInspectionApplication entity = this.getBaseMapper().selectOne(lambda);

        String taskId = entity.getNextTaskId();
        //组装信息
        TaskResultDTO task = new TaskResultDTO();
        task.setResultCode("approvalStatus");
        task.setTaskId(taskId);
        task.setComment(params.getOrDefault("comments", "").toString());
        HashMap<String, Object> map = new HashMap<>();
        map.put("approvalStatus", "0");
        task.setVariable(map);
        //执行流程
        task.setNextExecuteUserCompanyCode(entity.getInspectionUnitCode());
        ProcessTaskDTO processTaskDTO = cmWorkflowService.complete(taskId, task);
        entity.setStatus(String.valueOf(FlowStatusEnum.TO_BE_FINISHED.getCode()));
        JyjcInspectionApplicationModel model = new JyjcInspectionApplicationModel();
        model.setStatusName(FlowStatusEnum.TO_BE_FINISHED.getName());
        entity.setAcceptDate(new Date());
        entity.setInnerPersonCode(params.getOrDefault("innerPersonCode", "").toString());
        String processDescription = (String) params.get("comments");
        if (StringUtils.isNotBlank(processDescription)) {
            entity.setProcessDescription(processDescription);
        }
        List<String> persons = JSONArray.parseArray(JSON.toJSONString(params.get("inspectionChargePerson")), String.class);
        if (CollectionUtil.isNotEmpty(persons)) {

            List<String> personCodes = new ArrayList<>();
            List<String> personNames = new ArrayList<>();
            for (String person : persons) {
                String[] s = person.split("_");
                personCodes.add(s[0]);
                personNames.add(s[1]);
            }
            String inspectionChargePerson = persons == null ? "" : String.join(",", persons);
            if (StringUtils.isNotBlank(inspectionChargePerson)) {
                entity.setInspectionChargePerson(String.join(",", personCodes));
                entity.setInspectionChargePersonName(String.join(",", personNames));
            }
        }

        String inspectionChargePhone = (String) params.get("inspectionChargePhone");
        if (StringUtils.isNotBlank(inspectionChargePhone)) {
            entity.setInspectionChargePhone(inspectionChargePhone);
        }
        this.updateById(entity);

        BeanUtils.copyProperties(entity, model);
        updateTaskModel(model);

        // 执行接收业务
        JyjcInspectionApplicationModel inspectionApplicationModel = this.queryBySeq(sequenceNbr);

        List<JyjcInspectionApplicationEquipModel> applicationEquipModels = applicationEquipService.listApplicationEquipByApplicationSeq(sequenceNbr);
        if (inspectionApplicationModel == null || ValidationUtil.isEmpty(applicationEquipModels)) {
            log.warn("JyjcInspectionApplicationModel Not Found！");
            return;
        }


        List<JyjcInspectionResult> resultModels = new ArrayList(applicationEquipModels.size());
        List<String> codes = tzsServiceFeignClient.applicationFormCode(ApplicationFormTypeEnum.JG.getCode(), applicationEquipModels.size()).getResult();


        for (int i = 0; i < applicationEquipModels.size(); i++) {
            JyjcInspectionResult resultModel = new JyjcInspectionResult();
            resultModel.setInspectionUnitCode(inspectionApplicationModel.getInspectionUnitCode());
            resultModel.setInspectionUnitName(inspectionApplicationModel.getInspectionUnitName());
            resultModel.setApplicationNo(inspectionApplicationModel.getApplicationNo());
            resultModel.setApplicationUnitCode(inspectionApplicationModel.getApplicationUnitCode());
            resultModel.setApplicationUnitName(inspectionApplicationModel.getApplicationUnitName());
            resultModel.setResultStatus(ResultStatusEnum.NO_RESULT.getCode());
            resultModel.setApplicationDate(inspectionApplicationModel.getApplicationDate());
            resultModel.setResultType(inspectionApplicationModel.getResultType());
            resultModel.setInspectionType(inspectionApplicationModel.getInspectionType());
            resultModel.setInspectionTypeName(this.getDictNameByCode(inspectionApplicationModel.getInspectionType()));
            // 解析设备
            resultModel.setBizType(inspectionApplicationModel.getBizType());
            resultModel.setResultNo(codes.get(i));
            //设备唯一标识
            resultModel.setEquipUnicode(applicationEquipModels.get(i).getEquipUnicode());
            resultModel.setSupervisoryCode(applicationEquipModels.get(i).getSupervisoryCode());
            resultModel.setEquDefine(applicationEquipModels.get(i).getEquDefine());
            resultModel.setEquCategory(applicationEquipModels.get(i).getEquCategory());
            resultModel.setEquList(applicationEquipModels.get(i).getEquList());
            resultModels.add(resultModel);
        }
        inspectionResultService.saveOrUpdateBatch(resultModels);
        this.pushInspectionApplication(inspectionApplicationModel);
    }

    private void pushInspectionApplication(JyjcInspectionApplicationModel inspectionApplicationModel) {
        // 将检验检测申请信息推送至对应的检验机构
        if(inspectionApplicationModel.getResultType().equals(ResultTypeEnum.INTEGRATED.getCode())){
            InspectionApplicationPushEvent event = new InspectionApplicationPushEvent(this, inspectionApplicationModel);
            eventPublisher.publish(event);
        }
    }

    private String getDictNameByCode(String code) {
        DataDictionary dataDictionary = dataDictionaryService.getByCode(code, "JYJC");
        return dataDictionary != null ? dataDictionary.getName() : "";
    }

    /**
     * 退回
     *
     * @param params params
     * @return {@link }
     * @throws
     * @author yangyang
     * @date 2023/12/15 15:14
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean doReject(Map<String, Object> params) {

        Long sequenceNbr = Long.parseLong(params.get("sequenceNbr") + "");
        LambdaQueryWrapper<JyjcInspectionApplication> lambda = new QueryWrapper<JyjcInspectionApplication>().lambda();
        lambda.eq(JyjcInspectionApplication::getSequenceNbr, sequenceNbr);
        JyjcInspectionApplication entity = this.getBaseMapper().selectOne(lambda);
        ArrayList<String> roleListAll = new ArrayList<>();
        ArrayList<String> roleListNext = new ArrayList<>();
        ArrayList<String> roleList = new ArrayList<>();
        String taskId = entity.getNextTaskId();
        //组装信息
        TaskResultDTO task = new TaskResultDTO();
        task.setResultCode("approvalStatus");
        task.setTaskId(taskId);
        task.setComment(params.getOrDefault("comments", "").toString());
        HashMap<String, Object> map = new HashMap<>();
        map.put("approvalStatus", "1");
        task.setVariable(map);
        //执行流程
        task.setNextExecuteUserCompanyCode(entity.getInspectionUnitCode());
        ProcessTaskDTO processTaskDTO = cmWorkflowService.reject(taskId, task);
        String taskCode = FlowStatusEnum.TO_SUBMITTED.getName();
        String taskName1 = "";
        String nextTaskId = "";
        this.buildRoleList(Collections.singletonList(processTaskDTO), roleList, roleListAll);
        List<WorkflowResultDto> workflowResultDtos = taskModelService.buildWorkFlowInfo(Collections.singletonList(processTaskDTO));

        entity.setStatus(String.valueOf(FlowStatusEnum.REJECTED.getCode()));
        JyjcInspectionApplicationModel model = new JyjcInspectionApplicationModel();
        BeanUtils.copyProperties(entity, model);
        model.setStatusName(FlowStatusEnum.REJECTED.getName());
        String processDescription = (String) params.get("comments");
        if (StringUtils.isNotBlank(processDescription)) {
            entity.setProcessDescription(processDescription);
        }
        String nextUserIds = workflowResultDtos.get(0).getNextExecutorUserIds();
        String executorRoleIds = workflowResultDtos.get(0).getExecutorRoleIds();
        if (processTaskDTO != null && processTaskDTO.getNextTask() != null && processTaskDTO.getNextTask().size() > 0) {
            taskCode = processTaskDTO.getNextTask().get(0).getKey();
            taskName1 = processTaskDTO.getNextTask().get(0).getName();
            nextTaskId = processTaskDTO.getNextTask().get(0).getId();
        }
        model.setNextExecuteIds(String.join(",", roleList));
        if (!org.springframework.util.ObjectUtils.isEmpty(model.getWorkflowRole())) {
            model.setWorkflowRole(model.getWorkflowRole() + "," + String.join(",", roleList));
        } else {
            model.setWorkflowRole(String.join(",", roleList));
        }
        model.setNextTaskId(nextTaskId);
        model.setPromoter(RequestContext.getExeUserId());
        model.setNextTaskName(taskName1);
        model.setNextExecuteIds(executorRoleIds);
        model.setNextExecuteUserIds(nextUserIds);
        executeOneStep(model, taskName1, nextUserIds);
        BeanUtils.copyProperties(model, entity);
        this.updateById(entity);
        return true;
    }


    /**
     * 撤回流程办理单
     */
    public Boolean doRollback(String sequenceNbr) {
        JyjcInspectionApplicationModel inspectionApplicationModel = this.queryBySeq(Long.valueOf(sequenceNbr));
        if (inspectionApplicationModel == null) {
            log.warn("JyjcInspectionApplicationModel Not Found！sequenceNbr => " + sequenceNbr);
            return false;
        }
        String taskCode = FlowStatusEnum.TO_BE_FINISHED.getName();
        String[] taskName = new String[]{"流程结束"};
        List<String> roleListNext = new ArrayList<>();
        List<String> roleListAll = new ArrayList<>();
        ProcessTaskDTO processTaskDTO = cmWorkflowService.rollBack(inspectionApplicationModel.getProcessInstanceId());
        String nextTaskId = processTaskDTO.getNextTask().get(0).getId();
        this.buildRoleList(Collections.singletonList(processTaskDTO), roleListNext, roleListAll);
        List<WorkflowResultDto> workflowResultDtos = taskModelService.buildWorkFlowInfo(Collections.singletonList(processTaskDTO));
        if (!org.springframework.util.ObjectUtils.isEmpty(inspectionApplicationModel.getWorkflowRole())) {
            inspectionApplicationModel.setWorkflowRole(inspectionApplicationModel.getWorkflowRole() + "," + roleListAll);
        } else {
            inspectionApplicationModel.setWorkflowRole(inspectionApplicationModel.getWorkflowRole());
        }
        // 待调整
        taskCode = processTaskDTO.getNextTask().get(0).getKey();
        inspectionApplicationModel.setStatus(String.valueOf(FlowStatusEnum.ROLLBACK.getCode()));
        inspectionApplicationModel.setStatusName(FlowStatusEnum.ROLLBACK.getName());
        inspectionApplicationModel.setPromoter("");
        inspectionApplicationModel.setNextTaskId(nextTaskId);
        inspectionApplicationModel.setNextExecuteUserIds(workflowResultDtos.get(0).getNextExecutorUserIds());
        inspectionApplicationModel.setNextExecuteIds(String.join(",", roleListNext));
        JyjcInspectionApplication jyjcInspectionApplication = new JyjcInspectionApplication();


        BeanUtils.copyProperties(inspectionApplicationModel, jyjcInspectionApplication);

        this.getBaseMapper().updateById(jyjcInspectionApplication);
        JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(inspectionApplicationModel));
        jsonObject.put("nextTaskId", inspectionApplicationModel.getNextTaskId());
        jsonObject.put("nextExecuteUser", inspectionApplicationModel.getNextExecuteIds());
        jsonObject.put("taskType", BizTypeEnum.getNumByCode(inspectionApplicationModel.getBizType()));
        jsonObject.put("flowStatus", FlowStatusEnum.ROLLBACK.getCode());
        jsonObject.put("flowStatusLabel", FlowStatusEnum.ROLLBACK.getName());

        taskModelService.rollbackTask(inspectionApplicationModel.getProcessInstanceId(), jsonObject);
        return true;


    }

    public void updateModelByInstanceId(Long sequenceNbr, String instanceId, Map<String, Object> params, Boolean rollBack) {
        ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
        LambdaQueryWrapper<JyjcInspectionApplication> lambda = new QueryWrapper<JyjcInspectionApplication>().lambda();
        lambda.eq(JyjcInspectionApplication::getSequenceNbr, sequenceNbr);
        JyjcInspectionApplication entity = this.getBaseMapper().selectOne(lambda);
        if (entity == null) {
            return;
        }
        String status = (String) params.get("status");
        List<String> persons = JSONArray.parseArray(JSON.toJSONString(params.get("inspectionChargePerson")), String.class);

        String inspectionChargePerson = persons == null ? "" : String.join(",", persons);
        if (StringUtils.isNotBlank(inspectionChargePerson)) {
            entity.setInspectionChargePerson(inspectionChargePerson);
        }

        String processDescription = (String) params.get("comments");
        if (StringUtils.isNotBlank(processDescription)) {
            entity.setProcessDescription(processDescription);
        }
        String inspectionChargePhone = (String) params.get("inspectionChargePhone");
        if (StringUtils.isNotBlank(inspectionChargePhone)) {
            entity.setInspectionChargePhone(inspectionChargePhone);
        }

        Map<String, Object> nextNodeInfo = workflowHelper.getNextWorkflowNode(instanceId);
        String role = (String) nextNodeInfo.get("role");
        entity.setNextExecuteIds(role);
        entity.setPromoter(reginParams.getUserModel().getUserId());
        if (!org.springframework.util.ObjectUtils.isEmpty(entity.getWorkflowRole())) {
            entity.setWorkflowRole(entity.getWorkflowRole() + "," + role);
        } else {
            entity.setWorkflowRole(role);
        }
        entity.setStatus(status);
        //此处自己撤销也赋予了办理日期 存在问题 与驳回 通过区分处理
        if (rollBack) {
            this.getBaseMapper().updatePromoter(entity.getSequenceNbr());
        }
        //逻辑变更为 通过后才对办理时间赋值
        if (status.equals(String.valueOf(FlowStatusEnum.TO_BE_FINISHED.getCode()))) {
            entity.setAcceptDate(new Date());
            entity.setInnerPersonCode(params.getOrDefault("innerPersonCode", "").toString());
        }
        this.updateById(entity);

    }

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

    private void createdTaskModel(JyjcInspectionApplicationModel model) {

        ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
        TaskModelDto dto = new TaskModelDto();
        TaskMessageDto ta = new TaskMessageDto();
        ta.setInstanceId(model.getProcessInstanceId());
        ta.setStatus(model.getStatus());
        ta.setPromoter(model.getPromoter());
        ta.setNextExecuteIds(model.getNextExecuteIds());
        ta.setSequenceNbr(model.getSequenceNbr());
        ta.setProcessInstanceId(model.getProcessInstanceId());
        ta.setProcessKey(model.getProcessKey());
        ta.setInspectionUnitCode(model.getInspectionUnitCode());
        ta.setNextTaskId(model.getNextTaskId());
        ta.setBizType(model.getBizType());
        dto.setModel(ta);
        dto.setFlowCreateDate(new Date());
        dto.setTaskName(model.getNextTaskName());
        dto.setFlowCode(model.getNextTaskId());
        dto.setTaskContent("来自" + model.getEquList() + "【" + model.getSupervisoryCode() + "】的业务办理,【申请单号:" + model.getApplicationNo() + "】");
        dto.setTaskCode(model.getApplicationNo());
        dto.setTaskType(BizTypeEnum.getNumByCode(model.getBizType()));
        dto.setTaskTypeLabel(BizTypeEnum.getNameByCode(model.getBizType()));
        dto.setRelationId(model.getInstanceId());
        dto.setExecuteUserIds(model.getNextExecuteUserIds());
        dto.setTaskStatusLabel("未处理");
        dto.setFlowStatus(Integer.valueOf(model.getStatus()));
        dto.setFlowStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
        dto.setStartUserId(RequestContext.getExeUserId());
        dto.setStartUser(reginParams.getUserModel().getRealName());
        dto.setStartUserCompanyName(reginParams.getCompany().getCompanyName());
        dto.setStartDate(new Date());
        dto.setNextExecuteUser(model.getNextExecuteIds());

        taskModelService.buildTaskModel(Arrays.asList(dto));
    }


    private void executeOneStep(JyjcInspectionApplicationModel model, String taskName, String nextUserIds) {
        // 先更新之前的待办
        TaskV2Model taskV2Model = updateTaskModel(model);
        taskV2Model.setTaskDesc("");
        taskV2Model.setTaskName(taskName);
        taskV2Model.setTaskCode(model.getApplicationNo());
        taskV2Model.setExecuteUserIds(nextUserIds);
        taskV2Model.setRelationId(model.getProcessInstanceId());
        taskV2Model.setTaskStatus(Integer.valueOf(model.getStatus()));
        taskV2Model.setTaskStatusLabel(model.getStatusName());
        taskV2Model.setFlowStatus(Integer.valueOf(model.getStatus()));
        taskV2Model.setFlowStatusLabel(model.getStatusName());
        TaskModelDto modelDto = new TaskModelDto();
        BeanUtil.copyProperties(taskV2Model, modelDto);
        modelDto.setNextExecuteUser(model.getNextExecuteIds());
        if (model.getStatus().equals(FlowStatusEnum.REJECTED.getCode() + "")) {
            modelDto.setPageType("edit");
        }
        TaskMessageDto obj = new TaskMessageDto();
        obj.setInstanceId(model.getProcessInstanceId());
        obj.setStatus(model.getStatus());
        obj.setNextTaskId(model.getNextTaskId());
        obj.setPromoter(model.getPromoter());
        obj.setNextExecuteUserIds(model.getNextExecuteUserIds());
        obj.setSequenceNbr(model.getSequenceNbr());
        obj.setNextExecuteIds(model.getNextExecuteIds());
        obj.setProcessInstanceId(model.getProcessInstanceId());
        obj.setProcessKey(model.getProcessKey());
        obj.setInspectionUnitCode(model.getInspectionUnitCode());
        obj.setBizType(model.getBizType());
        obj.setCreateUserId(model.getCreateUserId());
        modelDto.setModel(obj);
        // 再插入新代办、数据待定
        taskModelService.buildTaskModel(Collections.singletonList(modelDto));
    }


    private TaskV2Model updateTaskModel(JyjcInspectionApplicationModel model) {
        Map<String, Object> params = new HashMap<>();
        params.put("relationId", model.getProcessInstanceId());
        params.put("taskStatus", model.getStatus());
        params.put("taskStatusLabel", model.getStatusName());
        params.put("flowStatus", model.getStatus());
        params.put("flowStatusLabel", model.getStatusName());
        params.put("model", model);
        return taskModelService.updateTaskModel(params);
    }
}