package com.ho.flow.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Snowflake;
import com.fasterxml.jackson.databind.JsonNode;
import com.ho.common.tools.constant.CommonConstant;
import com.ho.common.tools.entity.SimpleUser;
import com.ho.common.tools.exception.BaseResponseCode;
import com.ho.common.tools.exception.BusinessException;
import com.ho.common.tools.exception.DataResult;
import com.ho.flow.common.FlowTool;
import com.ho.flow.constant.WorkOrderConstant;
import com.ho.flow.entity.WorkOrderSub;
import com.ho.flow.entity.WorkOrderPlan;
import com.ho.flow.feignclient.UserFeignClient;
import com.ho.flow.mapper.WorkOrderSubMapper;
import com.ho.flow.service.ProcessFlowService;
import com.ho.flow.service.WorkOrderService;
import com.ho.flow.vo.req.workorder.*;
import com.ho.flow.vo.resp.workorder.FallBackTaskResp;
import com.ho.flow.vo.resp.workorder.HisTaskResp;
import com.ho.flow.vo.resp.workorder.TaskDone;
import com.ho.flow.vo.resp.workorder.WorkOrderRespVO;
import com.ho.user.api.entity.SysSubDict;
import com.ho.user.api.entity.SysUser;
import com.ho.user.api.vo.req.QueryUserReqVO;
import lombok.extern.slf4j.Slf4j;
import org.activiti.bpmn.model.*;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricVariableInstance;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author fancl
 * @desc: 工作流实现类
 * @date 2023/2/5
 */
@Service
@Slf4j
public class ProcessFlowServiceImpl implements ProcessFlowService {

    //工作流 定义的处理类
    @Autowired
    RuntimeService runtimeService;

    @Autowired
    HistoryService historyService;

    @Autowired
    RepositoryService repositoryService;

    //工作流 Task处理类
    @Autowired
    TaskService taskService;

    @Autowired
    WorkOrderService workOrderService;

    @Autowired
    WorkOrderSubMapper workOrderSubMapper;

    @Autowired
    UserFeignClient userFeignClient;

    @Autowired
    FlowTool flowTool;

    @Autowired
    Snowflake snowflake;

    //流程定义的key
    @Value("${flow.workOrder.procDefKey}")
    String procDefKey;

    //根据taskId查询任务
    @Override
    public Task getTaskById(TaskUserReq taskUserReq) {
        //1.代办人是自己的
        String tenantId = String.valueOf(taskUserReq.getTenantId());
        Task task = taskService.createTaskQuery()
                .processDefinitionKey(procDefKey)
                .processInstanceId(taskUserReq.getProcessInstId())
                //.processVariableValueEquals(WorkOrderConstant.orderType, "workOrder")
                .taskTenantId(tenantId)
                .singleResult();
        return task;
    }

    /**
     * 代办列表
     * 数据来自以下几个部分：
     * 1.处理人是自己的 2.候选人中有自己
     *
     * @param simpleUser
     * @return
     */
    @Override
    public Map<String, List<Task>> getTodoList(SimpleUser simpleUser) {
        //1.代办人是自己的
        String tenantId = String.valueOf(simpleUser.getGroupId());
        String assignee = simpleUser.getUserId();
        List<Task> assigneeTaskList = taskService.createTaskQuery()
                .processDefinitionKey(procDefKey)
                //.processVariableValueEquals(WorkOrderConstant.orderType, "workOrder")
                .taskTenantId(tenantId)
                .taskAssignee(assignee)
                .list();
        //2.查候选人有自己的
        List<Task> candidateTaskList = taskService.createTaskQuery()
                .processDefinitionKey(procDefKey)
                //.processVariableValueEquals(WorkOrderConstant.orderType, "workOrder")
                .taskTenantId(tenantId)
                //候选人有自己的
                .taskCandidateUser(assignee)
                .list();
        //集合合并
        Map<String, List<Task>> taskMap = new HashMap<>();

        taskMap.put(WorkOrderConstant.WorkOrderStatus.notProcessed, candidateTaskList);
        taskMap.put(WorkOrderConstant.WorkOrderStatus.processing, assigneeTaskList);
        return taskMap;
    }

    //查任务附属信息进行填充
    @Override
    public List<TaskDone> getToDoListFromTask(Map<String, List<Task>> taskMap, DoListTaskReq doListTaskReq) {
        //创建返回结果对象
        List<TaskDone> doneList = new ArrayList<>();

        //对任务的状态分别处理
        if (taskMap.containsKey(WorkOrderConstant.WorkOrderStatus.processing)) {
            List<Task> processingList = taskMap.get(WorkOrderConstant.WorkOrderStatus.processing);
            //处理中的任务
            for (Task task : processingList) {
                String processInstanceId = task.getProcessInstanceId();
                WorkOrderRespVO workOrder = new WorkOrderRespVO();
                if (doListTaskReq != null && doListTaskReq.getTitle() != null) {
                    workOrder = workOrderService.findByProcInstIdAndTitle(processInstanceId, doListTaskReq.getTitle());
                } else {
                    workOrder = workOrderService.findByProcInstId(processInstanceId);
                }
                if (workOrder != null) {
                    TaskDone taskDone = new TaskDone();
                    taskDone.setId(workOrder.getId().toString());
                    taskDone.setOrderType(workOrder.getOrderType());
                    taskDone.setTitle(workOrder.getTitle());
                    taskDone.setPlanTitle(workOrder.getPlanTitle());
                    //根据任务id和流程id查询节点变量
                    HistoricVariableInstance historicVariableInstance = historyService.createHistoricVariableInstanceQuery()
                            .taskId(task.getId())
                            .processInstanceId(task.getProcessInstanceId())
                            .variableName(WorkOrderConstant.sender)
                            .singleResult();
                    if (historicVariableInstance != null) {
                        Object value = historicVariableInstance.getValue();
                        if (value.toString() != null) {
                            //根据用户id查询用户名称
                            taskDone.setStartUserId(value.toString());
                            DataResult<SysUser> user = userFeignClient.getUserById(value.toString());
                            if (user.getData() != null) {
                                taskDone.setStartUserName(user.getData().getRealName());
                            }
                        }
                    }
                    taskDone.setStartTime(task.getCreateTime());
                    taskDone.setProcessInstanceId(task.getProcessInstanceId());
                    //查询字典表中优先级的值

                    Integer priority = workOrder.getPriority();
                    if (priority != null) {
                        DataResult<SysSubDict> result = userFeignClient.getDictById(priority);
                        if (result.getData() != null) {
                            taskDone.setPriority(result.getData().getValue());
                        } else {
                            //设置为1，避免空指针
                            taskDone.setPriority("1");
                        }
                    }
                    //任务状态统一设置为代办
                    taskDone.setStatus(WorkOrderConstant.WorkOrderStatus.processing);
                    doneList.add(taskDone);
                }
            }
        }
        //未处理的任务
        if (taskMap.containsKey(WorkOrderConstant.WorkOrderStatus.notProcessed)) {
            List<Task> notProcessedList = taskMap.get(WorkOrderConstant.WorkOrderStatus.notProcessed);
            //处理中的任务
            for (Task task : notProcessedList) {
                String processInstanceId = task.getProcessInstanceId();
                WorkOrderRespVO workOrder = new WorkOrderRespVO();
                if (doListTaskReq != null && doListTaskReq.getTitle() != null) {
                    workOrder = workOrderService.findByProcInstIdAndTitle(processInstanceId, doListTaskReq.getTitle());
                } else {
                    workOrder = workOrderService.findByProcInstId(processInstanceId);
                }
                if (workOrder != null) {
                    TaskDone taskDone = new TaskDone();
                    taskDone.setId(workOrder.getId().toString());
                    taskDone.setOrderType(workOrder.getOrderType());
                    taskDone.setTitle(workOrder.getTitle());
                    taskDone.setPlanTitle(workOrder.getPlanTitle());
                    taskDone.setStartTime(task.getCreateTime());
                    //根据任务id和流程id查询节点变量
                    HistoricVariableInstance historicVariableInstance = historyService.createHistoricVariableInstanceQuery()
                            .taskId(task.getId())
                            .processInstanceId(task.getProcessInstanceId())
                            .variableName(WorkOrderConstant.sender)
                            .singleResult();
                    if (historicVariableInstance != null) {
                        Object value = historicVariableInstance.getValue();
                        if (value.toString() != null) {
                            //根据用户id查询用户名称
                            DataResult<SysUser> user = userFeignClient.getUserById(value.toString());
                            if (user.getData() != null) {
                                taskDone.setStartUserName(user.getData().getRealName());
                            }
                        }
                        if (workOrder.getPriority() != null) {
                            DataResult<SysSubDict> result = userFeignClient.getDictById(workOrder.getPriority());
                            if (result.getData() != null) {
                                taskDone.setPriority(result.getData().getValue());
                            }
                        }
                    }
                    taskDone.setProcessInstanceId(task.getProcessInstanceId());
                    //任务状态统一设置为未处理
                    taskDone.setStatus(WorkOrderConstant.WorkOrderStatus.notProcessed);
                    doneList.add(taskDone);
                }
            }
        }
        return doneList;
    }


    //保存工单并发起工单流程
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String saveOrderAndStartProcess(WorkOrderAddReqVO workOrderAddReqVO) {
        //生成id和工单号
        String nextWorkOrderId = flowTool.getNextWorkOrderId(WorkOrderConstant.IdTypeWorkOrder);
        log.info("工单号: {}", nextWorkOrderId);
        //发起一个流程
        //tenantId
        String tenantId = String.valueOf(workOrderAddReqVO.getGroupId());
        //流程变量,包括工单类型, 站id
        Map<String, Object> variables = new HashMap<>(16);
        //工单类型 保存后不可修改
        variables.put(WorkOrderConstant.orderType, workOrderAddReqVO.getOrderType());
        //电站 保存后不可以修改
        variables.put(WorkOrderConstant.stationId, workOrderAddReqVO.getStationId());
        //发起人
        variables.put(WorkOrderConstant.startUser, workOrderAddReqVO.getUserId());
        //发送人
        variables.put(WorkOrderConstant.sender, workOrderAddReqVO.getUserId());
        try {
            //为了工单和流程相互关联,先生成流程数据再生成工单数据
            ProcessInstance processInstance = runtimeService
                    .startProcessInstanceByKeyAndTenantId(procDefKey, nextWorkOrderId, variables, tenantId);
            //流程实例id
            String processInstanceId = processInstance.getProcessInstanceId();
            log.info("工单流程实例id: {}", processInstanceId);
            long nextId = snowflake.nextId();
            workOrderAddReqVO.setId(nextId);
            workOrderAddReqVO.setOrderId(nextWorkOrderId);
            //工单关联流程实例id
            workOrderAddReqVO.setProcessId(processInstanceId);
            //设置任务主题
            String planTitle = workOrderAddReqVO.getPlanTitle();
            workOrderAddReqVO.setTitle(planTitle);
            //默认值
            workOrderAddReqVO.setDeleted(CommonConstant.DELETED);
            //生成一个工单对象
            workOrderService.add(workOrderAddReqVO);
            return processInstanceId;
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new BusinessException(BaseResponseCode.WORK_ORDER_ADD_ERROR);
        }

    }

    /**
     * 工单详情
     *
     * @return
     */
    @Override
    public WorkOrderRespVO getOrderDetail() {
        return null;
    }

    //接受任务
    @Override
    public void doClaimTask(TaskUserReq taskReq) {
        Task task = taskService.createTaskQuery().processInstanceId(taskReq.getProcessInstId())
                //集团Id一定要带着
                .taskTenantId(taskReq.getTenantId())
                .singleResult();
        //判断任务是否存在,还要判断任务是否已经被认领了
        if (task != null) {
            try {
                taskService.claim(task.getId(), taskReq.getUserId());
            } catch (Exception e) {
                log.error("认领任务时出错 ,task:{}, userId: {}", task.getId(), taskReq.getUserId());
                log.error(e.getMessage());
                //throw new BusinessException(BaseResponseCode.TASK_ALREADY_CLAIM_BY_OTHER);
            }
        }
    }

    /**
     * 完成任务
     */
    @Override
    public void doCompleteTask(DoTaskReq doTaskReq) {
        //先查这个任务
        Task task = taskService.createTaskQuery()
                //流程id查询
                .processInstanceId(doTaskReq.getProcessInstId())
                //集团id
                .taskTenantId(doTaskReq.getTenantId())
                //要使用责任人查询, 避免去做别人的任务
                //.taskAssignee(taskReq.getAssigneeUser())
                .singleResult();
        //如果没查到任务,报错
        if (task == null) {
            log.error("对应的任务不存在");
            throw new BusinessException(BaseResponseCode.TASK_NOT_EXISTS);
        }

        //判断该任务是否是当前人,不是就报错
        //todo 后续要打开
        /*if (!taskReq.getAssigneeUser().equals(task.getAssignee())) {
            throw new BusinessException(BaseResponseCode.TASK_IS_NOT_YOURS);
        }*/
        //下一个节点代办人
        List<String> candidateUserList = doTaskReq.getCandidateUserList();
        if (!WorkOrderConstant.TaskNodeName.node4.equals(task.getTaskDefinitionKey())) {
            if (candidateUserList == null || candidateUserList.isEmpty()) {
                throw new BusinessException(BaseResponseCode.TASK_CHOICE_CANDIDATE_USER);
            }
        }
        //完成 设置本地环境变量 complete==0
        Map<String, Object> variables = new HashMap<>();
        variables.put(WorkOrderConstant.completeKey, WorkOrderConstant.complete);
        variables.put(WorkOrderConstant.CandidateUser.nodeOneUsers, candidateUserList);
        //先使用local 设置完成标识变量
        //始终用这个名字的变量,不然还需要判断当前是第几节点
        taskService.setVariableLocal(task.getId(), WorkOrderConstant.CandidateUser.nodeOneUsers, candidateUserList);
        taskService.setVariableLocal(task.getId(), WorkOrderConstant.completeKey, WorkOrderConstant.complete);
        taskService.setVariableLocal(task.getId(), WorkOrderConstant.suggestion, doTaskReq.getSuggestion());
        taskService.setVariableLocal(task.getId(), WorkOrderConstant.sender, doTaskReq.getSenderId());
        try {
            taskService.complete(task.getId());
        } catch (Exception e) {
            log.error("完成任务时出错 ,task:{}, userId: {}", task.getId(), doTaskReq.getAssigneeUser());
            log.error(e.getMessage());
        }
    }


    /**
     * 作废任务
     *
     * @param doTaskReq
     */
    @Override
    public void doNullifyTaskTask(DoTaskReq doTaskReq) {
        //先查这个任务
        Task task = taskService.createTaskQuery()
                //用任务id查询
                .processInstanceId(doTaskReq.getProcessInstId())
                //集团id
                .taskTenantId(doTaskReq.getTenantId())
                //要使用责任人查询, 避免去做别人的任务
                //.taskAssignee(taskReq.getAssigneeUser())
                .singleResult();
        //如果没查到任务,报错
        if (task == null) {
            log.error("对应的任务不存在");
            throw new BusinessException(BaseResponseCode.TASK_NOT_EXISTS);
        }
        if (!WorkOrderConstant.TaskNodeName.node1.equals(task.getTaskDefinitionKey())) {
            log.error("对应的任务不在第一节点");
            throw new BusinessException(BaseResponseCode.TASK_IS_NOT_FIRST);
        }
        //判断该任务是否是当前人,不是就报错
        //todo 后续要打开
        /*if (!taskReq.getAssigneeUser().equals(task.getAssignee())) {
            throw new BusinessException(BaseResponseCode.TASK_IS_NOT_YOURS);
        }*/
        //下一个节点代办人
        List<String> candidateUserList = doTaskReq.getCandidateUserList();
        //完成 设置本地环境变量 complete==0
        Map<String, Object> variables = new HashMap<>();
        variables.put(WorkOrderConstant.completeKey, WorkOrderConstant.complete);
        variables.put(WorkOrderConstant.CandidateUser.nodeOneUsers, candidateUserList);
        //先使用local 设置完成标识变量
        //始终用这个名字的变量,不然还需要判断当前是第几节点
        taskService.setVariableLocal(task.getId(), WorkOrderConstant.CandidateUser.nodeOneUsers, candidateUserList);
        taskService.setVariableLocal(task.getId(), WorkOrderConstant.completeKey, WorkOrderConstant.nullifyComplete);
        taskService.setVariableLocal(task.getId(), WorkOrderConstant.sender, doTaskReq.getAssigneeUser());
        taskService.setVariableLocal(task.getId(), WorkOrderConstant.suggestion, doTaskReq.getSuggestion());
        try {
            taskService.complete(task.getId());
        } catch (Exception e) {
            log.error("完成任务时出错 ,task:{}, userId: {}", task.getId(), doTaskReq.getAssigneeUser());
            log.error(e.getMessage());
        }
    }

    /**
     * 退回任务
     */
    @Override
    public void doRejectTask(RejectTaskReq rejectTaskReq) {
        //先查这个任务
        Task task = taskService.createTaskQuery()
                //用流程id查询
                .processInstanceId(rejectTaskReq.getProcessInstId())
                //集团id
                .taskTenantId(rejectTaskReq.getTenantId())
                //要使用责任人查询, 避免去做别人的任务
                //.taskAssignee(taskReq.getAssigneeUser())
                .singleResult();
        //如果没查到任务,报错
        if (task == null) {
            log.error("对应的任务不存在");
            throw new BusinessException(BaseResponseCode.TASK_NOT_EXISTS);
        }

        List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery()
                //流程id
                .processInstanceId(rejectTaskReq.getProcessInstId())
                //任务定义key
                .taskDefinitionKey(rejectTaskReq.getTaskDefinitionKey())
                //集团id
                .taskTenantId(rejectTaskReq.getTenantId())
                .list();

        //候选人id集合
        List<String> candidateUserList = new ArrayList<>();
        for (HistoricTaskInstance historicTaskInstance : list) {
            boolean contains = candidateUserList.contains(historicTaskInstance.getAssignee());
            if (!contains) {
                candidateUserList.add(historicTaskInstance.getAssignee());
            }
        }
        //获取complete值
        String complete = rejectTaskReq.getTaskDefinitionKey().substring(1);
        taskService.setVariableLocal(task.getId(), WorkOrderConstant.CandidateUser.nodeOneUsers, candidateUserList);
        taskService.setVariableLocal(task.getId(), WorkOrderConstant.completeKey, complete);
        taskService.setVariableLocal(task.getId(), WorkOrderConstant.suggestion, rejectTaskReq.getSuggestion());
        taskService.setVariableLocal(task.getId(), WorkOrderConstant.sender, rejectTaskReq.getUserId());
        try {
            taskService.complete(task.getId());
        } catch (Exception e) {
            log.error("回退任务时出错 ,task:{}", task.getId());
            log.error(e.getMessage());
        }
    }

    @Override
    public void doDiscardTask(TaskReq taskReq) {

    }

    /**
     * 获取回退任务列表
     *
     * @param fallBackTaskReq
     */
    @Override
    public List<FallBackTaskResp> getFallBackTask(FallBackTaskReq fallBackTaskReq) {
        //创建返回值对象
        List<FallBackTaskResp> fallBackTaskRespList = new ArrayList<>();
        //获取所有历史节点任务
        List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(fallBackTaskReq.getProcessInstId())
                .orderByHistoricTaskInstanceStartTime().asc().list();

        if (historicTaskInstanceList.isEmpty() || historicTaskInstanceList == null) {
            return fallBackTaskRespList;
        }

        //先查这个任务
        Task task = taskService.createTaskQuery()
                //用任务id查询
                .processInstanceId(fallBackTaskReq.getProcessInstId())
                //集团id
                .taskTenantId(fallBackTaskReq.getTenantId())
                //要使用责任人查询, 避免去做别人的任务
                //.taskAssignee(taskReq.getAssigneeUser())
                .singleResult();

        //判断任务是否存在,还要判断任务是否已经被认领了
        if (task != null) {
            try {
                String taskDefinitionKey = task.getTaskDefinitionKey();
                //获取当前任务节点的数字
                String substring = taskDefinitionKey.substring(1);
                Integer currentNumber = Integer.valueOf(substring);

                Map<String, List<HistoricTaskInstance>> hisTaskMap = historicTaskInstanceList.stream()
                        //过滤当前任务以后的节点
                        .filter(s -> {
                            String number = s.getTaskDefinitionKey().substring(1);
                            Integer integer = Integer.valueOf(number);
                            return currentNumber > integer;
                        })
                        //转化为以name分组的map
                        .collect(Collectors.groupingBy(HistoricTaskInstance::getName));


                //遍历map并赋值
                for (String key : hisTaskMap.keySet()) {
                    List<HistoricTaskInstance> historicTaskInstances = hisTaskMap.get(key);
                    FallBackTaskResp resp = new FallBackTaskResp();
                    resp.setName(key);
                    resp.setProcessInstId(fallBackTaskReq.getProcessInstId());
                    //历史任务的id集合
                    List<String> taskInstIds = new ArrayList<>();
                    for (HistoricTaskInstance historicTaskInstance : historicTaskInstances) {
                        taskInstIds.add(historicTaskInstance.getId());
                        resp.setTaskDefinitionKey(historicTaskInstance.getTaskDefinitionKey());
                    }
                    resp.setTaskInstIds(taskInstIds);
                    fallBackTaskRespList.add(resp);
                }
                return fallBackTaskRespList;
            } catch (Exception e) {
                log.error("获取回退任务列表出错 ,task:{}, processInstanceId: {}", task.getId(), fallBackTaskReq.getProcessInstId());
                log.error(e.getMessage());
            }
        }
        return fallBackTaskRespList;

    }

    @Override
    public List<HistoricTaskInstance> getDoneList(SimpleUser simpleUser) {
        //1.代办人是自己的
        String tenantId = String.valueOf(simpleUser.getGroupId());
        String assignee = simpleUser.getUserId();
        List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery()
                .processDefinitionKey(procDefKey)
                //.processVariableValueEquals(WorkOrderConstant.orderType, "workOrder")
                .taskTenantId(tenantId)
                .taskAssignee(assignee)
                .list();


        //集合合并
        List<HistoricTaskInstance> taskList = new ArrayList<>();

        //查询到流程id集合
        List<String> processInstanceIds = new ArrayList<>();
        for (HistoricTaskInstance historicTaskInstance : list) {
            boolean flag = processInstanceIds.contains(historicTaskInstance.getProcessInstanceId());
            if (!flag) {
                processInstanceIds.add(historicTaskInstance.getProcessInstanceId());
            }
        }

        //根据流程id遍历查询
        for (String processInstanceId : processInstanceIds) {
            List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery()
                    .processDefinitionKey(procDefKey)
                    .taskTenantId(tenantId)
                    .processInstanceId(processInstanceId)
                    .list();
            taskList.addAll(historicTaskInstanceList);
        }

        return taskList;
    }

    @Override
    public List<TaskDone> getDoneListFromTask(List<HistoricTaskInstance> taskList, DoListTaskReq doListTaskReq) {
        // 一个流程实例对应多个任务,汇总拿到流程实例
        Map<String, WorkOrderRespVO> procInstIdsMap = new HashMap<>();
        for (HistoricTaskInstance task : taskList) {
            String procInstKey = task.getProcessInstanceId();
            //减少查询次数
            if (!procInstIdsMap.containsKey(procInstKey)) {
                //找到流程所对应的流程id
                String processInstanceId = task.getProcessInstanceId();
                WorkOrderRespVO workOrder = new WorkOrderRespVO();
                if (doListTaskReq != null && doListTaskReq.getTitle() != null) {
                    workOrder = workOrderService.findByProcInstIdAndTitle(processInstanceId, doListTaskReq.getTitle());
                } else {
                    workOrder = workOrderService.findByProcInstId(processInstanceId);
                }
                //一个任务一个发起人,所以再去查发起人对应的人名
                if (workOrder != null) {
                    procInstIdsMap.put(procInstKey, workOrder);
                }
            }
        }
        List<TaskDone> doneList = new ArrayList<>();

        List<QueryUserReqVO> queryUserReqVOS = new ArrayList<>();

        for (HistoricTaskInstance task : taskList) {
            WorkOrderRespVO workOrder = procInstIdsMap.get(task.getProcessInstanceId());
            if (workOrder != null) {
                //创建taskDone对象并填充属性
                TaskDone taskDone = new TaskDone();
                taskDone.setId(workOrder.getId().toString());
                taskDone.setOrderType(workOrder.getOrderType());
                taskDone.setTitle(workOrder.getTitle());
                taskDone.setPlanTitle(workOrder.getPlanTitle());
                taskDone.setStartUserId(workOrder.getUserId());
                //根据任务id和流程id查询节点变量
                HistoricVariableInstance historicVariableInstance = historyService.createHistoricVariableInstanceQuery()
                        .taskId(task.getId())
                        .processInstanceId(task.getProcessInstanceId())
                        .variableName(WorkOrderConstant.sender)
                        .singleResult();
                if (historicVariableInstance != null) {
                    Object value = historicVariableInstance.getValue();
                    if (value.toString() != null) {
                        taskDone.setStartUserId(value.toString());
                        //把用户id添加到集合中
                        QueryUserReqVO queryUserReqVO = new QueryUserReqVO();
                        queryUserReqVO.setUserId(value.toString());
                        taskDone.setStartUserId(value.toString());
                        queryUserReqVOS.add(queryUserReqVO);
                    }
                }
                if (task.getEndTime() != null) {
                    taskDone.setStartTime(task.getEndTime());
                } else {
                    taskDone.setStartTime(task.getStartTime());
                }
                taskDone.setProcessInstanceId(task.getProcessInstanceId());
                if (!doneList.contains(taskDone)) {
                    doneList.add(taskDone);
                }
            }
        }

        //根据id查询到用户集合
        DataResult<List<SysUser>> result = userFeignClient.queryUser(queryUserReqVOS);
        List<SysUser> users = new ArrayList<>();
        if (result.getData() != null) {
            users = result.getData();
        }

        //查询任务状态并给发起人赋值
        for (TaskDone taskDone : doneList) {
            if (taskDone.getStartUserId() != null) {
                if (!users.isEmpty()) {
                    for (SysUser user : users) {
                        if (user.getId().equals(taskDone.getStartUserId())) {
                            taskDone.setStartUserName(user.getRealName());
                            break;
                        }
                    }
                }
            }
            Task task = taskService.createTaskQuery()
                    .processInstanceId(taskDone.getProcessInstanceId())
                    .singleResult();
            if (task != null) {
                taskDone.setStatus(WorkOrderConstant.WorkOrderStatus.processing);
            } else {
                taskDone.setStatus(WorkOrderConstant.WorkOrderStatus.completed);
            }
        }
        return doneList;
    }

    @Override
    public List<HisTaskResp> getCirculationTask(CirculationTaskReq taskReq) {
        //创建返回对象
        List<HisTaskResp> hisTaskRespList = new ArrayList<>();
        //获取所有历史节点任务
        List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(taskReq.getProcessInstId())
                .orderByHistoricTaskInstanceStartTime().asc().list();


        //循环遍历赋值
        for (HistoricTaskInstance historicTaskInstance : historicTaskInstanceList) {
            HisTaskResp hisTaskResp = new HisTaskResp();

            hisTaskResp.setName(historicTaskInstance.getName());
            if (WorkOrderConstant.create.equals(historicTaskInstance.getName())) {
                hisTaskResp.setStartTime(historicTaskInstance.getStartTime());
            }
            if (historicTaskInstance.getClaimTime() != null) {
                hisTaskResp.setStartTime(historicTaskInstance.getClaimTime());
            }
            String processInstanceId = historicTaskInstance.getProcessInstanceId();

            //根据任务id和流程id查询complete变量
            HistoricVariableInstance historicVariableInstance = historyService.createHistoricVariableInstanceQuery()
                    .taskId(historicTaskInstance.getId())
                    .processInstanceId(processInstanceId)
                    .variableName(WorkOrderConstant.completeKey)
                    .singleResult();
            if (historicVariableInstance != null) {
                String value = historicVariableInstance.getValue().toString();
                Integer complete = Integer.valueOf(value);
                //为0表示同意
                if (WorkOrderConstant.complete.equals(complete)) {
                    hisTaskResp.setStatus(WorkOrderConstant.WorkOrderStatus.agree);
                } else if (complete == null) {
                    hisTaskResp.setStatus(null);
                } else {
                    hisTaskResp.setStatus(WorkOrderConstant.WorkOrderStatus.refuse);
                }
            }


            String userId = historicTaskInstance.getAssignee();
            //历史任务中执行人id为不为空直接查询
            if (userId != null) {
                DataResult<SysUser> result = userFeignClient.getUserById(userId);
                SysUser user = result.getData();
                if (user != null) {
                    hisTaskResp.setUserName(user.getRealName());
                } else {
                    hisTaskResp.setUserName("");
                }
            }
            //为空则需要去查询流程变量
            else {
                //根据任务id和流程id查询候选人列表变量
                HistoricVariableInstance candidateUsers = historyService.createHistoricVariableInstanceQuery()
                        .taskId(historicTaskInstance.getId())
                        .processInstanceId(processInstanceId)
                        .variableName(WorkOrderConstant.CandidateUser.nodeOneUsers)
                        .singleResult();
                JsonNode value = (JsonNode) candidateUsers.getValue();
                if (value != null) {
                    for (JsonNode jsonNode : value) {
                        String id = jsonNode.asText();
                        //遍历赋值给执行人
                        DataResult<SysUser> result = userFeignClient.getUserById(id);
                        if (result.getData() != null) {
                            //第一个直接赋值
                            if (hisTaskResp.getUserName() == null) {
                                hisTaskResp.setUserName(result.getData().getRealName());
                            }
                            //后续的用逗号隔开继续添加
                            else {
                                String userName = hisTaskResp.getUserName();
                                boolean flag = userName.contains(result.getData().getRealName());
                                if (!flag) {
                                    userName = userName + "," + result.getData().getRealName();
                                    hisTaskResp.setUserName(userName);
                                }
                            }
                        }
                    }
                }
            }
            //建议需要去流程变量去查
            HistoricVariableInstance value = historyService.createHistoricVariableInstanceQuery()
                    .taskId(historicTaskInstance.getId())
                    .processInstanceId(historicTaskInstance.getProcessInstanceId())
                    .variableName(WorkOrderConstant.suggestion)
                    .singleResult();
            if (value != null) {
                String suggestion = (String) value.getValue();
                hisTaskResp.setSuggestion(suggestion);
            }
            if (historicTaskInstance.getEndTime() != null) {
                hisTaskResp.setEndTime(hisTaskResp.getEndTime());
                long l = DateUtil.betweenMs(historicTaskInstance.getStartTime(), historicTaskInstance.getEndTime());
                BigDecimal ms = new BigDecimal(l);
                BigDecimal taskTime = ms.divide(new BigDecimal("3600000"), 2, BigDecimal.ROUND_HALF_UP);
                hisTaskResp.setTaskTime(taskTime);
                hisTaskResp.setEndTime(historicTaskInstance.getEndTime());
            } else {
                hisTaskResp.setEndTime(null);
                hisTaskResp.setTaskTime(BigDecimal.ZERO);
                //没有结束时间,则没有对应的状态和建议实则为空
                hisTaskResp.setStatus(null);
                hisTaskResp.setSuggestion(null);
            }

            hisTaskRespList.add(hisTaskResp);
        }
        return hisTaskRespList;
    }

    @Override
    public void planAddWorkOrder(WorkOrderPlan workOrderPlan, List<String> userIds,List<WorkOrderSub> workOrderSubs) {
        //先创建工单
        WorkOrderAddReqVO reqVO = new WorkOrderAddReqVO();
        BeanUtils.copyProperties(workOrderPlan,reqVO);
        reqVO.setWorkOrderSubs(workOrderSubs);
        String processInstanceId = saveOrderAndStartProcess(reqVO);
        //在对工单进行流转
        DoTaskReq doTaskReq = new DoTaskReq();
        doTaskReq.setProcessInstId(processInstanceId);
        //设置发送者的id
        doTaskReq.setSenderId(workOrderPlan.getUserId());
        doTaskReq.setTenantId(String.valueOf(workOrderPlan.getGroupId()));
        doTaskReq.setCandidateUserList(userIds);
        //完成任务的责任人必须和自己相同,否则需要给出提示
        doTaskReq.setAssigneeUser(workOrderPlan.getUserId());
        doCompleteTask(doTaskReq);
    }

    /**
     * 根据集团id部署工作流
     * @param groupId
     */
    @Override
    public void deploymentWorkflow(Integer groupId) {
        String fileName = "processes/workOrder.bpmn20.xml";
        if (groupId != null) {
            Deployment deployment = repositoryService.createDeployment()
                    .addClasspathResource(fileName)
                    .name("工单流程")
                    .tenantId(groupId.toString())
                    //.category("workOrder")
                    .deploy();
        }else {
            throw new BusinessException(BaseResponseCode.GROUP_ID_IS_NULL);
        }
    }

    //获取下一个节点的任务名
    @Override
    public String getNextTaskName(String processInstId) {
        //当前任务信息
        Task task = taskService.createTaskQuery().processInstanceId(processInstId).singleResult();
        if (task == null) {
            return "";
        }
        //流程实例id
        String processInstanceId = task.getProcessInstanceId();
        //获取
        // 流程发布Id信息
        String definitionId = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId).singleResult().getProcessDefinitionId();
        //获取bpm对象
        BpmnModel bpmnModel = repositoryService.getBpmnModel(definitionId);
        //传节点定义key 获取当前节点
        FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(task.getTaskDefinitionKey());
        //输出连线
        List<SequenceFlow> outgoingFlows = flowNode.getOutgoingFlows();

        //当前任务id  d1 d2
        String currentTaskId = task.getTaskDefinitionKey();
        String currentNode = currentTaskId.substring(1);
        //遍历返回下一个节点信息
        for (SequenceFlow outgoingFlow : outgoingFlows) {
            //类型自己判断
            FlowElement targetFlowElement = outgoingFlow.getTargetFlowElement();
            //用户任务
            if (targetFlowElement instanceof UserTask) {
                //找 name比它大的
                String nextTaskId = targetFlowElement.getId();
                nextTaskId = nextTaskId.substring(1);
                if (nextTaskId.compareTo(currentNode) > 0) {
                    log.info("下一任务id: {}", nextTaskId);
                    return targetFlowElement.getName();
                }
            } else if (targetFlowElement instanceof ExclusiveGateway) {
                //排他网关,继续
                //setExclusiveGateway(targetFlowElement);
                continue;
            } else if (targetFlowElement instanceof EndEvent) {
                //结束事件,返回结束点名称
                return targetFlowElement.getName();
            }
        }
        return "";
    }


    private void setExclusiveGateway(FlowElement targetFlow) {
        //排他网关，获取连线信息
        List<SequenceFlow> targetFlows = ((ExclusiveGateway) targetFlow).getOutgoingFlows();
        for (SequenceFlow sequenceFlow : targetFlows) {
            //目标节点信息
            FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement();
            if (targetFlowElement instanceof UserTask) {
                // do something
            } else if (targetFlowElement instanceof EndEvent) {
                // do something
            } else if (targetFlowElement instanceof ServiceTask) {
                // do something
            } else if (targetFlowElement instanceof ExclusiveGateway) {
                //递归寻找
                setExclusiveGateway(targetFlowElement);
            } else if (targetFlowElement instanceof SubProcess) {
                // do something
            }
        }
    }
}
