package com.yifu.cloud.plus.v1.yifu.process.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.yifu.cloud.plus.v1.yifu.process.entity.*;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser;
import com.yifu.cloud.plus.v1.yifu.common.security.util.SecurityUtils;
import com.yifu.cloud.plus.v1.yifu.process.entity.*;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.ResultConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;
import com.yifu.cloud.plus.v1.yifu.common.core.util.R;
import com.yifu.cloud.plus.v1.yifu.common.core.util.bean.BeanCopyUtils;
import com.yifu.cloud.plus.v1.yifu.process.service.*;
import com.yifu.cloud.plus.v1.yifu.process.vo.CheckNodeVo;
import com.yifu.cloud.plus.v1.yifu.process.mapper.TProcessMapper;
import com.yifu.cloud.plus.v1.yifu.process.vo.DeleteProcessIdsVo;
import com.yifu.cloud.plus.v1.yifu.process.vo.ProcessVo;
import com.yifu.cloud.plus.v1.yifu.process.vo.TProcessViewVo;
import com.yifu.cloud.plus.v1.yifu.process.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.yifu.cloud.plus.v1.yifu.common.core.constant.ResultConstants.FAIL_INFO_NO_MODEL;

/**
 * 主流程表
 *
 * @author hgw
 * @date 2020-07-16 15:44:02
 */
@Service
@Slf4j
public class TProcessServiceImpl extends ServiceImpl<TProcessMapper, TProcess> implements TProcessService {

	 @Resource
     private TProcessNodeService processNodeService;

	 @Resource
     private TNodeRouteService nodeRouteService;

	 @Resource
     private TNodePrimissionService nodePrimissionService;

	 @Resource
     private TNodeReaderPromissionService nodeReaderPromissionService;

     static final List<String> departIdType = Arrays.asList("1", "4", "5", "6","7","8","9","10","11","12");
     static final List<String> chapterUnitType = Arrays.asList("2", "3");

	 @Resource
     private TNodeRouteConditionService nodeRouteConditionService;

	 @Resource
     private TNodeTransferConfigService nodeTransferConfigService;

	 @Resource
     private TProcessApprovalConfService processApprovalConfService;


     /**
      * 主流程表简单分页查询
      *
      * @param tProcess 主流程表
      * @return
      */
     @Override
     public IPage<TProcessViewVo> getTProcessPage(Page<TProcessViewVo> page, TProcessViewVo tProcess,String type) {
          //参数处理
          if (Common.isEmpty(tProcess.getProcessIsUse())){
               //默认查询在用
               tProcess.setProcessIsUse(CommonConstants.ZERO_STRING);
          }
          // getProcessIds为空表示从流程管理页面进来查询的。不为空是用流程检测列表来的
          List<TProcessApprovalConf> thisDepartIdConfig = new ArrayList<>();
          if (Common.isEmpty(tProcess.getProcessIds())) {
               //先获得符合条件的配置流程
               thisDepartIdConfig = processApprovalConfService.list(Wrappers.<TProcessApprovalConf>query().lambda()
                       .eq(Common.isNotNull(tProcess.getProcessType()),TProcessApprovalConf::getType,tProcess.getProcessType())
                       .eq(Common.isNotNull(tProcess.getDepartId()),TProcessApprovalConf::getFieldValue,tProcess.getDepartId())
                       .eq(TProcessApprovalConf::getDeleteFlag, CommonConstants.ZERO_STRING));
               //用于流程信息查询方法 where查询的范围参数
               Set<String> processIdSet = new HashSet<>();
               if (Common.isNotKong(thisDepartIdConfig)){
                    //将符合条件的流程id封装起来
                    processIdSet = thisDepartIdConfig.stream().map(TProcessApprovalConf::getProcessId).collect(Collectors.toSet());
                    tProcess.setProcessIds(processIdSet);
               }else {
                    //若条件查到为0条，则下面获得流程信息也应为0条
                    processIdSet.add(CommonConstants.ZERO_STRING);
                    tProcess.setProcessIds(processIdSet);
               }
          } else {
               thisDepartIdConfig = processApprovalConfService.list(Wrappers.<TProcessApprovalConf>query().lambda()
                      .eq(TProcessApprovalConf::getDeleteFlag, CommonConstants.ZERO_STRING));
          }

          IPage<TProcessViewVo> tProcessPage = baseMapper.getTProcessPage(page, tProcess, type);
          List<TProcessViewVo> records = tProcessPage.getRecords();
          if(Common.isEmpty(records)) {
               return tProcessPage;
          }
          //合同和部门用章单位
          //获取所有流程id的数据
          //key: 流程, value:部门
          Map<String, Set<String>> departIdTypeMap=Maps.newHashMap();
          //key: 流程, value:流程类型
          Map<String, String> processTypeMap=Maps.newHashMap();
          //key: 流程, value:用章单位
          Map<String, Set<String>> chapterUnitTypeMap=Maps.newHashMap();

          if (Common.isNotKong(thisDepartIdConfig)) {
               for (TProcessApprovalConf processApprovalConf : thisDepartIdConfig) {
                    processTypeMap.put(processApprovalConf.getProcessId(),processApprovalConf.getType());
                    //部门类型
                    if (departIdType.contains(processApprovalConf.getType())) {
                         Set<String> processDepartSet = departIdTypeMap.get(processApprovalConf.getProcessId());
                         if (processDepartSet == null) {
                              processDepartSet = Sets.newHashSet();
                              processDepartSet.add(processApprovalConf.getFieldValue());
                              departIdTypeMap.put(processApprovalConf.getProcessId(), processDepartSet);
                         } else {
                              processDepartSet.add(processApprovalConf.getFieldValue());
                         }
                    }
                    //用章单位类型
                    if (chapterUnitType.contains(processApprovalConf.getType())) {
                         Set<String> processChapterUnitSet = chapterUnitTypeMap.get(processApprovalConf.getProcessId());
                         if (processChapterUnitSet == null) {
                              processChapterUnitSet = Sets.newHashSet();
                              processChapterUnitSet.add(processApprovalConf.getFieldValue());
                              chapterUnitTypeMap.put(processApprovalConf.getProcessId(), processChapterUnitSet);
                         } else {
                              processChapterUnitSet.add(processApprovalConf.getFieldValue());
                         }
                    }
               }
          }

          for (TProcessViewVo record :records) {
                    record.setType(processTypeMap.get(record.getId()));
                    Set<String> strings = departIdTypeMap.get(record.getId());
                    record.setDepartIds(departIdTypeMap.get(record.getId()));
                    record.setChapterUnits(chapterUnitTypeMap.get(record.getId()));
          }
          return tProcessPage;
     }

     /**
      * @param id
      * @Description: 获取包装类
      * @Author: hgw
      * @Date: 2020/7/17 11:05
      * @return: ProcessVo
      **/
     @Override
     public ProcessVo getProcessVoById(String id) {
          // 主流程表
          ProcessVo processVo = new ProcessVo();
          if (Boolean.TRUE.equals(Common.isEmpty(id))) {
               return processVo;
          }
          processVo.setProcessId(id);
          // 节点
          TProcessNode processNode = new TProcessNode();
          processNode.setProcessId(id);
          // 节点查询
          QueryWrapper<TProcessNode> queryWrapperPn = new QueryWrapper<>();
          queryWrapperPn.setEntity(processNode);
          // 节点列表
          List<TProcessNode> processNodeList = processNodeService.list(queryWrapperPn);
          if (processNodeList != null && !processNodeList.isEmpty()) {
               // 权限
               TNodePrimission nodePrimission;
               // 权限查询
               QueryWrapper<TNodePrimission> queryWrapperNp;
               // 权限列表
               List<TNodePrimission> nodePrimissionList;
               // 抄送
               TNodeReaderPromission nodeReaderPromission;
               // 抄送查询
               QueryWrapper<TNodeReaderPromission> queryWrapperNrp;
               // 抄送列表
               List<TNodeReaderPromission> nodeReaderPromissionList;
               for (TProcessNode proNode : processNodeList) {
                    nodePrimission = new TNodePrimission();
                    nodePrimission.setNodeId(proNode.getId());
                    queryWrapperNp = new QueryWrapper<>();
                    queryWrapperNp.setEntity(nodePrimission);
                    nodePrimissionList = nodePrimissionService.list(queryWrapperNp);
                    proNode.setNodePrimissionList(nodePrimissionList);
                    nodeReaderPromission = new TNodeReaderPromission();
                    nodeReaderPromission.setNodeId(proNode.getId());
                    queryWrapperNrp = new QueryWrapper<>();
                    queryWrapperNrp.setEntity(nodeReaderPromission);
                    nodeReaderPromissionList = nodeReaderPromissionService.list(queryWrapperNrp);
                    proNode.setNodeReaderPromissionList(nodeReaderPromissionList);
                    //子流程
                    proNode.setNodeTransferConfigs(nodeTransferConfigService.list(Wrappers.<TNodeTransferConfig>query().lambda().eq(TNodeTransferConfig::getNodeId, proNode.getId())));
               }
          }
          processVo.setProcessNodeList(processNodeList);

          // 路由
          TNodeRoute nodeRoute = new TNodeRoute();
          nodeRoute.setProcessId(id);
          // 路由查询
          QueryWrapper<TNodeRoute> queryWrapperNr = new QueryWrapper<>();
          queryWrapperNr.setEntity(nodeRoute);
          // 路由列表
          List<TNodeRoute> nodeRouteList = nodeRouteService.list(queryWrapperNr);
          //路由条件
          for (TNodeRoute tNodeRoute : nodeRouteList) {
               tNodeRoute.setNodeRouteConditionList(nodeRouteConditionService.list(Wrappers.<TNodeRouteCondition>query().lambda().eq(TNodeRouteCondition::getNodeRouteId,tNodeRoute.getId())));
          }
          processVo.setNodeRouteList(nodeRouteList);
          return processVo;
     }

	/**
	 * 根据流程类型查询ProcessVo
	 * @param processType 流程类型
	 * @return R<ProcessVo>
	 * @since mvp1.7.5
	 **/
     @Override
     public ProcessVo getProcessVoByType(String processType) {
		 TProcessApprovalConf approvalConf = processApprovalConfService.getOne(Wrappers.<TProcessApprovalConf>query().lambda()
				 .eq(TProcessApprovalConf::getType, processType)
				 .eq(TProcessApprovalConf::getDeleteFlag, CommonConstants.ZERO_STRING).last(CommonConstants.SQL_LIMIT_ONE));
		 if(Common.isEmpty(approvalConf)){
		 	 log.error("根据类型获取流程配置失败>>processType={}",processType);
			 return null;
		 }
          // 获取主流程信息
          ProcessVo processVo = new ProcessVo();
          TProcess process = this.getById(approvalConf.getProcessId());
          if (Common.isEmpty(process)) {
			  log.error("获取主流程信息失败>>processId={}",approvalConf.getProcessId());
			  return null;
          }
          String processId = process.getId();
          processVo.setProcessId(processId);
          processVo.setName(process.getName());

          // 获取节点列表信息
		  List<TProcessNode> processNodeList = processNodeService.list(Wrappers.<TProcessNode>query().lambda()
				  .eq(TProcessNode::getProcessId, processId));
          if (Common.isNotNull(processNodeList)) {
               // 定义审批用户列表
               List<TNodePrimission> nodePrimissionList;
               // 定义抄送用户列表
               List<TNodeReaderPromission> nodeReaderPromissionList;

               for (TProcessNode nodeInfo : processNodeList) {
               		// 赋值审批用户列表
                    nodePrimissionList = nodePrimissionService.list(Wrappers.<TNodePrimission>query().lambda()
							.eq(TNodePrimission::getNodeId, nodeInfo.getId()));
				    nodeInfo.setNodePrimissionList(nodePrimissionList);
					// 赋值抄送用户列表
                    nodeReaderPromissionList = nodeReaderPromissionService.list(Wrappers.<TNodeReaderPromission>query().lambda()
							.eq(TNodeReaderPromission::getNodeId, nodeInfo.getId()));
				    nodeInfo.setNodeReaderPromissionList(nodeReaderPromissionList);
               }
          }
          processVo.setProcessNodeList(processNodeList);
          // 路由列表
          List<TNodeRoute> nodeRouteList = nodeRouteService.list(Wrappers.<TNodeRoute>query().lambda()
				  .eq(TNodeRoute::getProcessId, processId));
		  // 路由条件判断列表
		  if (Common.isNotNull(nodeRouteList)) {
			  List<TNodeRouteCondition> nodeRouteConditionList;
			 for (TNodeRoute tNodeRoute : nodeRouteList) {
				 nodeRouteConditionList = nodeRouteConditionService.list(Wrappers.<TNodeRouteCondition>query().lambda().eq(TNodeRouteCondition::getNodeRouteId,tNodeRoute.getId()));
				 tNodeRoute.setNodeRouteConditionList(nodeRouteConditionList);
			 }
			 processVo.setNodeRouteList(nodeRouteList);
		   }

          return processVo;
     }

     /**
      * @param processVo 流程VO
      * @Description: 保存流程
      * @Author: hgw
      * @Date: 2020/7/17 11:14
      * @return: com.yifu.cloud.plus.v1.yifu.common.core.util.R
      **/
     @Override
     @Transactional
     public R saveProcessVo(ProcessVo processVo) {
          // 主流程表
          if (Boolean.TRUE.equals(Common.isEmpty(processVo.getProcessId()))) {
               return R.failed("流程id不可为空！");
          }
          // 流程id
          String processId = processVo.getProcessId();

          // 删除之前保存的且被删掉的节点、线、权限、抄送
          this.deleteIds(processVo.getDeleteIdsVo());

          // 用户
		  YifuUser user = SecurityUtils.getUser();
          // 用户id
          String userId = String.valueOf(user.getId());
          // 当前时间
          LocalDateTime nowTime = LocalDateTime.now();
          // 保存流程节点
          if (processVo.getProcessNodeList() != null) {
               // 循环节点
               R err = saveOrUpdateNode(processVo, processId);
               if (Common.isNotKong(err)){
                    return err;
               }
          }
          // 保存节点路由
          if (processVo.getNodeRouteList() != null && !processVo.getNodeRouteList().isEmpty()) {
               //crm2.12.0 保存之前先进行校验 配置保存的时候验证同一个节点相同路由条件不能指向不同的节点
               R r = saveBeforeCheck(processVo);
               if (Common.isNotKong(r)){
                    return r;
               }
               saveOrUpdateRoute(processVo, processId, userId, nowTime);
          }
          return R.ok("保存成功");
     }

     /**
      * @param processVo 流程vo
      * @param processId 流程id
      * @param userId 用户id
      * @param nowTime 当前时间
      * @Description: 保存线
      * @Author: hgw
      * @Date: 2020/7/27 14:12
      * @return: void
      **/
     private void saveOrUpdateRoute(ProcessVo processVo, String processId, String userId, LocalDateTime nowTime) {
          for (TNodeRoute nodeRoute : processVo.getNodeRouteList()) {
               nodeRoute.setProcessId(processId);
               if (Boolean.TRUE.equals(Common.isNotKong(nodeRoute.getId()))) {
                    nodeRoute.setUpdateDate(nowTime);
                    nodeRoute.setUpdateUser(userId);
                    nodeRouteService.updateById(nodeRoute);
               } else {
                    nodeRoute.setCreateDate(nowTime);
                    nodeRoute.setCreateUser(userId);
                    nodeRouteService.save(nodeRoute);
               }
               saveOrUpdateRouteCondition(nodeRoute);
          }
     }

     /**
      * 功能描述: 校验同一个节点相同路由条件不能指向不同的节点
      * @Param: []
      * @Return: void
      * @Author: wangdayu
      * @Date: 2023/10/25 15:10
      * @Since:
      */
     private R saveBeforeCheck(ProcessVo processVo) {
          List<CheckNodeVo> checkList = new ArrayList<>();
          for (TNodeRoute tNodeRoute : processVo.getNodeRouteList()) {
               //将需要的信息封装起来
               CheckNodeVo one = new CheckNodeVo();
               one.setProcessId(tNodeRoute.getProcessId());
               one.setPrewNode(tNodeRoute.getPrewNode());
               one.setNextNode(tNodeRoute.getNextNode());
               one.setLogoTitle(tNodeRoute.getLogoTitle());
               if (Common.isNotKong(tNodeRoute.getNodeRouteConditionList())) {
                    for (TNodeRouteCondition tNodeRouteCondition : tNodeRoute.getNodeRouteConditionList()) {
                         one.setNodeRouteId(tNodeRouteCondition.getNodeRouteId());
                         one.setField(tNodeRouteCondition.getField());
                    }
               }
               checkList.add(one);
          }
          if (Common.isNotKong(checkList)){
               Map<String, List<CheckNodeVo>> groupMap = checkList.stream()
                       .collect(
                               Collectors.groupingBy(CheckNodeVo::getPrewNode));
               if (Common.isNotKong(groupMap)) {
                    for (String key : groupMap.keySet()) {
                         List<CheckNodeVo> checkNodeVoList = groupMap.get(key);
                         for (CheckNodeVo checkNodeVo : checkNodeVoList) {
                              for (CheckNodeVo nodeVo : checkNodeVoList) {
                                   //位置重合路由
                                   if (Common.isNotKong(checkNodeVo.getPrewNode())
                                           && Common.isNotKong(nodeVo.getPrewNode())
                                           && !StringUtils.equals(checkNodeVo.getLogoTitle(),nodeVo.getLogoTitle())
                                           && StringUtils.equals(checkNodeVo.getPrewNode(),nodeVo.getPrewNode())
                                           && StringUtils.equals(checkNodeVo.getNextNode(),nodeVo.getNextNode())){
                                        return R.failed("存在重合路由！");
                                   }
                                   //如果表达式相同且后置节点相同，跳过，否则抛出异常
                                   if (Common.isNotKong(checkNodeVo.getField()) && Common.isNotKong(nodeVo.getField())) {
                                        if (checkNodeVo.getField().equals(nodeVo.getField())) {
                                             if (Common.isNotKong(checkNodeVo.getNextNode())
                                                     && Common.isNotKong(nodeVo.getNextNode())
                                                     && !checkNodeVo.getNextNode().equals(nodeVo.getNextNode())) {
                                                  return R.failed("存在相同表达式路由指向不同节点！");
                                             }
                                        }
                                   }

                              }
                         }
                    }
               }
          }
          return null;
     }

     /**
      * 保存路由条件
      * @param nodeRoute
      */
     private void saveOrUpdateRouteCondition(TNodeRoute nodeRoute){
          List<TNodeRouteCondition> nodeRouteConditionList = nodeRoute.getNodeRouteConditionList();
          if(nodeRouteConditionList!=null) {
              for (TNodeRouteCondition nodeRouteCondition : nodeRouteConditionList) {
                  nodeRouteCondition.setNodeRouteId(nodeRoute.getId());
                  nodeRouteConditionService.saveOrUpdate(nodeRouteCondition);
              }
          }
     }


     /**
      * @param processVo 流程vo
      * @param processId 流程id
      * @Description: 保存节点
      * @Author: hgw
      * @Date: 2020/7/27 14:11
      * @return: void
      **/
     private R saveOrUpdateNode(ProcessVo processVo, String processId) {
          //保存之前先进行节点重合判断
          String flag = saveBeforeCheckoverlap(processVo.getProcessNodeList());
          if (Common.isNotKong(flag)){
               return R.failed(flag);
          }
          for (TProcessNode processNode : processVo.getProcessNodeList()) {
               processNode.setProcessId(processId);
               if (Boolean.TRUE.equals(Common.isNotKong(processNode.getId()))) {
                    processNodeService.updateById(processNode);
               } else {
                    processNodeService.save(processNode);
               }
               saveNodePromission(processId, processNode);
               saveNodeReaderPromission(processId, processNode);
               saveOrUpdateNodeTransferConfigs(processNode);
          }
          return null;
     }

     /**
      * 功能描述: 保存节点前先进行做坐标重合判断
      * @Param: [processNodeList]
      * @Return: java.lang.Boolean
      * @Author: wangdayu
      * @Date: 2023/10/31 14:26
      * @Since:
      */
     private String saveBeforeCheckoverlap(List<TProcessNode> processNodeList) {
          if (Common.isNotKong(processNodeList)){
               for (TProcessNode first : processNodeList) {
                    for (TProcessNode second : processNodeList) {
                         if (Common.isNotKong(first.getLogoTitle())
                                 &&Common.isNotKong(second.getLogoTitle())
                                 &&!first.getLogoTitle().equals(second.getLogoTitle())){
                              //这里和前端保持一致逻辑，坐标差值在5以内，判定为重复节点
                              if (Math.abs(Double.valueOf(first.getCoordinatex()) - Double.valueOf(second.getCoordinatex())) <Double.valueOf(CommonConstants.FIVE_STRING)
                                      && Math.abs(Double.valueOf(first.getCoordinatey()) - Double.valueOf(second.getCoordinatey()))<Double.valueOf(CommonConstants.FIVE_STRING)){
                                   return "存在节点位置重复";
                              }
                         }
                    }
               }

               Set<String> logoTitleSet = processNodeList.stream().map(TProcessNode::getLogoTitle).collect(Collectors.toSet());
               if (processNodeList.size() != logoTitleSet.size()){
                    return "存在节点标志重复";
               }
          }
          return CommonConstants.EMPTY_STRING;

     }


     /**
      * 保存子流程
      * @param processNode
      */
     private void saveOrUpdateNodeTransferConfigs(TProcessNode processNode){
          List<TNodeTransferConfig> nodeRouteConditionList = processNode.getNodeTransferConfigs();
          if(nodeRouteConditionList!=null) {
              for (TNodeTransferConfig nodeTransferConfig : nodeRouteConditionList) {
                  nodeTransferConfig.setNodeId(processNode.getId());
                  nodeTransferConfigService.saveOrUpdate(nodeTransferConfig);
              }
          }
     }


     /**
      * @param deleteIdsVo 需要删除的ids
      * @Description: 删除流程内的相关
      * @Author: hgw
      * @Date: 2020/7/27 11:10
      * @return: void
      **/
     private void deleteIds(DeleteProcessIdsVo deleteIdsVo) {
          if (deleteIdsVo != null) {
               // 删除子流程节点
               deleteNodeTransferConfig(deleteIdsVo);
               // 删除线权限
               deleteRoteCondition(deleteIdsVo);
               // 删除权限
               deletePrimission(deleteIdsVo);
               // 删除抄送
               deleteReadPrimission(deleteIdsVo);
               // 删除节点路由
               deleteRoute(deleteIdsVo);
               // 删除流程节点
               deleteNode(deleteIdsVo);
          }
     }

     /**
      * @param deleteIdsVo 删除id
      * @Description: 删除流程节点
      * @Author: hgw
      * @Date: 2020/7/27 11:26
      * @return: void
      **/
     private void deleteNode(DeleteProcessIdsVo deleteIdsVo) {
          if (Boolean.TRUE.equals(Common.isNotKong(deleteIdsVo.getNodeIds()))
                  && deleteIdsVo.getNodeIds().length > 0) {
               for (String id : deleteIdsVo.getNodeIds()) {
                    processNodeService.removeById(id);
               }
          }
     }

     /**
      * 删除子流程
      * @param deleteIdsVo
      */
     private void deleteNodeTransferConfig(DeleteProcessIdsVo deleteIdsVo) {
          if (Boolean.TRUE.equals(Common.isNotKong(deleteIdsVo.getNodeTransferConfigIds()))
                  && deleteIdsVo.getNodeTransferConfigIds().length > 0) {
               for (String id : deleteIdsVo.getNodeTransferConfigIds()) {
                    nodeTransferConfigService.removeById(id);
               }
          }
     }

     /**
      * @param deleteIdsVo 删除id
      * @Description: 删除线
      * @Author: hgw
      * @Date: 2020/7/27 11:26
      * @return: void
      **/
     private void deleteRoute(DeleteProcessIdsVo deleteIdsVo) {
          if (Boolean.TRUE.equals(Common.isNotKong(deleteIdsVo.getRoteIds()))
                  && deleteIdsVo.getRoteIds().length > 0) {
               for (String id : deleteIdsVo.getRoteIds()) {
                    nodeRouteService.removeById(id);
               }
          }
     }

     /**
      * @param deleteIdsVo 删除id
      * @Description: 删除线权限id
      * @Author: hgw
      * @Date: 2020/7/27 11:26
      * @return: void
      **/
     private void deleteRoteCondition(DeleteProcessIdsVo deleteIdsVo) {
          if (Boolean.TRUE.equals(Common.isNotKong(deleteIdsVo.getRoteConditionIds()))
                  && deleteIdsVo.getRoteConditionIds().length > 0) {
               for (String id : deleteIdsVo.getRoteConditionIds()) {
                    nodeRouteConditionService.removeById(id);
               }
          }
     }
     /**
      * @param deleteIdsVo 删除id
      * @Description: 删除抄送
      * @Author: hgw
      * @Date: 2020/7/27 11:26
      * @return: void
      **/
     private void deleteReadPrimission(DeleteProcessIdsVo deleteIdsVo) {
          if (Boolean.TRUE.equals(Common.isNotKong(deleteIdsVo.getReadPrimissionIds()))
                  && deleteIdsVo.getReadPrimissionIds().length > 0) {
               for (String id : deleteIdsVo.getReadPrimissionIds()) {
                    nodeReaderPromissionService.removeById(id);
               }
          }
     }

     /**
      * @param deleteIdsVo 删除id
      * @Description: 删除权限
      * @Author: hgw
      * @Date: 2020/7/27 11:26
      * @return: void
      **/
     private void deletePrimission(DeleteProcessIdsVo deleteIdsVo) {
          if (Boolean.TRUE.equals(Common.isNotKong(deleteIdsVo.getPrimissionIds()))
                  && deleteIdsVo.getPrimissionIds().length > 0) {
               for (String id : deleteIdsVo.getPrimissionIds()) {
                    nodePrimissionService.removeById(id);
               }
          }
     }

     /**
      * @param processId   流程id
      * @param processNode 节点
      * @Description: 保存抄送
      * @Author: hgw
      * @Date: 2020/7/24 20:18
      * @return: void
      **/
     private void saveNodeReaderPromission(String processId, TProcessNode processNode) {
          if (processNode.getNodeReaderPromissionList() != null) {
               for (TNodeReaderPromission nodeReaderPrimission : processNode.getNodeReaderPromissionList()) {
                    nodeReaderPrimission.setProcessId(processId);
                    nodeReaderPrimission.setNodeId(processNode.getId());
                    if (Boolean.TRUE.equals(Common.isNotKong(nodeReaderPrimission.getId()))) {
                         nodeReaderPromissionService.updateById(nodeReaderPrimission);
                    } else {
                         nodeReaderPromissionService.save(nodeReaderPrimission);
                    }
               }
          }
     }

     /**
      * @param processId   流程id
      * @param processNode 节点
      * @Description: 保存权限
      * @Author: hgw
      * @Date: 2020/7/24 20:19
      * @return: void
      **/
     private void saveNodePromission(String processId, TProcessNode processNode) {
          if (processNode.getNodePrimissionList() != null) {
               for (TNodePrimission nodePrimission : processNode.getNodePrimissionList()) {
                    nodePrimission.setProcessId(processId);
                    nodePrimission.setNodeId(processNode.getId());
                    if (Boolean.TRUE.equals(Common.isNotKong(nodePrimission.getId()))) {
                         nodePrimissionService.updateById(nodePrimission);
                    } else {
                         nodePrimissionService.save(nodePrimission);
                    }
               }
          }
     }

     /**
      * @param processId 流程id
      * @Description: 删除流程以及节点、路由
      * @Author: hgw
      * @Date: 2020/7/17 17:22
      * @return: com.yifu.cloud.plus.v1.yifu.common.core.util.R
      **/
     @Override
     public R deleteById(String processId) {
          if (Boolean.TRUE.equals(Common.isEmpty(processId))) {
               return R.failed("流程id不可为空！");
          }
          // 删除节点路由
          nodeRouteService.deleteByProcessId(processId);
          // 删除流程节点
          processNodeService.deleteByProcessId(processId);
          // 主流程表
          this.removeById(processId);
          return R.ok("删除成功");
     }

     /**
      * @param vo
      * @Author: wangan
      * @Date: 2021/6/16
      * @Description:  根据不同类型判断是
      * @return: com.yifu.cloud.plus.v1.yifu.common.core.util.R
      * @see com.yifu.cloud.plus.v1.process.service.impl
      *  类型 1客户合同审批 2客户合同办理 3客户合同归档 4垫付 5crm客户审批
      *  如果类型非 合同办理和合同归档，则判断部门
      *  如果类型为  合同办理和合同归档，为用章档案
      *  如果数据为空。则直接过，为了兼容hr页面
      **/
     @Override
     @Transactional
     public R<String> add(TProcessViewVo vo) {
          TProcess tProcess = new TProcess();
          BeanCopyUtils.copyProperties(vo, tProcess);
          if (Common.isEmpty(vo.getProcessIsUse())){
               //设置默认在用
               tProcess.setProcessIsUse(CommonConstants.ZERO_STRING);
          }
          if (Common.isNotKong(vo.getType())) {
               // 若选则了通用
               //if (CommonConstants.ZERO_STRING.equals(vo.getCommonUse())){
                    return commonUseSave(vo, tProcess);
//               } else {
//               	// 1.7.5 只留通用流程
//                    if (departIdType.contains(vo.getType())) {
//                         return addDepartConfs(vo, tProcess);
//                    } else {
//                         return R.failCheckGeneric("未知的类型", CommonConstants.NULL);
//                    }
//               }

          } else {
               this.save(tProcess);
               return R.ok(CommonConstants.NULL,ResultConstants.SUCCESS_INFO);
          }
     }


     /**
      * @param vo
      * @Author: wangan
      * @Date: 2021/6/16
      * @Description: 修改
      * @return: com.yifu.cloud.plus.v1.yifu.common.core.util.R<java.lang.String>
      * @see com.yifu.cloud.plus.v1.process.service.impl
      * 新增逻辑不变。增加删除逻辑
      **/
     @Override
     @Transactional
     public R<String> modify(TProcessViewVo vo) {
          TProcess tProcess = new TProcess();
          BeanCopyUtils.copyProperties(vo, tProcess);
          if (Common.isNotKong(vo.getType())) {
               // todo 1.7.5 只留通用流程若选则了通用
               //if (CommonConstants.ZERO_STRING.equals(vo.getCommonUse())){
                    return commonUseSave(vo, tProcess);
               //}
//               if (departIdType.contains(vo.getType())) {
//                    if (vo.getDepartIds()!=null && !vo.getDepartIds().isEmpty()) {
//                         R<String> addDepartConfsR = addDepartConfs(vo, tProcess);
//                         if(addDepartConfsR==null ||addDepartConfsR.getCode()!=CommonConstants.SUCCESS){
//                              throw new CheckedException(addDepartConfsR.getMsg());
//                         }
//                    }
//                    if(vo.getDelDepartIds()!=null && !vo.getDelDepartIds().isEmpty()){
//                         //删除部门配置
//                          processApprovalConfService.remove(Wrappers.<TProcessApprovalConf>query().lambda()
//                                 .eq(TProcessApprovalConf::getType, vo.getType()).eq(TProcessApprovalConf::getDeleteFlag, CommonConstants.ZERO_STRING)
//                                 .in(TProcessApprovalConf::getFieldValue, vo.getDelDepartIds()));
//                    }
//                    this.updateById(tProcess);
//                    return R.successCheckGeneric(ResultConstants.SUCCESS_INFO,CommonConstants.NULL);
//               } else {
//                    return R.failCheckGeneric("未知的类型", CommonConstants.NULL);
//               }
          } else {
               this.updateById(tProcess);
               return R.ok(CommonConstants.NULL,ResultConstants.SUCCESS_INFO);
          }
     }

     /**
      * @param id
      * @Author: wangan
      * @Date: 2021/6/18
      * @Description: 数据都重置为假删除
      * @return: com.yifu.cloud.plus.v1.yifu.common.core.util.R<java.lang.String>
      * @see com.yifu.cloud.plus.v1.process.service.impl
      **/
     @Override
     public R<String> delete(String id) {
          TProcess process = this.getById(id);
          if (process == null) {
               return R.failed(CommonConstants.NULL,ResultConstants.FAIL_INFO_NO_MODEL);
          }
          //更新配置表为删除
          TProcessApprovalConf processApprovalConf = new TProcessApprovalConf();
          processApprovalConf.setDeleteFlag(CommonConstants.DELETE_FLAG);
          processApprovalConfService.update(processApprovalConf,Wrappers.<TProcessApprovalConf>query().lambda()
                  .eq(TProcessApprovalConf::getProcessId,id));
          //更新流程表为删除
          process.setDeleteFlag(CommonConstants.DELETE_FLAG);
          this.updateById(process);
          return R.ok(CommonConstants.NULL,ResultConstants.SUCCESS_INFO);
     }


     /**
      * @param vo
      * @param tProcess
      * @Author: wangdayu
      * @Date: 2023年10月27日10:45
      * @Description: 通用流程保存逻辑
      * @return: com.yifu.cloud.plus.v1.yifu.common.core.util.R<java.lang.String>
      * @see com.yifu.cloud.plus.v1.process.service.impl
      **/
     private R<String> commonUseSave(TProcessViewVo vo, TProcess tProcess) {
          LambdaQueryWrapper<TProcessApprovalConf> query = new LambdaQueryWrapper<>();
          //获取该类型下面的通用流程配置,并判断当前类型的流程是否是在用流程，若是，则提示重复，否则正常保存
          query.eq(TProcessApprovalConf::getType, vo.getType())
                  .eq(TProcessApprovalConf::getDeleteFlag, CommonConstants.ZERO_STRING)
                  .and(wq -> wq.isNull(TProcessApprovalConf::getFieldValue).or()
                          .eq(TProcessApprovalConf::getFieldValue, CommonConstants.EMPTY_STRING));
          List<TProcessApprovalConf> commonProcess = processApprovalConfService.list(query);
          //存在该类型的流程配置
          if (Common.isNotKong(commonProcess)) {
               Boolean inUse = judgeInuse(commonProcess);
               if (inUse) {
                    if (Common.isEmpty(vo.getId())){
                         return R.failed("当前流程类型存在正在使用的流程");
                    }
               }
          }
          //删除部门配置
          processApprovalConfService.remove(Wrappers.<TProcessApprovalConf>query().lambda()
                  .eq(TProcessApprovalConf::getType, vo.getType())
                  .eq(TProcessApprovalConf::getProcessId,vo.getId())
                  .eq(TProcessApprovalConf::getDeleteFlag, CommonConstants.ZERO_STRING));
          //校验通过后插入数据
          if(Common.isEmpty(vo.getId())) {
               //如果没有id则是新增
               this.save(tProcess);
          }
          TProcessApprovalConf processApprovalConf = new TProcessApprovalConf();
          processApprovalConf.setType(vo.getType());
          if (departIdType.contains(vo.getType())) {
               processApprovalConf.setClassName("OrganizationInfo");
               processApprovalConf.setFieldName("id");
          } else if (chapterUnitType.contains(vo.getType())) {
               processApprovalConf.setClassName("TCustomerContract");
               processApprovalConf.setFieldName("chapterUnit");
          }
          processApprovalConf.setDeleteFlag(CommonConstants.ZERO_STRING);
          processApprovalConf.setFieldValue(CommonConstants.EMPTY_STRING);
          processApprovalConf.setParentId(CommonConstants.ZERO_STRING);
          processApprovalConf.setProcessId(tProcess.getId());
          processApprovalConf.setRemark(tProcess.getName());
          processApprovalConfService.save(processApprovalConf);
          this.updateById(tProcess);
          return R.ok(CommonConstants.NULL,ResultConstants.SUCCESS_INFO);
     }

     /**
      * 功能描述: 校验当前类型流程是否存在在用
      * @Param: [processId]
      * @Return: java.lang.Boolean
      * @Author: wangdayu
      * @Date: 2023/10/27 10:32
      * @Since:
      */
     private Boolean judgeInuse(List<TProcessApprovalConf> tprocessApprovalConf) {
          if (Common.isNotKong(tprocessApprovalConf)) {
               Set<String> processId = tprocessApprovalConf.stream().map(TProcessApprovalConf::getProcessId)
                       .collect(Collectors.toSet());
               //在流程表里面判断是否是在用流程
               List<TProcess> tProcesses = this.listByIds(processId);
               if (Common.isNotKong(tProcesses)) {
                    Boolean inUseFlag = tProcesses.stream().anyMatch(
                            t -> (CommonConstants.ZERO_STRING.equals(t.getProcessIsUse())
                                    && CommonConstants.NOT_DELETE_FLAG.equals(t.getDeleteFlag())));
                    //若当前类型的流程配置存在在用，则提示重复
                    return inUseFlag;
               }

          }
          return Boolean.FALSE;
     }


     @Override
     public R<String> noUse(TProcess tProcess) {
          //1.参数校验
          if (Common.isEmpty(tProcess.getId())){
			  return R.failed("id不能为空");
          }

          //2.实体是否存在校验
          TProcess process = this.getById(tProcess.getId());
          if (Common.isEmpty(process)){
               return R.failed(FAIL_INFO_NO_MODEL);
          }

          //3.修改条件封装:实体存在则进行状态修改
          UpdateWrapper<TProcess> updateWrapper = new UpdateWrapper();
          updateWrapper.lambda()
                  .eq(TProcess::getId,tProcess.getId())
                  .eq(TProcess::getDeleteFlag, CommonConstants.NOT_DELETE_FLAG)
                  .set(TProcess::getProcessIsUse,CommonConstants.ONE_STRING);

          //4.返回结果
          if (this.update(updateWrapper)){
               return R.ok(ResultConstants.MODIFY_SUCCESS);
          }
          return R.failed(ResultConstants.MODIFY_FAIL);
     }

     /**
      * 根据角色ID获取关联流程
      *
      * @param tProcess 审批角色
      * @return IPage<TProcessViewVo>
      * @author chenyuxi
      * @date 2023-10-23 09:48:57
      * @since crm2.12.0
      */
     @Override
     public IPage<TProcessViewVo> getProcessPageByRoleId(Page<TProcessViewVo> page, TProcessViewVo tProcess) {
          Set<String> processIds = new HashSet<>();
          // 查关联角色的流程ID
          LambdaQueryWrapper<TNodePrimission> nodePrimissionQuery = Wrappers.<TNodePrimission>lambdaQuery()
                  .eq(TNodePrimission::getApprovalRole, tProcess.getRole())
                  .eq(TNodePrimission::getType, tProcess.getNodePermissionType());

          List<TNodePrimission> nodePrimissionList = nodePrimissionService.list(nodePrimissionQuery);

          if(Common.isNotKong(nodePrimissionList)) {
               processIds = nodePrimissionList.stream().map(TNodePrimission::getProcessId).collect(Collectors.toSet());
          }
          // 查关联角色的抄送流程ID t_node_reader_promission
          LambdaQueryWrapper<TNodeReaderPromission> nodeReaderPrimissionQuery = Wrappers.<TNodeReaderPromission>lambdaQuery()
                  .eq(TNodeReaderPromission::getApprovalRole, tProcess.getRole())
                  .eq(TNodeReaderPromission::getType, tProcess.getNodePermissionType());

          List<TNodeReaderPromission> nodeReaderPrimissionList = nodeReaderPromissionService.list(nodeReaderPrimissionQuery);

          if(Common.isNotKong(nodeReaderPrimissionList)) {
               for(TNodeReaderPromission nodeReaderPromission : nodeReaderPrimissionList) {
                    processIds.add(nodeReaderPromission.getProcessId());
               }
          }
          if(Common.isEmpty(processIds)) {
               return null;
          }

          // 传流程ID集合查流程列表
          tProcess.setProcessIds(processIds);
          return this.getTProcessPage(page, tProcess,CommonConstants.ZERO_STRING);
     }

     @Override
     public String checkProcessByRoleId(TProcessViewVo tProcess) {
          LambdaQueryWrapper<TNodePrimission> nodePrimissionQuery = Wrappers.<TNodePrimission>lambdaQuery()
                  .eq(TNodePrimission::getApprovalRole, tProcess.getRole())
                  .eq(TNodePrimission::getType, tProcess.getNodePermissionType());

          List<TNodePrimission> nodePrimissionList = nodePrimissionService.list(nodePrimissionQuery);

          LambdaQueryWrapper<TNodeReaderPromission> nodeReaderPrimissionQuery = Wrappers.<TNodeReaderPromission>lambdaQuery()
                  .eq(TNodeReaderPromission::getApprovalRole, tProcess.getRole())
                  .eq(TNodeReaderPromission::getType, tProcess.getNodePermissionType());

          List<TNodeReaderPromission> nodeReaderPrimissionList = nodeReaderPromissionService.list(nodeReaderPrimissionQuery);

          if(nodePrimissionList.size() == 0 && nodeReaderPrimissionList.size() == 0) {
               return CommonConstants.ZERO_STRING;
          } else {
               Set<String> processIds = new HashSet<>();
               if(Common.isNotKong(nodePrimissionList)) {
                    processIds = nodePrimissionList.stream().map(TNodePrimission::getProcessId).collect(Collectors.toSet());
               }
               if(Common.isNotKong(nodeReaderPrimissionList)) {
                    for(TNodeReaderPromission nodeReaderPromission : nodeReaderPrimissionList) {
                         processIds.add(nodeReaderPromission.getProcessId());
                    }
               }
               // 检测关联的流程是否被删除
               LambdaQueryWrapper<TProcess> processQuery = Wrappers.<TProcess>lambdaQuery()
                       .in(TProcess::getId, processIds)
                       .eq(TProcess::getDeleteFlag, CommonConstants.ZERO_STRING);

               long processCount = this.count(processQuery);
               if(processCount == 0) {
                    return CommonConstants.ZERO_STRING;
               }
          }

          return CommonConstants.ONE_STRING;
     }
}
