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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.engine.*;
import org.activiti.engine.history.*;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskInfo;
import org.activiti.engine.task.TaskQuery;
import org.activiti.image.ProcessDiagramGenerator;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.Constant;
import org.jeecg.common.base.entity.BaseTaskEntity;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.utils.DictEnum;
import org.jeecg.common.utils.DictModelConstant;
import org.jeecg.common.utils.StringUtils;
import org.jeecg.common.config.CustomProcessDiagramGenerator;
import org.jeecg.modules.approval.model.dto.ApprovalOpinionDTO;
import org.jeecg.modules.approval.model.vo.*;
import org.jeecg.modules.approval.service.ApprovalService;
import org.jeecg.modules.approval.service.ApprovalTaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.yaml.snakeyaml.Yaml;

import javax.servlet.http.HttpServletRequest;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 任务处理实现
 *
 * @author yao
 */
@Service("actTaskService")
@Slf4j
public class ApprovalTaskServiceImpl implements ApprovalTaskService {

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private ProcessEngine processEngine;

    @Autowired
    private ApprovalService approvalService;




    /**
     * 待处理任务
     *
     * @return
     * @param
     */
    @Override
    public IPage listMyTask(Integer pageNo, Integer pageSize,HttpServletRequest req) {
        Map<String, String[]> parms = req.getParameterMap();
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        String tenantId = req.getHeader("tenant-id");
        TaskQuery taskQuery = taskService.createTaskQuery()
                .taskCandidateOrAssigned(sysUser.getId())
                .includeProcessVariables()
                .orderByTaskCreateTime()
                .taskTenantId(tenantId)
                .desc();
        if(parms !=null){
            String[] keys = parms.get("approveName");
            if (!"".equals(keys) && keys != null) {
                String key = keys[0];
                //taskQuery.taskName(key);
                taskQuery.processDefinitionName(key);
            }
        }

        List<Task> taskList = taskQuery.listPage((pageNo - 1) * pageSize, pageSize);

        List<TaskVO> tasks = new ArrayList<>();
        for (Task task : taskList) {

            Map<String, Object> map = task.getProcessVariables();
            BaseTaskEntity baseTaskEntity =
                    JSON.parseObject(map.get(Constant.ACT_BASE_TASK).toString(), BaseTaskEntity.class);
            TaskVO taskVO = new TaskVO(task);
            taskVO.setUserName(baseTaskEntity.getUserName());
            taskVO.setRemarks(baseTaskEntity.getRemarks());
            taskVO.setTaskUrl(String.format("%s/%s", baseTaskEntity.getFormKey(), baseTaskEntity.getId()));
            taskVO.setProcessDefinitionKey(baseTaskEntity.getProcessKey());
            taskVO.setProcessDefinitionName(baseTaskEntity.getProcessInstanceName());
            taskVO.setApproveName(DictEnum.getValue(DictModelConstant.MODEL_APPLY_CONFIG,
                    DictModelConstant.MODEL_APPLY_CONFIG_FORMKEY, baseTaskEntity.getFormKey()));
            taskVO.setCreateTime(task.getCreateTime());
            Map<String, Object> param = baseTaskEntity.getParam();

            if (StringUtils.isNotEmpty(param)) {
                taskVO.setParam(param);
            }
            tasks.add(taskVO);
        }

        IPage<TaskVO> page = new Page<>(pageNo, pageSize);
        page.setTotal((int) taskQuery.count());
        return page.setRecords(tasks);
    }

    /**
     * 已处理任务列表
     *
     * @param
     * @return
     */
    @Override
    public IPage listMyProcessedTask(Integer pageNo,Integer pageSize,HttpServletRequest req) {
        String tenantId = req.getHeader("tenant-id");
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        String userId = sysUser.getId();
        HistoricTaskInstanceQuery historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery()
                .taskAssignee(userId)
                .finished()
                .taskTenantId(tenantId)
                .includeProcessVariables()
                .orderByTaskCreateTime()
                .desc();
        String[] keys = req.getParameterMap().get("approveName");
        if (!"".equals(keys) && keys != null) {
            String key = keys[0];
            historicTaskInstanceQuery.processDefinitionName(key);
        }
        List<HistoricTaskInstance> taskList = historicTaskInstanceQuery.listPage((pageNo - 1) * pageSize, pageSize);

        List<HistoryTaskVO> tasks = new ArrayList<>();
        for (HistoricTaskInstance task : taskList) {
            Map<String, Object> variables = task.getProcessVariables();
            BaseTaskEntity baseTaskEntity = JSONObject
                    .parseObject(variables.get(Constant.ACT_BASE_TASK).toString(), BaseTaskEntity.class);
            HistoryTaskVO taskVO = new HistoryTaskVO(task);
            taskVO.setUserName(baseTaskEntity.getUserName());
            taskVO.setRemarks(baseTaskEntity.getRemarks());
            taskVO.setTaskUrl(String.format("%s/%s", baseTaskEntity.getFormKey(), baseTaskEntity.getId()));
            taskVO.setProcessDefinitionKey(baseTaskEntity.getProcessKey());
            taskVO.setProcessDefinitionName(baseTaskEntity.getProcessInstanceName());
            taskVO.setApproveName(DictEnum.getValue(DictModelConstant.MODEL_APPLY_CONFIG,
                    DictModelConstant.MODEL_APPLY_CONFIG_FORMKEY, baseTaskEntity.getFormKey()));
            if (StringUtils.isNotEmpty(baseTaskEntity.getResult())) {
                taskVO.setResultStr(DictEnum.getValue(DictModelConstant.MODEL_APPLY, DictModelConstant.MODEL_APPLY_RESULT, baseTaskEntity.getResult()));
            }
            Map<String, Object> param = baseTaskEntity.getParam();
            if (StringUtils.isNotEmpty(param)) {
                taskVO.setParam(param);
            }
            //我审批的结果
            Object opinionStr = variables.get(Constant.ACT_APPLY_OPINION_LIST);
            if (null != opinionStr) {
                List<ApprovalOpinionVO> approvalOpinionVOS = JSONArray
                        .parseArray(opinionStr.toString(), ApprovalOpinionVO.class);
                for (ApprovalOpinionVO approvalOpinionVO : approvalOpinionVOS) {
                    if (task.getId().equals(approvalOpinionVO.getTaskId()) && approvalOpinionVO.getOpId().equals(userId)) {
                        taskVO.setResult(approvalOpinionVO.getFlag());
                    }
                }
            }
            tasks.add(taskVO);
        }

        IPage<HistoryTaskVO> page = new Page<>(pageNo,pageSize);
        page.setTotal((int) historicTaskInstanceQuery.count());

        return page.setRecords(tasks);
    }

    /**
     * 我发起的流程
     *
     * @return
     * processInstanceTenantId(UserUtils.getTenantId())
     */

    @Override
    public IPage listApprovalMyStarted(Integer pageNo, Integer pageSize, HttpServletRequest req) {

        //获取当前登录人
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        String tenantId = req.getHeader("tenant-id");
        HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery()
                .startedBy(sysUser.getId())
                .orderByProcessInstanceStartTime()
                .processInstanceTenantId(tenantId)
                .desc()
                .includeProcessVariables();
        List<HistoricProcessInstance> processInstances = historicProcessInstanceQuery.listPage((pageNo - 1) * pageSize, pageSize);

        List<HistoryTaskVO> tasks = Lists.newArrayList();
        for (HistoricProcessInstance processInstance : processInstances) {

            BaseTaskEntity baseTaskEntity = JSONObject
                    .parseObject(processInstance.getProcessVariables().get(Constant.ACT_BASE_TASK).toString(), BaseTaskEntity.class);

            HistoryTaskVO taskVO = new HistoryTaskVO();
            taskVO.setId(processInstance.getId());
            taskVO.setProcessInstanceId(processInstance.getId());
            taskVO.setTaskNodeName("");
            taskVO.setCreateTime(processInstance.getStartTime());
            taskVO.setProcessDefinitionId(processInstance.getProcessDefinitionId());
            taskVO.setProcessDefinitionKey(baseTaskEntity.getProcessKey());
            taskVO.setProcessDefinitionName(baseTaskEntity.getProcessInstanceName());
            taskVO.setUserName(baseTaskEntity.getUserName());
            taskVO.setRemarks(baseTaskEntity.getRemarks());
            taskVO.setTaskUrl(String.format("%s/%s", baseTaskEntity.getFormKey(), baseTaskEntity.getId()));
            taskVO.setApproveName(DictEnum.getValue(DictModelConstant.MODEL_APPLY_CONFIG,
                    DictModelConstant.MODEL_APPLY_CONFIG_FORMKEY, baseTaskEntity.getFormKey()));
            Map<String, Object> param = baseTaskEntity.getParam();
            if (StringUtils.isNotEmpty(param)) {
                taskVO.setParam(param);
            }
            //判断流程是否结束
            wrapperInfoByProcessStatus(processInstance, taskVO);
            tasks.add(taskVO);
        }
        IPage<HistoryTaskVO> page = new Page<>(pageNo,pageSize);
        page.setTotal(historicProcessInstanceQuery.count());
        page.setRecords(tasks);
        return page;
    }

    private void wrapperInfoByProcessStatus(HistoricProcessInstance processInstance, HistoryTaskVO taskVO) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        ProcessInstance pi = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstance.getId())
                .processInstanceTenantId(processInstance.getTenantId())
                .singleResult();
        if (null == pi) {
            Object flagObj = processInstance.getProcessVariables().get(Constant.ACT_TASK_FLAG);
            String flag = "";
            String result = DictEnum.APPLY_RESULT_PROCESSING.getKey();
            if (null == flagObj) {
                result = DictEnum.APPLY_RESULT_CANCEL.getKey();
            } else {
                flag = flagObj.toString();
            }
            if (DictEnum.Apply_APPROVAL_OPINION_REFUSE.getKey().equals(flag)) {
                result = DictEnum.APPLY_RESULT_REFUSE.getKey();
            } else if (DictEnum.Apply_APPROVAL_OPINION_AGREE.getKey().equals(flag)) {
                result = DictEnum.APPLY_RESULT_AGREE.getKey();
            } else if (DictEnum.APPLY_APPROVAL_OPINION_ABANDON.getKey().equals(flag)) {
                result = DictEnum.APPLY_RESULT_CANCEL.getKey();
            } else if (DictEnum.APPLY_APPROVAL_OPINION_CONFIRM.getKey().equals(flag)) {
                result = DictEnum.APPLY_RESULT_AGREE.getKey();
            }
            taskVO.setResult(result);
            if (StringUtils.isNotEmpty(result)) {
                taskVO.setResultStr(DictEnum.getValue(DictModelConstant.MODEL_APPLY, DictModelConstant.MODEL_APPLY_RESULT, result));
            }
            taskVO.setId("");
            taskVO.setFinished(true);
        } else {
            taskVO.setFinished(false);
            TaskQuery taskQuery = taskService.createTaskQuery()
                    .processInstanceId(processInstance.getId());
            List<Task> list = taskQuery.list();

            for (Task task : list) {
                if (null != task) {
                    taskVO.setId(task.getId());
                    taskVO.setTaskNodeName(task.getName());
                    taskVO.setAssignee(task.getAssignee());
                }
            }
        }
    }

    /**
     * 任务明细
     *
     * @param taskId
     * @return
     */
    @Override
    public Object getTask(String taskId) {
        Map<String, Object> variables = taskService.getVariables(taskId);
        BaseTaskEntity baseTask = (BaseTaskEntity) variables.get(Constant.ACT_BASE_TASK);
        return baseTask;
    }

    /**
     * 追踪流程图片
     *
     * @param processInstanceId
     * @return
     * @throws Exception
     */
    @Override
    public byte[] getProcessImage(String processInstanceId) throws Exception {
        // 获取历史流程实例
        HistoricProcessInstance historicProcessInstance =
                historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (historicProcessInstance == null) {
            throw new Exception();
        } else {
            // 获取流程定义
            ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) repositoryService
                    .getProcessDefinition(historicProcessInstance.getProcessDefinitionId());

            // 获取流程历史中已执行节点，并按照节点在流程中执行先后顺序排序
            List<HistoricActivityInstance> historicActivityInstanceList =
                    historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId)
                            .orderByHistoricActivityInstanceId().desc().list();
            // 已执行的节点ID集合
            List<String> executedActivityIdList = new ArrayList<>();
            for (HistoricActivityInstance activityInstance : historicActivityInstanceList) {
                if ("userTask".equals(activityInstance.getActivityType()) && StringUtils.isNull(activityInstance.getEndTime())) {
                    executedActivityIdList.add(activityInstance.getActivityId() + "#");
                } else {
                    executedActivityIdList.add(activityInstance.getActivityId());
                }
            }
            // 获取流程图图像字符流
            BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());

            // 通过流程实例ID获取流程中 正在执行的节点
            List<String> runningActivitiIdList = new ArrayList<String>();
            List<Execution> runningActivityInstanceList = getRunningActivityInst(processInstanceId);
            for (Execution execution : runningActivityInstanceList) {
                if (StringUtils.isNotEmpty(execution.getActivityId())) {
                    runningActivitiIdList.add(execution.getActivityId());
                }
            }

            // 已执行flow的集和
            List<String> executedFlowIdList = getHighLightedFlows(bpmnModel, historicActivityInstanceList);

            // 定义流程画布生成器
            // 如果完成，流程图高亮颜色为绿色，如果没有已经完成为红色
            ProcessDiagramGenerator processDiagramGenerator = new CustomProcessDiagramGenerator();

            // 使用默认配置获得流程图表生成器，并生成追踪图片字符流
            InputStream imageStream = ((CustomProcessDiagramGenerator) processDiagramGenerator)
               .generateDiagramCustom(bpmnModel, "png",
                  executedActivityIdList, runningActivitiIdList, executedFlowIdList,
                  "宋体", "微软雅黑", "黑体",
                  null, 2.0);
            // 将InputStream数据流转换为byte[]
            byte[] buffer = new byte[imageStream.available()];
            imageStream.read(buffer);
            imageStream.close();
            return buffer;
        }
    }

    /**
     * Desc: 通过流程实例ID获取流程中正在执行的节点
     *
     * @param procInstId
     * @return
     * @author liuxz
     */
    public List<Execution> getRunningActivityInst(String procInstId) {
        return runtimeService.createExecutionQuery().processInstanceId(procInstId).list();
    }

    /**
     * 获取已经流转的线
     *
     * @param bpmnModel
     * @param historicActivityInstances
     * @return
     */
    private static List<String> getHighLightedFlows(BpmnModel bpmnModel,
                                                    List<HistoricActivityInstance> historicActivityInstances) {
        // 高亮流程已发生流转的线id集合
        List<String> highLightedFlowIds = new ArrayList<>();
        // 全部活动节点
        List<FlowNode> historicActivityNodes = new ArrayList<>();
        // 已完成的历史活动节点
        List<HistoricActivityInstance> finishedActivityInstances = new ArrayList<>();

        for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
            FlowNode flowNode =
               (FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstance.getActivityId(), true);
            historicActivityNodes.add(flowNode);
            if (historicActivityInstance.getEndTime() != null) {
                finishedActivityInstances.add(historicActivityInstance);
            }
        }

        FlowNode currentFlowNode = null;
        FlowNode targetFlowNode = null;
        // 遍历已完成的活动实例，从每个实例的outgoingFlows中找到已执行的
        for (HistoricActivityInstance currentActivityInstance : finishedActivityInstances) {
            // 获得当前活动对应的节点信息及outgoingFlows信息
            currentFlowNode =
               (FlowNode) bpmnModel.getMainProcess().getFlowElement(currentActivityInstance.getActivityId(), true);
            List<SequenceFlow> sequenceFlows = currentFlowNode.getOutgoingFlows();

            /**
             * 遍历outgoingFlows并找到已已流转的 满足如下条件认为已已流转： 1.当前节点是并行网关或兼容网关，则通过outgoingFlows能够在历史活动中找到的全部节点均为已流转
             * 2.当前节点是以上两种类型之外的，通过outgoingFlows查找到的时间最早的流转节点视为有效流转
             */
            if ("parallelGateway".equals(currentActivityInstance.getActivityType())
               || "inclusiveGateway".equals(currentActivityInstance.getActivityType())) {
                // 遍历历史活动节点，找到匹配流程目标节点的
                for (SequenceFlow sequenceFlow : sequenceFlows) {
                    targetFlowNode =
                       (FlowNode) bpmnModel.getMainProcess().getFlowElement(sequenceFlow.getTargetRef(), true);
                    if (historicActivityNodes.contains(targetFlowNode)) {
                        highLightedFlowIds.add(targetFlowNode.getId());
                    }
                }
            } else {
                List<Map<String, Object>> tempMapList = new ArrayList<>();
                for (SequenceFlow sequenceFlow : sequenceFlows) {
                    for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
                        if (historicActivityInstance.getActivityId().equals(sequenceFlow.getTargetRef())) {
                            Map<String, Object> map = new HashMap<>();
                            map.put("highLightedFlowId", sequenceFlow.getId());
                            map.put("highLightedFlowStartTime", historicActivityInstance.getStartTime().getTime());
                            tempMapList.add(map);
                        }
                    }
                }

                if (!CollectionUtils.isEmpty(tempMapList)) {
                    // 遍历匹配的集合，取得开始时间最早的一个
                    long earliestStamp = 0L;
                    String highLightedFlowId = null;
                    for (Map<String, Object> map : tempMapList) {
                        long highLightedFlowStartTime = Long.valueOf(map.get("highLightedFlowStartTime").toString());
                        if (earliestStamp == 0 || earliestStamp >= highLightedFlowStartTime) {
                            highLightedFlowId = map.get("highLightedFlowId").toString();
                            earliestStamp = highLightedFlowStartTime;
                        }
                    }

                    highLightedFlowIds.add(highLightedFlowId);
                }

            }

        }
        return highLightedFlowIds;
    }


    @Override
    public long countUnprocessed() {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        return taskService.createTaskQuery().
                taskCandidateOrAssigned(sysUser.getId())
                .count();
    }

    @Override
    public long countMyStarted() {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        return historyService.createHistoricProcessInstanceQuery()
                .startedBy(sysUser.getId())
                .count();
    }

    /**
     * 我审批的
     *
     * @param
     * @param param
     * @return
     */
    @Override
    public IPage listApiMyApproval(Map<String, String> params, ApprovalTaskQueryVo param) {

        int pageNo = Integer.parseInt( params.get("pageNo"));
        int pageSize = Integer.parseInt( params.get("pageSize"));

        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        String formType = param.getFormType();
        String status = param.getStatus();
        boolean processed = param.isProcessed();

        HistoricTaskInstanceQuery historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery();
        historicTaskInstanceQuery
                .includeProcessVariables()
                .taskAssignee(sysUser.getId())
                .orderByTaskCreateTime()
                .desc();

        if (StringUtils.isNotEmpty(formType)) {
            historicTaskInstanceQuery.processInstanceBusinessKeyLikeIgnoreCase(formType + "/%");
        }

        if (processed) {
            historicTaskInstanceQuery.finished();
            //流程状态
            if (StringUtils.isNotEmpty(status)) {
                if (Constant.ACT_TASK_QUERY_STATUS_RUN.equals(status)) {
                    historicTaskInstanceQuery.processUnfinished();
                } else if (Constant.ACT_TASK_STATUS_END.equals(status)) {
                    historicTaskInstanceQuery.processFinished();
                }
            }
        } else {
            historicTaskInstanceQuery.unfinished();
        }

        List<HistoricTaskInstance> taskList = historicTaskInstanceQuery
                .listPage( (pageNo - 1) * pageSize, pageSize);

        List<HistoryTaskVO> tasks = new ArrayList<>();
        HistoryTaskVO taskVO = null;
        for (HistoricTaskInstance task : taskList) {
            BaseTaskEntity baseTaskEntity = JSONObject
                    .parseObject(task.getProcessVariables().get(Constant.ACT_BASE_TASK).toString(), BaseTaskEntity.class);
            taskVO = new HistoryTaskVO(task);
            taskVO.setUserName(baseTaskEntity.getUserName());
            taskVO.setRemarks(baseTaskEntity.getRemarks());
            taskVO.setTaskUrl(String.format("%s/%s", baseTaskEntity.getFormKey(), baseTaskEntity.getId()));
            taskVO.setProcessDefinitionKey(baseTaskEntity.getProcessKey());
            taskVO.setProcessDefinitionName(baseTaskEntity.getProcessInstanceName());
            taskVO.setApproveName(DictEnum.getValue(DictModelConstant.MODEL_APPLY_CONFIG,
                    DictModelConstant.MODEL_APPLY_CONFIG_FORMKEY, baseTaskEntity.getFormKey()));

            //我审批的结果
            Object o = task.getProcessVariables().get(Constant.ACT_APPLY_OPINION_LIST);
            if (null != o) {
                List<ApprovalOpinionVO> approvalOpinionVOS = JSONArray
                        .parseArray(o.toString(), ApprovalOpinionVO.class);
                for (ApprovalOpinionVO approvalOpinionVO : approvalOpinionVOS) {
                    if (task.getId().equals(approvalOpinionVO.getTaskId()) && approvalOpinionVO.getOpId().equals(sysUser.getId())) {
                        taskVO.setResult(approvalOpinionVO.getFlag());
                        taskVO.setResultStr(DictEnum.getValue(DictModelConstant.MODEL_APPLY,DictModelConstant.MODEL_APPLY_APPROVAL_OPINION_FLAG,approvalOpinionVO.getFlag()));
                    }
                }
            }
            //流程是否结束标识
            taskVO.setFinished(!approvalService.getApprovalStatus(task.getProcessInstanceId()));
            tasks.add(taskVO);
        }

        IPage<HistoryTaskVO> page = new Page(pageNo, pageSize);
        page.setTotal(historicTaskInstanceQuery.count());
        return page.setRecords(tasks);
    }

    /**
     * 我发起的
     *
     * @param
     * @param param
     * @return
     */
    @Override
    public IPage listApiMyStarted(Map<String, String> params, ApprovalTaskQueryVo param) {

        int pageNo = Integer.parseInt( params.get("pageNo"));
        int pageSize = Integer.parseInt( params.get("pageSize"));

        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        String status = param.getStatus();
        String formType = param.getFormType();

        //我发起的
        HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery();
        historicProcessInstanceQuery
                .includeProcessVariables()
                .startedBy(sysUser.getId())
                .orderByProcessInstanceStartTime()
                .desc();

        List<HistoryTaskVO> tasks = new ArrayList<>();
        if (StringUtils.isNotEmpty(formType)) {
            List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery()
                    .processInstanceBusinessKeyLike(formType + "/%")
                    .list();
            Set<String> collect = list.stream().map(TaskInfo::getProcessInstanceId).collect(Collectors.toSet());
            if (StringUtils.isNotEmpty(collect)) {
                historicProcessInstanceQuery.processInstanceIds(collect);
            } else {
                IPage<HistoryTaskVO> page = new Page(pageNo, pageSize);
                page.setTotal(0);
            }
        }

        if (StringUtils.isNotEmpty(status)) {
            if (status.equals(Constant.ACT_TASK_STATUS_END)) {
                historicProcessInstanceQuery.finished();
            } else if (status.equals(Constant.ACT_TASK_QUERY_STATUS_RUN)) {
                historicProcessInstanceQuery.unfinished();
            }
        }

        List<HistoricProcessInstance> processInstances = historicProcessInstanceQuery
                .listPage((pageNo - 1) * pageSize, pageSize);

        for (HistoricProcessInstance processInstance : processInstances) {
            BaseTaskEntity baseTaskEntity = JSONObject
                    .parseObject(processInstance.getProcessVariables().get(Constant.ACT_BASE_TASK).toString(), BaseTaskEntity.class);

            HistoryTaskVO taskVO = new HistoryTaskVO();
            taskVO.setId(processInstance.getId());
            taskVO.setProcessInstanceId(processInstance.getId());

            taskVO.setTaskNodeName("");
            taskVO.setCreateTime(processInstance.getStartTime());
            taskVO.setProcessDefinitionId(processInstance.getProcessDefinitionId());
            taskVO.setProcessDefinitionKey(baseTaskEntity.getProcessKey());
            taskVO.setProcessDefinitionName(baseTaskEntity.getProcessInstanceName());
            taskVO.setUserName(baseTaskEntity.getUserName());
            taskVO.setRemarks(baseTaskEntity.getRemarks());
            taskVO.setTaskUrl(String.format("%s/%s", baseTaskEntity.getFormKey(), baseTaskEntity.getId()));
            taskVO.setApproveName(DictEnum.getValue(DictModelConstant.MODEL_APPLY_CONFIG,
                    DictModelConstant.MODEL_APPLY_CONFIG_FORMKEY, baseTaskEntity.getFormKey()));

            //我发起的流程审批结果
            if (status.equals(Constant.ACT_TASK_STATUS_END)) {
                taskVO.setResult(processInstance.getProcessVariables().get(Constant.ACT_TASK_FLAG).toString());
                taskVO.setFinished(true);
            } else {
                wrapperInfoByProcessStatus(processInstance, taskVO);
            }
            tasks.add(taskVO);
        }

        IPage<HistoryTaskVO> page = new Page(pageNo, pageSize);
        page.setTotal(historicProcessInstanceQuery.count());
        return page.setRecords(tasks);
    }


    @Override
    public TaskVO getMyApprovalTask(String processInstanceId) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        Task task = taskService.createTaskQuery()
                .processInstanceId(processInstanceId)
                .taskCandidateOrAssigned(sysUser.getId())
                .includeProcessVariables()
                .singleResult();
        if (task == null) {
            return null;
        }

        TaskVO taskVO = new TaskVO(task);
        Map<String, Object> processVariableMap = task.getProcessVariables();
        BaseTaskEntity baseTaskEntity = JSONObject.parseObject(processVariableMap.get(Constant.ACT_BASE_TASK).toString(), BaseTaskEntity.class);
        taskVO.setTaskUrl(String.format("%s/%s", baseTaskEntity.getFormKey(), baseTaskEntity.getId()));
        taskVO.setProcessDefinitionKey(baseTaskEntity.getProcessKey());
        taskVO.setProcessDefinitionName(baseTaskEntity.getProcessInstanceName());
        taskVO.setApproveName(DictEnum.getValue(DictModelConstant.MODEL_APPLY_CONFIG,
                DictModelConstant.MODEL_APPLY_CONFIG_FORMKEY, baseTaskEntity.getFormKey()));
        return taskVO;
    }

    @Override
    public List<ApprovalOpinionDTO> listOpinionsByPId(String processInstanceId) {
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .includeProcessVariables()
                .singleResult();
        if (historicProcessInstance == null) {
            return Lists.newArrayList();
        }
        Map<String, Object> processVariables = historicProcessInstance.getProcessVariables();
        Object obj = processVariables.get(Constant.ACT_APPLY_OPINION_LIST);
        if (StringUtils.isNull(obj)) {
            return Lists.newArrayList();
        }
        List<ApprovalOpinionDTO> approvalOpinionDTOS = JSONArray.parseArray(obj.toString(), ApprovalOpinionDTO.class);

        for (ApprovalOpinionDTO approvalOpinionDTO : approvalOpinionDTOS) {
            approvalOpinionDTO.setFlagStr(DictEnum.getValue(DictModelConstant.MODEL_APPLY, DictModelConstant.MODEL_APPLY_APPROVAL_OPINION_FLAG, approvalOpinionDTO.getFlag()));
        }
        //获取审批结果 并修改样式
        for (ApprovalOpinionDTO approvalOpinionDTO : approvalOpinionDTOS) {
            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());
            String style= rejectStyle.contains(approvalOpinionDTO.getFlag())?"error":"success";
            approvalOpinionDTO.setStyle(style);
        }

        return approvalOpinionDTOS;
    }
}
