package org.jeecg.modules.approval.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.activiti.bpmn.model.*;
import org.activiti.engine.*;
import org.activiti.engine.form.FormProperty;
import org.activiti.engine.form.TaskFormData;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricVariableInstance;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceBuilder;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.Constant;
import org.jeecg.common.exception.CustomException;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.common.utils.DictEnum;
import org.jeecg.common.utils.DictModelConstant;
import org.jeecg.common.utils.StringUtils;
import org.jeecg.modules.approval.model.dto.ApprovalOpinionDTO;
import org.jeecg.modules.approval.model.dto.DynamicFormConf;
import org.jeecg.modules.approval.model.vo.ApprovalOpinionVO;
import org.jeecg.modules.approval.model.vo.ApprovalVO;
import org.jeecg.modules.approval.service.ApprovalService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 审批业务实现
 *
 * @author yao
 */
@Slf4j
@Service("approvalService")
public class ApprovalServiceImpl implements ApprovalService {
    /**
     * 当前流程节点集合
     */
    public static final String CURR_TASK_NODES = "currTaskNodes";
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private FormService formService;


    /**
     *
     *  发起审批流程
     * @param approvalVO
     * @return
     */
    @Override
    public ProcessInstance addApproval(ApprovalVO approvalVO) {
        // 发起审批流程
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        Authentication.setAuthenticatedUserId(sysUser.getId());
        ProcessInstanceBuilder processInstanceBuilder = runtimeService.createProcessInstanceBuilder();
        processInstanceBuilder.processDefinitionKey(approvalVO.getBaseTask().getProcessKey());
        processInstanceBuilder.businessKey(approvalVO.getBusinessKey());
        processInstanceBuilder.variables(approvalVO.getBaseTaskVariables());
        ProcessInstance processInstance = processInstanceBuilder.start();
        return processInstance;
    }

    /**
     * 发起审批流程
     *tenantId 项目id
     * @param approvalVO
     * @return
     */
    @Override
    public ProcessInstance addApprovalTenantId(ApprovalVO approvalVO,String tenantId) {

        // 发起审批流程
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        Authentication.setAuthenticatedUserId(sysUser.getId());
        ProcessInstanceBuilder processInstanceBuilder = runtimeService.createProcessInstanceBuilder();
        processInstanceBuilder.tenantId(tenantId);
        processInstanceBuilder.processDefinitionKey(approvalVO.getBaseTask().getProcessKey());
        processInstanceBuilder.businessKey(approvalVO.getBusinessKey());
        processInstanceBuilder.variables(approvalVO.getBaseTaskVariables());
        ProcessInstance processInstance = processInstanceBuilder.start();
        return processInstance;
    }

    /**
     * 获取流程状态,已结束或不存在false, 存在true
     *
     * @param processInstanceId
     * @return
     */
    @Override
    public boolean getApprovalStatus(String processInstanceId) {

        ProcessInstance processInstance =
                runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        return processInstance != null;
    }

    /**
     * 审批处理
     *
     * @param approvalOpinionVO
     * @return
     */
    @Override
    public boolean handleApproval(ApprovalOpinionVO approvalOpinionVO) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        Task task = taskService.createTaskQuery()
                .taskId(approvalOpinionVO.getTaskId())
                .includeProcessVariables()    //定义参数
                .singleResult();  //单个结果
        if (task == null) {
            throw new CustomException("流程未启动或已执行完成");
        }
        if (StringUtils.isNotEmpty(task.getAssignee()) && !sysUser.getId().equals(task.getAssignee())) {
            throw new CustomException("当前用户不是审核人，无法进行审核");
        }


        if (StringUtils.isEmpty(task.getAssignee())) {
            Set<String> candidates = getCandiates(task.getId());
            if (candidates.isEmpty()) {
                throw new CustomException("当前用户不是审核人，无法进行审核");
            }
            if (candidates.contains(sysUser.getId())) {
                taskService.claim(task.getId(),sysUser.getId());
            }
        }

        Map<String, Object> processVariables = task.getProcessVariables();
        approvalOpinionVO.setCreateTime(new Date());
        approvalOpinionVO.setOpId(sysUser.getId());
        approvalOpinionVO.setOpName(sysUser.getRealname());
        approvalOpinionVO.setTaskNodeName(task.getName());
        Map<String, Object> map = Maps.newHashMap();
        map.put(Constant.ACT_TASK_FLAG, approvalOpinionVO.getFlag());

        //驳回操作
        if (DictEnum.APPLY_APPROVAL_OPINION_REJECT.getKey().equals(approvalOpinionVO.getFlag())) {
            return rejected(approvalOpinionVO, task, map);
        }
        //撤回到指定节点
        if (DictEnum.APPLY_APPROVAL_OPINION_ASSIGN.getKey().equals(approvalOpinionVO.getFlag())) {
            return runNodes(approvalOpinionVO, task, map);
        }
        // 审批信息叠加
        List<ApprovalOpinionDTO> opinionDTOS = new ArrayList<>();
        Object options = processVariables.get(Constant.ACT_APPLY_OPINION_LIST);
        if (options != null) {
            opinionDTOS = JSONObject.parseArray(options.toString(), ApprovalOpinionDTO.class);
        }
        ApprovalOpinionDTO applyOpinionDTO = new ApprovalOpinionDTO();
        //VO转为dto
        BeanUtils.copyProperties(approvalOpinionVO, applyOpinionDTO);

        opinionDTOS.add(applyOpinionDTO);
        map.put(Constant.ACT_APPLY_OPINION_LIST, JSONObject.toJSONString(opinionDTOS));
        taskService.complete(applyOpinionDTO.getTaskId(), map);
        return true;
    }

    /**
     * 获取当前任务下的候选人
     * 候选人>候选组 : 没有候选人时,再从候选组中查找
     *
     * @param taskId
     * @return
     */
    @Override
    public Set<String> getCandiates(String taskId) {
        Set<String> candiates = Sets.newHashSet();
        Set<String> groupIds = Sets.newHashSet();
        List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(taskId);
        for (IdentityLink identityLink : identityLinks) {
            if (Constant.ACT_CANDIDATE.equals(identityLink.getType())) {
                candiates.add(identityLink.getUserId());
            }
            if (StringUtils.isNotEmpty(identityLink.getGroupId())) {
                groupIds.add(identityLink.getGroupId());
            }
        }
        if (candiates.isEmpty()) {
            // TODO: 2020/5/19 候选人为空时,查询候选组中的人
        }
        return candiates;
    }

    @Override
    public  Map<String,String> getRunNodes(String processInstanceId) {

        Map<String, String> map = new LinkedHashMap<String, String>();
        // 获取流程历史中已执行节点，并按照节点在流程中执行先后顺序排序
        List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(processInstanceId)
                .activityType("userTask")
                .finished()
                .orderByHistoricActivityInstanceEndTime()
                .asc()
                .list();

        // 已执行的节点ID集合
        if (StringUtils.isNotEmpty(historicActivityInstanceList)) {
            // map = historicActivityInstanceList.stream().collect(Collectors.toMap(HistoricActivityInstance::getActivityId,HistoricActivityInstance::getActivityName,(k1,k2)->k1));
            for (HistoricActivityInstance historicActivityInstance : historicActivityInstanceList) {
                if (!map.containsKey(historicActivityInstance.getActivityId())) {
                    map.put(historicActivityInstance.getActivityId(), historicActivityInstance.getActivityName());
                }
            }
        }

        return map;
    }

    @Override
    public boolean autoHandleApproval(ApprovalOpinionVO approvalOpinionVO) {
        Task task = taskService.createTaskQuery()
                .taskId(approvalOpinionVO.getTaskId())
                // .executionId(approvalOpinionVO.getTaskId())
                .includeProcessVariables()
                .singleResult();
        if (task == null) {
            throw new CustomException("流程未启动或已执行完成");
        }

        Map<String, Object> processVariables = task.getProcessVariables();
        approvalOpinionVO.setCreateTime(new Date());
        approvalOpinionVO.setTaskNodeName(task.getName());
        Map<String, Object> map = Maps.newHashMap();
        map.put(Constant.ACT_TASK_FLAG, approvalOpinionVO.getFlag());
        // 审批信息叠加
        List<ApprovalOpinionDTO> opinionDTOS = new ArrayList<>();
        Object options = processVariables.get(Constant.ACT_APPLY_OPINION_LIST);
        if (options != null) {
            opinionDTOS = JSONObject.parseArray(options.toString(), ApprovalOpinionDTO.class);
        }
        ApprovalOpinionDTO applyOpinionDTO = new ApprovalOpinionDTO();
        //VO转为dto
        BeanUtils.copyProperties(approvalOpinionVO, applyOpinionDTO);
        opinionDTOS.add(applyOpinionDTO);
        map.put(Constant.ACT_APPLY_OPINION_LIST, JSONObject.toJSONString(opinionDTOS));
        taskService.complete(applyOpinionDTO.getTaskId(), map);
        return true;
    }

    /**
     * 根据 执行对象id获取审批信息
     *
     * @param processId
     * @return
     */
    @Override
    public List<ApprovalOpinionDTO> listApprovalDetail(String processId) {
        if (!StringUtils.isNotEmpty(processId)) {
            return Lists.newArrayList();
        }
        ProcessInstance instance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processId)
                .includeProcessVariables()
                .singleResult();
        // 保证运行ing
        List<ApprovalOpinionDTO> leaveList = Lists.newArrayList();
        if (instance != null) {
            Map<String, Object> variables = instance.getProcessVariables();
            if (StringUtils.isNotEmpty(variables) && variables.containsKey(Constant.ACT_APPLY_OPINION_LIST)) {
                Object obj = variables.get(Constant.ACT_APPLY_OPINION_LIST);
                if (StringUtils.isNotNull(obj)) {
                    leaveList = JSONObject.parseArray(obj.toString(), ApprovalOpinionDTO.class);
                }
            }
        } else {
            HistoricVariableInstance historicVariableInstance = historyService.createHistoricVariableInstanceQuery()
                    .processInstanceId(processId)
                    .variableName(Constant.ACT_APPLY_OPINION_LIST)
                    .singleResult();
            if (null != historicVariableInstance) {
                leaveList = JSONObject.parseArray(historicVariableInstance.getValue().toString(), ApprovalOpinionDTO.class);
            }
        }

        for (ApprovalOpinionDTO approvalOpinionDTO : leaveList) {
            if (StringUtils.isEmpty(approvalOpinionDTO.getFlagStr())) {
                approvalOpinionDTO.setFlagStr(DictEnum.getValue(DictModelConstant.MODEL_APPLY, DictModelConstant.MODEL_APPLY_APPROVAL_OPINION_FLAG, approvalOpinionDTO.getFlag()));
            }

            List<String> rejectStyle = Lists.newArrayList(DictEnum.Apply_APPROVAL_OPINION_REFUSE.getKey(),
                    DictEnum.APPLY_APPROVAL_OPINION_REJECT.getKey(),
                    DictEnum.APPLY_APPROVAL_OPINION_ABANDON.getKey(),
                    DictEnum.APPLY_APPROVAL_OPINION_ASSIGN.getKey());
            String style = rejectStyle.contains(approvalOpinionDTO.getFlag()) ? "error" : "success";
            approvalOpinionDTO.setStyle(style);
        }
        //按时间倒叙
        if (leaveList.size() > 0) {
            leaveList.sort(Comparator.comparing(ApprovalOpinionDTO::getCreateTime).reversed());
        }

        return leaveList;
    }

    /**
     * 驳回到上一步
     *
     * @param approvalOpinionVO
     * @return
     */
    @Override
    public boolean rejected(ApprovalOpinionVO approvalOpinionVO, Task task, Map<String, Object> map) {
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        String myTaskId = null;
        if (user.getId().equals(task.getAssignee())) {
            myTaskId = task.getId();
        }

        if (null == myTaskId) {
            throw new CustomException("当前用户无法驳回");
        }
        //获取当前节点
        String currActivityId = task.getTaskDefinitionKey();
        String processDefinitionId = task.getProcessDefinitionId();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        FlowNode currFlow = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currActivityId);

        if (null == currFlow) {
            List<SubProcess> subProcessList = bpmnModel.getMainProcess().findFlowElementsOfType(SubProcess.class, true);
            for (SubProcess subProcess : subProcessList) {
                FlowElement flowElement = subProcess.getFlowElement(currActivityId);
                if (flowElement != null) {
                    currFlow = (FlowNode) flowElement;
                    break;
                }
            }
        }

        //审批意见叠加
        Map<String, Object> variables = task.getProcessVariables();
        //拒绝,通过,驳回
        List<ApprovalOpinionDTO> approvalOpinionDTOs = new ArrayList<>();
        Object options = variables.get(Constant.ACT_APPLY_OPINION_LIST);
        if (null != options) {
            approvalOpinionDTOs = JSONObject.parseArray(options.toString(), ApprovalOpinionDTO.class);
        }
        ApprovalOpinionDTO applyOpinionDTO = new ApprovalOpinionDTO();
        //VO转为dto
        BeanUtils.copyProperties(approvalOpinionVO, applyOpinionDTO);
        approvalOpinionDTOs.add(applyOpinionDTO);
        map.put(Constant.ACT_APPLY_OPINION_LIST, JSONObject.toJSONString(approvalOpinionDTOs));

        //判断是否已指定驳回目标任务
        boolean hasTarget = false;
        List<SequenceFlow> outgoingFlows = currFlow.getOutgoingFlows();
        loop1:
        for (SequenceFlow outgoingFlow : outgoingFlows) {
            if ("${flag==2}".equals(StringUtils.trimAll(outgoingFlow.getConditionExpression()))) {
                hasTarget = true;
                break;
            } else {
                FlowNode targetFlowElement = (FlowNode) outgoingFlow.getTargetFlowElement();
                if (targetFlowElement.isExclusive()) {
                    List<SequenceFlow> subOutgoingFlows = targetFlowElement.getOutgoingFlows();
                    loop2:
                    for (SequenceFlow subOutgoingFlow : subOutgoingFlows) {
                        if ("${flag==2}".equals(StringUtils.trimAll(subOutgoingFlow.getConditionExpression()))) {
                            hasTarget = true;
                            break loop1;
                        }
                    }
                }
            }
        }

        if (hasTarget) {
            taskService.complete(task.getId(), map);
            return true;
        }

        //获取目标节点
        List<HistoricActivityInstance> userTasks = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(task.getProcessInstanceId())
                .activityType("userTask")
                .finished()
                .orderByHistoricActivityInstanceEndTime()
                .desc()
                .list();

        if (StringUtils.isEmpty(userTasks)) {
            throw new CustomException("此处无法进行驳回操作");
        }

        //判断目标节点是否是下一步的节点
        if (options != null) {
            for (ApprovalOpinionDTO approvalOpinionDTO : approvalOpinionDTOs) {
                if (userTasks.get(0).getTaskId().equals(approvalOpinionDTO.getTaskId())) {
                    if (DictEnum.APPLY_APPROVAL_OPINION_REJECT.getKey().equals(approvalOpinionDTO.getFlag())) {
                        throw new CustomException("此处无法进行驳回操作");
                    }
                }
            }
        }

        String activityId = userTasks.get(0).getActivityId();
        FlowNode targetFlow = (FlowNode) bpmnModel.getFlowElement(activityId);

        //如果不是同一个流程(子流程)不能驳回
        if (!(currFlow.getParentContainer().equals(targetFlow.getParentContainer()))) {
            throw new CustomException("此处无法进行驳回操作");
        }

        //记录原活动方向
        List<SequenceFlow> oriSequenceFlows = Lists.newArrayList();
        oriSequenceFlows.addAll(currFlow.getOutgoingFlows());

        //清理活动方向
        currFlow.getOutgoingFlows().clear();

        //建立新的方向
        List<SequenceFlow> newSequenceFlows = Lists.newArrayList();
        SequenceFlow newSequenceFlow = new SequenceFlow();
        String uuid = UUID.randomUUID().toString().replace("-", "");
        newSequenceFlow.setId(uuid);
        newSequenceFlow.setSourceFlowElement(currFlow);
        newSequenceFlow.setTargetFlowElement(targetFlow);
        newSequenceFlows.add(newSequenceFlow);

        currFlow.setOutgoingFlows(newSequenceFlows);
        taskService.complete(task.getId(), map);

        historyService.deleteHistoricTaskInstance(applyOpinionDTO.getTaskId());

        //恢复原方向
        currFlow.setOutgoingFlows(oriSequenceFlows);
        return true;
    }

    /**
     * 驳回到指定节点
     *
     * @param approvalOpinionVO
     * @param task
     * @param map
     * @return
     */
    @Override
    public boolean runNodes(ApprovalOpinionVO approvalOpinionVO, Task task, Map<String, Object> map) {
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        String myTaskId = null;
        if (user.getId().equals(task.getAssignee())) {
            myTaskId = task.getId();
        }
        if (null == myTaskId) {
            throw new CustomException("当前用户无法驳回");
        }
        //获取当前节点
        String currActivityId = task.getTaskDefinitionKey();
        String processDefinitionId = task.getProcessDefinitionId();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        FlowNode currFlow = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currActivityId);

        if (null == currFlow) {
            List<SubProcess> subProcessList = bpmnModel.getMainProcess().findFlowElementsOfType(SubProcess.class, true);
            for (SubProcess subProcess : subProcessList) {
                FlowElement flowElement = subProcess.getFlowElement(currActivityId);
                if (flowElement != null) {
                    currFlow = (FlowNode) flowElement;
                    break;
                }
            }
        }

        FlowNode targetFlow = (FlowNode) bpmnModel.getFlowElement(approvalOpinionVO.getRunNodeId());

        //如果不是同一个流程(子流程)不能驳回
        if (!(currFlow.getParentContainer().equals(targetFlow.getParentContainer()))) {
            throw new CustomException("此处无法进行驳回操作");
        }

        //记录原活动方向
        List<SequenceFlow> oriSequenceFlows = Lists.newArrayList();
        oriSequenceFlows.addAll(currFlow.getOutgoingFlows());

        //清理活动方向
        currFlow.getOutgoingFlows().clear();

        //建立新的方向
        List<SequenceFlow> newSequenceFlows = Lists.newArrayList();
        SequenceFlow newSequenceFlow = new SequenceFlow();
        String uuid = UUID.randomUUID().toString().replace("-", "");
        newSequenceFlow.setId(uuid);
        newSequenceFlow.setSourceFlowElement(currFlow);
        newSequenceFlow.setTargetFlowElement(targetFlow);
        newSequenceFlows.add(newSequenceFlow);
        currFlow.setOutgoingFlows(newSequenceFlows);

        //审批意见叠加
        Map<String, Object> variables = task.getProcessVariables();
        //拒绝,通过,驳回
        List<ApprovalOpinionDTO> approvalOpinionDTOs = new ArrayList<>();
        Object options = variables.get(Constant.ACT_APPLY_OPINION_LIST);
        if (null != options) {
            approvalOpinionDTOs = JSONObject.parseArray(options.toString(), ApprovalOpinionDTO.class);
        }
        ApprovalOpinionDTO applyOpinionDTO = new ApprovalOpinionDTO();
        //VO转为dto
        BeanUtils.copyProperties(approvalOpinionVO, applyOpinionDTO);
        applyOpinionDTO.setFlagStr(applyOpinionDTO.getTaskNodeName() + "撤回到" + targetFlow.getName());
        approvalOpinionDTOs.add(applyOpinionDTO);
        map.put(Constant.ACT_APPLY_OPINION_LIST, JSONObject.toJSONString(approvalOpinionDTOs));

        //判断是否已指定驳回目标任务
        if (StringUtils.isEmpty(approvalOpinionVO.getRunNodeId())) {
            boolean hasTarget = false;
            List<SequenceFlow> outgoingFlows = currFlow.getOutgoingFlows();
            loop1:
            for (SequenceFlow outgoingFlow : outgoingFlows) {
                if ("${flag==2}".equals(StringUtils.trimAll(outgoingFlow.getConditionExpression()))) {
                    hasTarget = true;
                    break;
                } else {
                    FlowNode targetFlowElement = (FlowNode) outgoingFlow.getTargetFlowElement();
                    if (targetFlowElement.isExclusive()) {
                        List<SequenceFlow> subOutgoingFlows = targetFlowElement.getOutgoingFlows();
                        loop2:
                        for (SequenceFlow subOutgoingFlow : subOutgoingFlows) {
                            if ("${flag==2}".equals(StringUtils.trimAll(subOutgoingFlow.getConditionExpression()))) {
                                hasTarget = true;
                                break loop1;
                            }
                        }
                    }
                }
            }
            if (hasTarget) {
                taskService.complete(task.getId(), map);
                return true;
            }
        }

        taskService.complete(task.getId(), map);

        //恢复原方向
        currFlow.setOutgoingFlows(oriSequenceFlows);
        return true;
    }

    /**
     * 取消申请
     *
     * @param processInstanceId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean withdrawProcess(String processInstanceId) {
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .startedBy(user.getId())
                .singleResult();

        if (processInstance != null) {

            Execution execution = runtimeService.createExecutionQuery()
                    .processInstanceId(processInstanceId)
                    .startedBy(user.getId())
                    .singleResult();

            String businessKey = processInstance.getBusinessKey();
            String[] split = businessKey.split("/");
            String module = split[0];
            String taskId = split[1];

            Map<String, Object> variables = processInstance.getProcessVariables();
            runtimeService.setVariable(execution.getId(), Constant.ACT_TASK_FLAG, DictEnum.APPLY_APPROVAL_OPINION_ABANDON.getKey());
            runtimeService.deleteProcessInstance(processInstanceId, "取消申请");

            //领用模块

            //采购模块

            return true;
        }
            return false;
    }


    /**
     * 获取流程状态 是否可撤销,可修改,可重新提交
     *
     * @param processInstanceId
     * @return
     */
    @Override
    public Map getProcessStatus(String processInstanceId) {
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        Map map = Maps.newHashMap();
        map.put(Constant.APPROVAL_HANDLE_WITHDRAW, Constant.NO);
        map.put(Constant.APPROVAL_HANDLE_MODIFY, Constant.NO);
        map.put(Constant.APPROVAL_HANDLE_REAPPLY, Constant.NO);
        //存放最终审批结果
        map.put(Constant.APPROVAL_RESULT_STATUS, "");

        ProcessInstance runtimeProcessInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .includeProcessVariables()
                .singleResult();
        if (runtimeProcessInstance != null) {
            map.put(Constant.APPROVAL_HANDLE_WITHDRAW, Constant.YES);

            List<Task> list = taskService.createTaskQuery()
                    .processInstanceId(processInstanceId)
                    .list();

            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                    .startedBy(user.getId())
                    .processInstanceId(processInstanceId)
                    .finished()
                    .includeProcessVariables()
                    .singleResult();

            if (historicProcessInstance != null) {

                String deleteReason = historicProcessInstance.getDeleteReason();
                //申请人取消或是被拒绝的,可以编辑后再次申请
                if (StringUtils.isNotEmpty(deleteReason)) {
                    map.put(Constant.APPROVAL_HANDLE_REAPPLY, Constant.YES);
                }
                //获取结束的审批流程最后一个节点的审批结果
                Map<String, Object> processVariables = historicProcessInstance.getProcessVariables();
                Object object = processVariables.get(Constant.ACT_TASK_FLAG);
                if (object != null && object != "") {
                    //根据审批结果进行显示
                    //未通过
                    if (DictEnum.Apply_APPROVAL_OPINION_REFUSE.getKey().equals(object.toString())) {
                        map.put(Constant.APPROVAL_RESULT_STATUS, DictEnum.APPLY_RESULT_REFUSE.getValue());
                        //判断是否可重新提交申请
                        map.put(Constant.APPROVAL_HANDLE_REAPPLY, Constant.YES);
                    }

                    //通过
                    if (DictEnum.Apply_APPROVAL_OPINION_AGREE.getKey().equals(object.toString()) || DictEnum.APPLY_APPROVAL_OPINION_CONFIRM.getKey().equals(object.toString())) {
                        map.put(Constant.APPROVAL_RESULT_STATUS, DictEnum.APPLY_RESULT_AGREE.getValue());
                    }

                    //取消申请
                    if (DictEnum.APPLY_APPROVAL_OPINION_ABANDON.getKey().equals(object.toString())) {
                        map.put(Constant.APPROVAL_RESULT_STATUS, DictEnum.APPLY_RESULT_CANCEL.getValue());
                    }
                }
            }
        }
        return map;
    }

    @Override
    public DynamicFormConf taskDynamicParams(String taskId) {
        DynamicFormConf dynamicFormConf = new DynamicFormConf();
        Map<String, String> map = Maps.newHashMap();
        List<DictEnum> enumList = DictEnum.getEnumList(DictModelConstant.MODEL_APPLY, DictModelConstant.MODEL_APPLY_APPROVAL_OPINION_FLAG);
        TaskFormData taskFormData = formService.getTaskFormData(taskId);
        if (null != taskFormData && StringUtils.isNotEmpty(taskFormData.getFormProperties())) {
            Task task = taskService.createTaskQuery()
                    .taskId(taskId)
                    .singleResult();
            //.taskTenantId(UserUtils.getTenantId())

            List<FormProperty> formProperties = taskFormData.getFormProperties();
            for (FormProperty formProperty : formProperties) {
                //有自定义的操作选项
                if (formProperty.getId().equals(DictModelConstant.MODEL_APPLY_APPROVAL_OPINION_FLAG)) {
                    String name = formProperty.getName();
                    if (StringUtils.isNotEmpty(name)) {
                        String[] split = name.split(",");
                        for (String s : split) {
                            for (DictEnum dictEnum : enumList) {
                                if (s.equals(dictEnum.getKey())) {
                                    map.put(dictEnum.getKey(), dictEnum.getValue());
                                    break;
                                }
                            }
                        }
                    }
                }
                //修改表单
                if (formProperty.getId().equals(DictModelConstant.MODEL_APPLY_TASK_FORM_WRITABLE)) {
                        dynamicFormConf.setWritable(true);
                }
                //批量控制字段是否可编辑
                if (formProperty.getId().equals(DictModelConstant.MODEL_APPLY_TASK_FORM_FIELD_WRITABLE)) {
                        dynamicFormConf.setFieldWritable(true);
                }

                //是否可以指定下一步办理人
                if (formProperty.getId().equals(DictModelConstant.MODEL_APPLY_NEXT_ASSIGN)) {
                    //if (isAssigneeOrCandiate(task, UserUtils.getUserId())) {
                        dynamicFormConf.setNextAssign(true);
                    //}
                }
                //判断当前节点
                if (formProperty.getId().equals(DictModelConstant.MODEL_APPLY_NEXT_ISNODES)) {
                    //if (isAssigneeOrCandiate(task, UserUtils.getUserId())) {
                    dynamicFormConf.setIsNodes(formProperty.getName());
                    //}
                }
//                Map<String, Object> params = new HashMap<>();
//                params.put(formProperty.getId(), formProperty.getName());
//                dynamicFormConf.setParams(params);
            }
        }

        //使用默认的操作选项
        if (map.isEmpty()) {
            map.put(DictEnum.Apply_APPROVAL_OPINION_REFUSE.getKey(), DictEnum.Apply_APPROVAL_OPINION_REFUSE.getValue());
            map.put(DictEnum.Apply_APPROVAL_OPINION_AGREE.getKey(), DictEnum.Apply_APPROVAL_OPINION_AGREE.getValue());
            map.put(DictEnum.APPLY_APPROVAL_OPINION_REJECT.getKey(), DictEnum.APPLY_APPROVAL_OPINION_REJECT.getValue());
        }
        //判断是否有撤回到指定节点
        if(StringUtils.isNotEmpty(map.get(DictEnum.APPLY_APPROVAL_OPINION_ASSIGN.getKey()))){
            String processInstanceId = taskFormData.getTask().getProcessInstanceId();
            Map<String, String> runNodes = getRunNodes(processInstanceId);
            if(StringUtils.isNotEmpty(runNodes)){
                dynamicFormConf.setRunNodes(runNodes);
            }
        }

        dynamicFormConf.setApprovalTypeFlag(map);
        return dynamicFormConf;
    }

    /**
     * 判断用户是否为任务的办理人或候选人
     *
     * @param task
     * @return
     */
    private boolean isAssigneeOrCandiate(Task task, String userId) {
        if (StringUtils.isNull(task)) {
            return false;
        }
        String assignee = task.getAssignee();
        if (StringUtils.isNotEmpty(assignee)) {
            return assignee.equals(userId);
        } else {
            Set<String> candiates = getCandiates(task.getId());
            return candiates.contains(userId);
        }
    }
}
