package cn.fateverse.workflow.service.impl;

import cn.fateverse.workflow.constant.ProcessConstant;
import cn.fateverse.workflow.entity.bpmn.*;
import cn.fateverse.workflow.mapper.*;
import cn.hutool.core.util.StrUtil;
import cn.fateverse.admin.entity.User;
import cn.fateverse.common.core.entity.Option;
import cn.fateverse.common.core.exception.CustomException;
import cn.fateverse.common.core.result.page.TableDataInfo;
import cn.fateverse.common.core.utils.ObjectUtils;
import cn.fateverse.workflow.entity.FormPerm;
import cn.fateverse.workflow.entity.HistoricalOperation;
import cn.fateverse.workflow.entity.bo.AnalysisProcessBo;
import cn.fateverse.workflow.entity.bo.VariablesBo;
import cn.fateverse.workflow.entity.dto.TaskDto;
import cn.fateverse.workflow.entity.vo.FormItemData;
import cn.fateverse.workflow.entity.vo.HistoricalOperationVo;
import cn.fateverse.workflow.entity.vo.task.TaskResultVo;
import cn.fateverse.workflow.entity.vo.task.TaskVo;
import cn.fateverse.workflow.enums.ModeEnums;
import cn.fateverse.workflow.enums.OperationStateEnums;
import cn.fateverse.workflow.enums.OperationEnums;
import cn.fateverse.workflow.process.ProcessServiceUtils;
import cn.fateverse.workflow.process.cmd.RollbackUserTaskCmd;
import cn.fateverse.workflow.service.ProcessService;
import cn.fateverse.workflow.service.ProcessTaskService;
import cn.fateverse.workflow.process.FormItemParseUtil;
import cn.fateverse.common.mybatis.utils.PageUtils;
import cn.fateverse.common.core.utils.TableSupport;
import cn.fateverse.common.security.utils.SecurityUtils;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.Process;
import org.flowable.editor.language.json.converter.util.CollectionUtils;
import org.flowable.engine.*;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl;
import org.flowable.engine.runtime.ActivityInstance;
import org.flowable.task.api.Task;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 流程任务流转实现
 *
 * @author Clay
 * @date 2022/12/24
 */
@Slf4j
@Service
public class ProcessTaskServiceImpl implements ProcessTaskService {

    //task任务服务
    private final TaskService taskService;
    //运行时服务
    private final RuntimeService runtimeService;
    //用户流程实例
    private final UserInstanceMapper userInstanceMapper;
    //资源服务
    private final RepositoryService repositoryService;
    //表单权限
    private final FormPermMapper formPermMapper;
    //表单数据
    private final FormItemDataMapper formItemDataMapper;
    //流程辅助
    private final ProcessMapper processMapper;
    //历史操作
    private final HistoricalOperationMapper operationMapper;
    //运行中的实例
    private final RunFlowableActinstMapper runFlowableActinstMapper;
    //历史记录
    private final HisFlowableActinstMapper hisFlowableActinstMapper;
    //流程引擎管理服务
    private final ManagementService managementService;


    public ProcessTaskServiceImpl(TaskService taskService,
                                  RuntimeService runtimeService,
                                  UserInstanceMapper userInstanceMapper,
                                  RepositoryService repositoryService,
                                  FormPermMapper formPermMapper,
                                  FormItemDataMapper formItemDataMapper,
                                  ProcessMapper processMapper,
                                  HistoricalOperationMapper operationMapper,
                                  RunFlowableActinstMapper runFlowableActinstMapper,
                                  HisFlowableActinstMapper hisFlowableActinstMapper,
                                  ManagementService managementService) {
        this.taskService = taskService;
        this.runtimeService = runtimeService;
        this.userInstanceMapper = userInstanceMapper;
        this.repositoryService = repositoryService;
        this.formPermMapper = formPermMapper;
        this.formItemDataMapper = formItemDataMapper;
        this.processMapper = processMapper;
        this.operationMapper = operationMapper;
        this.runFlowableActinstMapper = runFlowableActinstMapper;
        this.hisFlowableActinstMapper = hisFlowableActinstMapper;
        this.managementService = managementService;
    }


    @Override
    public TableDataInfo<TaskVo> searchTaskList() {
        //获取分页信息
        int pageSize = TableSupport.buildPageRequest().getPageSize();
        Integer startSize = PageUtils.getStartSize();
        //查询代办任务数据
        String userId = SecurityUtils.getUserId().toString();
        List<Task> taskList = taskService.createTaskQuery().taskAssignee(userId)
                .includeProcessVariables()
                .orderByTaskCreateTime().desc()
                .listPage(startSize, pageSize);
        if (null == taskList || taskList.isEmpty()) {
            return PageUtils.convertDataTable(null, 0L);
        }
        long count = taskService.createTaskQuery().taskAssignee(userId).count();
        //将 processInstanceId 抽离,然后进入到list获取到 ProcessInstanceImpl对象获取到创建时间和审批人等相关的数据
        List<String> processInstanceIdList = taskList.stream().map(Task::getProcessInstanceId).distinct().collect(Collectors.toList());
        Map<String, ExecutionEntityImpl> processInstanceMap = processMapper.selectProcessInstanceMapByList(processInstanceIdList);
        List<TaskVo> taskVoList = taskList.stream().map(task -> {
            TaskVo taskVo = toTaskVo(task);
            ExecutionEntityImpl executionEntity = processInstanceMap.get(task.getProcessInstanceId());
            if (null != executionEntity) {
                taskVo.setProcessName(executionEntity.getName());
                taskVo.setCreatedDate(executionEntity.getStartTime());
            }
            return taskVo;
        }).collect(Collectors.toList());
        return PageUtils.convertDataTable(taskVoList, count);

    }

    private TaskVo toTaskVo(Task task) {
        Map<String, Object> variables = task.getProcessVariables();
        User user = (User) task.getProcessVariables().get(ProcessConstant.START_USER_INFO);
        String processStatus = variables.get(ProcessConstant.PROCESS_STATUS).toString();
        return TaskVo.builder()
                .taskId(task.getId())
                .taskName(task.getName())
                .initiatorName(user.getNickName())
                .arriveDate(task.getCreateTime())
                .state(processStatus)
                .build();
    }

    @Override
    public TaskResultVo searchTaskByTaskId(String taskId) {
        //获取到task任务
        Task task = getTaskByTaskId(taskId, Boolean.TRUE);//查询出当前实例对应的表单数据
        List<HistoricalOperation> historicalOperationList = operationMapper.selectListByProcessInstanceId(task.getProcessInstanceId(), null);
        //筛选出没有呗mark的操作历史
        List<HistoricalOperation> operationNoMarkList = historicalOperationList.stream().filter(operation -> operation.getMark().equals(0)).collect(Collectors.toList());
        //将所有的操作历史转换为vo
        List<HistoricalOperationVo> operationList = ProcessServiceUtils.getHistoricalOperationVoList(historicalOperationList);
        //获取到变淡数据
        FormItemData formItemData = formItemDataMapper.selectByProcessInstanceId(task.getProcessInstanceId(), true);
        //获取到流程文件
        Process mainProcess = repositoryService.getBpmnModel(task.getProcessDefinitionId()).getMainProcess();
        //获取到bpmn中附带的参数
        Map<String, String> bpmnAttribute = ProcessServiceUtils.getBpmnValueAttribute(mainProcess);
        //获取到表单json
        String formItemsStr = bpmnAttribute.get(ProcessConstant.BPMN_FORM_ITEMS);
        //解析
        List<FormItem> formItems = JSON.parseArray(formItemsStr, FormItem.class);
        //获取到当前task对应的表单权限
        Map<String, FormPerm> fromPermMap = formPermMapper.selectListByFormKeyAndDeploymentId(task.getFormKey(), null);
        //解析表单数据
        JSONObject formData = JSON.parseObject(formItemData.getFormData());
        //将权限和表单数据进行整合,筛选掉需要影藏的表单项,并将表单权限放入到props中
        List<FormItem> itemPerms = FormItemParseUtil.checkFromItemPermsNew(formItems, fromPermMap, formData, true);
        String taskDefinitionKey = task.getTaskDefinitionKey();
        //获取到所有的bpmn节点对象
        String processStr = bpmnAttribute.get(ProcessConstant.BPMN_FORM_PROCESS);
        //获取到可以退回的节点数据
        List<ProcessNode> processNodeList = new ProcessService().analysisEndOption(operationNoMarkList, processStr, taskDefinitionKey);
        //转换成为option list
        List<Option> userTaskOption = processNodeList.stream().map(processNode -> Option.builder()
                .value(processNode.getId())
                .label(processNode.getName())
                .build()).collect(Collectors.toList());
        //获取到当前流程的用户信息
        User user = (User) task.getProcessVariables().get(ProcessConstant.START_USER_INFO);
        UserInfo userInfo = UserInfo.toUserInfo(user);
        return TaskResultVo.builder()
                .userTaskOption(userTaskOption)
                .formItems(itemPerms)
                .formData(formData)
                .operationList(operationList)
                .userInfo(userInfo)
                .build();
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void completeTask(TaskDto taskDto) {
        //获取到task任务
        Task task = getTaskByTaskId(taskDto.getTaskId(), Boolean.TRUE);
        //对表单数据进行处理
        VariablesBo variablesBo = screeningFromPerm(task, taskDto.getFormData());
        //添加评论信息
        addComment(taskDto.getComment(), task);
        HistoricalOperation operation = operationMapper.selectByProcessInstanceIdAndNodeId(task.getProcessInstanceId(), task.getTaskDefinitionKey());
        List<UserInfo> infoList = JSON.parseArray(operation.getUserInfo(), UserInfo.class);
        String userId = SecurityUtils.getUserId().toString();
        if (ModeEnums.AND.getTypeName().equals(operation.getApprovalMode())
                || ModeEnums.NEXT.getTypeName().equals(operation.getApprovalMode())) {
            boolean flag = true;
            for (UserInfo userInfo : infoList) {
                if (userInfo.getId().equals(userId)) {
                    userInfo.setState(OperationStateEnums.AGREE);
                } else {
                    flag = userInfo.getState().equals(OperationStateEnums.AGREE);
                }
            }
            if (flag) {
                operation.setFinishTime(new Date());
                operation.setState(OperationStateEnums.AGREE);
            }
        } else if (ModeEnums.OR.getTypeName().equals(operation.getApprovalMode())
                || ModeEnums.NORMAL.getTypeName().equals(operation.getApprovalMode())) {
            for (UserInfo userInfo : infoList) {
                if (userInfo.getId().equals(userId)) {
                    userInfo.setState(OperationStateEnums.AGREE);
                } else {
                    userInfo.setState(OperationStateEnums.PASS);
                }
            }
            operation.setFinishTime(new Date());
            operation.setState(OperationStateEnums.AGREE);
        }
        operation.setUserInfo(JSON.toJSONString(infoList));
        operationMapper.update(operation);
        //完成task
        taskService.complete(taskDto.getTaskId(), variablesBo.getVariables());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void refuseTask(TaskDto taskDto) {
        //获取到task任务
        Task task = getTaskByTaskId(taskDto.getTaskId(), Boolean.TRUE);
        Date finishTime = new Date();
        String userId = SecurityUtils.getUserId().toString();
        //获取到所有正在处理的节点信息
        List<HistoricalOperation> operationList = operationMapper.selectByProcessInstanceIdAndNotNodeId(task.getProcessInstanceId(), ProcessConstant.PROCESS_RUNNING);
        //遍历所有节点
        for (HistoricalOperation operation : operationList) {
            List<UserInfo> infoList = JSON.parseArray(operation.getUserInfo(), UserInfo.class);
            //如果与当前运行的节点相同,则进行拒绝的操作
            if (operation.getNodeId().equals(task.getTaskDefinitionKey())) {
                //遍历所有的用户
                for (UserInfo userInfo : infoList) {
                    //找到对应的用户
                    if (userInfo.getId().equals(userId)) {
                        userInfo.setState(OperationStateEnums.REFUSE);
                    } else {
                        //其他设置为pass
                        if (userInfo.getState().equals(OperationStateEnums.RUNNING)) {
                            userInfo.setState(OperationStateEnums.PASS);
                        }
                    }
                }
                taskAddComment(taskDto, operation);
                //更新当前历史操作的信息
                operation.setState(OperationStateEnums.REFUSE);
            } else {
                if (null != infoList && !infoList.isEmpty()) {
                    //不是当前节点则将所有的用户操作状态设置为pass
                    for (UserInfo userInfo : infoList) {
                        if (userInfo.getState().equals(OperationStateEnums.RUNNING)) {
                            userInfo.setState(OperationStateEnums.PASS);
                        }
                    }
                }
                //节点也设置为pass
                operation.setState(OperationStateEnums.PASS);
            }
            operation.setUserInfo(JSON.toJSONString(infoList));
            operation.setFinishTime(finishTime);
        }
        //批量更新节点信息
        operationMapper.batchUpdate(operationList);
        //获取流程数据,并设置为拒绝状态
        Map<String, Object> variables = task.getProcessVariables();
        variables.put(ProcessConstant.PROCESS_STATUS, ProcessConstant.BUSINESS_STATUS_REJECT);
        //将表单数据设置到流程中
        runtimeService.setVariables(task.getProcessInstanceId(), variables);
        //拒绝流程
        runtimeService.deleteProcessInstance(task.getProcessInstanceId(), "拒绝");
        userInstanceMapper.updateState(task.getProcessInstanceId(), ProcessConstant.BUSINESS_STATUS_REJECT);
    }

    private void taskAddComment(TaskDto taskDto, HistoricalOperation operation) {
        CommentInfo comment = taskDto.getComment();
        String context = comment.getContext();
        List<Attachment> attachments = comment.getAttachments();
        if (!StrUtil.isEmpty(context) || !ObjectUtils.isEmpty(attachments)) {
            operation.setMessage(JSON.toJSONString(comment));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delegateTas(TaskDto taskDto) {
        //获取到task任务
        Task task = getTaskByTaskId(taskDto.getTaskId(), Boolean.TRUE);
        //对表单数据进行处理
        VariablesBo variablesBo = screeningFromPerm(task, taskDto.getFormData());
        if (variablesBo.getFlag()) {
            runtimeService.setVariables(task.getProcessInstanceId(), variablesBo.getVariables());
        }
        //添加评论信息
        addComment(taskDto.getComment(), task);
        //设置好委托人
        UserInfo delegateUserInfo = taskDto.getDelegateUserInfo();
        taskService.delegateTask(task.getId(), delegateUserInfo.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void resolveCompleteTask(TaskDto taskDto) {
        //获取到task任务
        Task task = getTaskByTaskId(taskDto.getTaskId(), Boolean.TRUE);
        //对表单数据进行处理
        VariablesBo variablesBo = screeningFromPerm(task, taskDto.getFormData());
        //添加评论信息
        addComment(taskDto.getComment(), task);
        //委托人同意
        taskService.resolveTask(task.getId(), variablesBo.getVariables());
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void revokeTask(TaskDto taskDto) {
        //自己的才能够撤销
        //1. 判断当前流程是否是自己发起的
        Task task = getTaskByTaskId(taskDto.getTaskId(), Boolean.TRUE);
        VariablesBo variablesBo = screeningFromPerm(task, taskDto.getFormData());
        Map<String, Object> variables = variablesBo.getVariables();
        User user = (User) variables.get(ProcessConstant.START_USER_INFO);
        if (!user.getUserId().equals(SecurityUtils.getUserId())) {
            throw new CustomException("您不是发起人,无权撤销当前流程!");
        }
        //将流程状态设置为撤销
        variables.put(ProcessConstant.PROCESS_STATUS, ProcessConstant.BUSINESS_STATUS_REVOCATION);
        runtimeService.setVariables(task.getProcessInstanceId(), variables);
        //2. 进行撤销操作
        addComment(taskDto.getComment(), task);
        runtimeService.deleteProcessInstance(task.getProcessInstanceId(), "撤销");
        userInstanceMapper.updateState(task.getProcessInstanceId(), ProcessConstant.BUSINESS_STATUS_REVOCATION);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void assigneeTask(TaskDto taskDto) {
        //获取到task任务
        Task task = getTaskByTaskId(taskDto.getTaskId(), Boolean.TRUE);
        //对表单数据进行处理
        VariablesBo variablesBo = screeningFromPerm(task, taskDto.getFormData());
        if (variablesBo.getFlag()) {
            runtimeService.setVariables(task.getProcessInstanceId(), variablesBo.getVariables());
        }
        //添加评论信息
        addComment(taskDto.getComment(), task);
        //转办
        taskService.setAssignee(taskDto.getTaskId(), taskDto.getTransferUserInfo().getId());

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void rollbackTask(TaskDto taskDto) {
        //获取到task任务
        Task task = getTaskByTaskId(taskDto.getTaskId(), Boolean.TRUE);
        //获取到流程数据
        Process process = repositoryService.getBpmnModel(task.getProcessDefinitionId()).getProcesses().get(0);
        String processStr = process.getAttributes().get(ProcessConstant.BPMN_FORM_PROCESS).get(0).getValue();
        //获取到操作历史
        List<HistoricalOperation> operationList = operationMapper.selectListByProcessInstanceId(task.getProcessInstanceId(), 0);

        //获取到流程需要删除的数据信息
        List<ActivityInstance> activityInstanceList = runtimeService.createActivityInstanceQuery()
                .processInstanceId(task.getProcessInstanceId())
                .list();
        //解析需要改变和回滚的节点id
        AnalysisProcessBo processBo = new ProcessService().analysisProcessNodeAndRunningNode(operationList, processStr, task.getTaskDefinitionKey(), taskDto.getRollBackId(), activityInstanceList, process.getFlowElements());
        //需要改变的节点
        Set<String> changeNodeSet = processBo.getChangeNodeSet();
        //需要回滚的节点
        Set<String> rollbackNodeSet = processBo.getRollbackNodeSet();
        //初始化需要改变的历史操作记录
        List<HistoricalOperation> changeOperations = new ArrayList<>(rollbackNodeSet.size() + changeNodeSet.size());
        //将流程节点根据改变还是回滚进行数据清洗
        for (HistoricalOperation operation : operationList) {
            //当前节点还应特殊处理
            List<UserInfo> userInfos = JSON.parseArray(operation.getUserInfo(), UserInfo.class);
            if (operation.getNodeId().equals(task.getTaskDefinitionKey())) {
                log.info("此处对当前节点进行特殊处理");
                for (UserInfo userInfo : userInfos) {
                    if (userInfo.getState().equals(OperationStateEnums.RUNNING)) {
                        if (userInfo.getId().equals(SecurityUtils.getUserId().toString())) {
                            userInfo.setState(OperationStateEnums.ROLLBACK);
                        } else {
                            userInfo.setState(OperationStateEnums.PASS);
                        }
                    }
                }
                operation.setUserInfo(JSON.toJSONString(userInfos));
                operation.setMark(1);
                operation.setState(OperationStateEnums.ROLLBACK);
                changeOperations.add(operation);
            } else if (rollbackNodeSet.contains(operation.getNodeId())) {
                for (UserInfo userInfo : userInfos) {
                    if (userInfo.getState().equals(OperationStateEnums.RUNNING)) {
                        userInfo.setState(OperationStateEnums.PASS);
                    }
                }
                operation.setUserInfo(JSON.toJSONString(userInfos));
                operation.setMark(1);
                operation.setState(OperationStateEnums.PASS);
                changeOperations.add(operation);
                //需要改变状态的节点和回退目标节点
            } else if (changeNodeSet.contains(operation.getNodeId())) {
                operation.setMark(1);
                changeOperations.add(operation);
            }
        }
        //批量的处理需要更新的操作历史
        if (!changeOperations.isEmpty()) {
            operationMapper.batchUpdate(changeOperations);
        }
        //对表单数据进行处理
        addComment(taskDto.getComment(), task);
        //todo 签字信息后续添加
        addSignInfo(taskDto.getSignInfo(), task);
        //删除历史节点的信息
        deleteActivity(processBo);
        //回滚执行
        managementService.executeCommand(new RollbackUserTaskCmd(runtimeService, task, taskDto, processBo, process));
    }

    /**
     * 删除历史记录
     *
     * @param processBo
     */
    private void deleteActivity(AnalysisProcessBo processBo) {
        List<String> runActivityIds = new ArrayList<>(processBo.getActivityIdSet());
        if (CollectionUtils.isNotEmpty(runActivityIds)) {
            runFlowableActinstMapper.deleteRunActinstsByIds(runActivityIds);
            hisFlowableActinstMapper.deleteByIds(runActivityIds);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addMultiTask(TaskDto taskDto) {
        //获取到task任务
        Task task = getTaskByTaskId(taskDto.getTaskId(), Boolean.TRUE);
        Map<String, Object> variables = task.getProcessVariables();
        addComment(taskDto.getComment(), task);
        //进行加签操作
        variables.put(ProcessConstant.ASSIGNEE_NAME, taskDto.getMultiAddUserInfo().getId());
        runtimeService.addMultiInstanceExecution(task.getTaskDefinitionKey(), task.getProcessInstanceId(), variables);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void searchMultiUsersInfo(String taskId) {
        //1. 获取到任务信息
        Task task = getTaskByTaskId(taskId, Boolean.FALSE);
        List<Task> list = taskService.createTaskQuery()
                .processInstanceId(task.getProcessInstanceId())
                .taskDefinitionKey(task.getTaskDefinitionKey()).list();
        //2. 获取当前节点所有的task任务

        //3. 通过用户ids获取到对应的用户信息

        //4. 组装好数据返回
        System.out.println("输出加签的用户");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteMultiTask(String taskId) {
        //获取当前的task 任务
        Task task = getTaskByTaskId(taskId, Boolean.FALSE);
        //删除这个执行任务
        runtimeService.deleteMultiInstanceExecution(task.getExecutionId(), true);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addCommentTask(CommentInfo CommentInfo) {
        //获取当前的task 任务
        Task task = getTaskByTaskId(CommentInfo.getTaskId(), Boolean.FALSE);
        //添加评论
        addComment(CommentInfo, task);
    }

    /**
     * 过滤表单数据
     *
     * @param task
     * @param formStr
     * @return
     */
    private VariablesBo screeningFromPerm(Task task, String formStr) {
        Map<String, Object> variables = task.getProcessVariables();
        //获取当当前task的表单权限,将权限为 E 的写入到旧的表单中,向数据库插入一条新的数据,并将新插入的这一条数据设为当前数据
        Map<String, FormPerm> fromPermMap = formPermMapper.selectListByFormKeyAndDeploymentId(task.getFormKey(), null);
        if (!fromPermMap.isEmpty()) {
            JSONObject formData = JSON.parseObject(formStr);
            FormItemData formItemData = formItemDataMapper.selectByProcessInstanceId(task.getProcessInstanceId(), true);
            JSONObject formDataOld = JSON.parseObject(formItemData.getFormData());
            JSONObject formDataNew = FormItemParseUtil.checkFromDataPrem(formData, formDataOld, fromPermMap);
            formItemDataMapper.updatePresentStart(task.getProcessInstanceId());
            //入库表单数据
            FormItemData data = FormItemData.builder()
                    .isPresent(Boolean.TRUE)
                    .processInstanceId(task.getProcessInstanceId())
                    .formData(formDataNew.toJSONString())
                    .createBy(SecurityUtils.getUsername())
                    .build();
            formItemDataMapper.insert(data);
            //todo 获取到当前节点是否有参数传入
            //todo 流程实例启动时需要的参数
            //开始判断走审核通过的流程,此处还应该有评论数据入库
            variables.putAll(formDataNew);
            return VariablesBo.ok(variables);
        }
        return VariablesBo.no(variables);
    }

    /**
     * 获取到task 对象
     *
     * @param taskId   任务id
     * @param variable 是否需要参数
     * @return task任务对象
     */
    private Task getTaskByTaskId(String taskId, Boolean variable) {
        if (variable) {
            return taskService.createTaskQuery()
                    .includeProcessVariables()
                    .taskId(taskId)
                    .singleResult();
        } else {
            return taskService.createTaskQuery()
                    .taskId(taskId)
                    .singleResult();
        }
    }

    /**
     * 添加签字信息
     *
     * @param info 签字信息
     * @param task task任务对象
     */
    private void addSignInfo(String info, Task task) {
        if (!StrUtil.isEmpty(info)) {
            taskService.addComment(task.getId(), task.getProcessInstanceId(), ProcessConstant.COMMENT_SIGN, info);
        }
    }

    /**
     * 操作过程中填写的数据
     *
     * @param comment 评论对象
     * @param task    task任务对象
     */
    private void addComment(CommentInfo comment, Task task) {
        addComment(comment, task, OperationStateEnums.COMMENT, OperationEnums.COMMENT, "参与评论");
    }


    /**
     * 添加评论,后期可能会进行更改,只是添加评论,附加就加到评论信息内
     * todo 注释信息需要单独创建一张表存储
     *
     * @param comment       评论对象
     * @param task          task任务对象
     * @param start         评论类型
     * @param operationName 评论名称
     */
    private void addComment(CommentInfo comment, Task task, OperationStateEnums start, OperationEnums operation, String operationName) {
        String taskId = UUID.randomUUID().toString();
        addComment(comment, taskId, task.getProcessInstanceId(), start, operation, operationName);
    }


    private void addComment(CommentInfo comment, String taskId,
                            String processInstanceId,
                            OperationStateEnums start,
                            OperationEnums operationType,
                            String operationName) {
        //判断评论是否为空
        if (!ObjectUtils.isEmpty(comment)) {
            //判断评论内容是否为空
            String context = comment.getContext();
            List<Attachment> attachments = comment.getAttachments();
            if (!StrUtil.isEmpty(context) || !ObjectUtils.isEmpty(attachments)) {
                Date date = new Date();
                comment.setTaskId(taskId);
                User user = Objects.requireNonNull(SecurityUtils.getLoginUser()).getUser();
                UserInfo userInfo = UserInfo.toUserInfo(user);
                String message = JSON.toJSONString(comment);
                HistoricalOperation operation = HistoricalOperation.builder()
                        .taskId(taskId)
                        .processInstanceId(processInstanceId)
                        .message(message)
                        .operationName(operationName)
                        .operation(operationType)
                        .nodeId(taskId)
                        .state(start)
                        .finishTime(date)
                        .startTime(date.getTime())
                        .userInfo(JSON.toJSONString(Collections.singletonList(userInfo)))
                        .build();
                operationMapper.insert(operation);
            }
        }
    }

}
