package com.bbd.bpm.controller.taskOperate;

import com.bbd.bpm.dto.BtnBean;
import com.bbd.bpm.dto.PageUtil;
import com.bbd.bpm.dto.SysCode;
import com.bbd.bpm.dto.request.CompleteTaskRequest;
import com.bbd.bpm.dto.request.PendingTaskListRequest;
import com.bbd.bpm.dto.request.QueryStartedPiByUserIdRequest;
import com.bbd.bpm.dto.request.SpecialRequest;
import com.bbd.bpm.dto.response.BpmResponse;
import com.bbd.bpm.dto.response.PendingTaskListBean;
import com.bbd.bpm.dto.response.QueryPiByUserIdBean;
import com.bbd.bpm.service.ActivitiService;
import com.bbd.bpm.util.validate.ValidateUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
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.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.impl.ProcessInstanceQueryImpl;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.util.ProcessDefinitionUtil;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

/**
 * Created by houkang on 2019/2/27.
 */
@Controller
@RequestMapping("/api/bpm/task")
@Api(tags = {"任务管理"})
public class TaskOperateController {
    private static final Logger Log = LoggerFactory.getLogger(TaskOperateController.class);

    @Autowired
    private TaskService taskService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private RuntimeService runtimeService;


    @Autowired
    private ActivitiService activitiService;

    @Autowired
    private RepositoryService repositoryService;

    /**
     * taskStatus 1 已完成  2 未完成  3 全部
     */
    @ApiOperation(value = "查询我发起的流程")
    @PostMapping("/queryStartedPiByUserId")
    @ResponseBody
    public BpmResponse queryStartedPiByUserId(QueryStartedPiByUserIdRequest req,PageUtil pageUtil) {
        BpmResponse resp = new BpmResponse();
        try {
            //数据校验
            String error = ValidateUtil.check_queryStartedPiByUserId(req);
            if (error != null) {
                Log.error("查询我发起的流程，数据校验失败" + error);
                resp.setCode(SysCode.VALIDATE_ERROR);
                resp.setMessage(error);
                resp.setSuccess(false);
                return resp;
            }
            //任务办理人
            PageHelper.startPage(pageUtil.getPageNumber(), pageUtil.getPageSize());
            List<HistoricProcessInstance> listPi = historyService.createHistoricProcessInstanceQuery().involvedUser(req.getUserId()).listPage(pageUtil.getPageNumber(), pageUtil.getPageSize());
            if (listPi != null && !listPi.isEmpty()) {
                List<QueryPiByUserIdBean> datalist = new ArrayList<>();
                for (HistoricProcessInstance hpi : listPi) {

                    List<Task> taskList = taskService.createTaskQuery().processInstanceId(hpi.getId()).list();
                    QueryPiByUserIdBean bean = new QueryPiByUserIdBean();
                    //业务密钥
                    bean.setBusinessKey(hpi.getBusinessKey());
                    //流程名称
                    bean.setProcessDefinitionName(hpi.getProcessDefinitionName());
                    //流程实例id
                    bean.setProcessInstanceId(hpi.getId());
                    //开始时间
                    bean.setStartTime(hpi.getStartTime());
                    //结束时间
                    bean.setEndTime(hpi.getEndTime());
                    if (hpi.getEndTime() != null) {
                        bean.setEnded(true);
                    }
                    if ("1".equals(req.getTaskStatus())) {
                        if (bean.isEnded()) {
                            //当前操作人
                            bean.setName("已审批完成");
                            bean.setProcessNodeName("审批完成");
                            datalist.add(bean);
                        }
                    } else if ("2".equals(req.getTaskStatus())) {
                        if (!bean.isEnded()) {
                            for (Task t : taskList) {
                                //当前操作人
                                bean.setName(t.getAssignee());
                                bean.setTaskId(t.getId());
                                bean.setExecutionId(t.getExecutionId());
                                bean.setProcessNodeName(t.getName());
                            }
                            datalist.add(bean);
                        }
                    } else {
                        //当前操作人
                        bean.setName("已审批完成");
                        bean.setProcessNodeName("审批完成");
                        for (Task t : taskList) {
                            //当前操作人
                            bean.setName(t.getAssignee());
                            bean.setProcessNodeName(t.getName());
                            bean.setTaskId(t.getId());
                            bean.setExecutionId(t.getExecutionId());
                        }
                        datalist.add(bean);
                    }
                }
                PageInfo pageInfo = new PageInfo(datalist);
                resp.setData(pageInfo);
            }

            resp.setCode(SysCode.SUCCESS_CODE);
            resp.setSuccess(true);
        } catch (Exception e) {
            Log.error("查询我发起的流程失败", e);
            resp.setSuccess(false);
            resp.setCode(SysCode.SYS_ERROR);
            resp.setMessage("查询我发起的流程失败" + e.getMessage());
        }
        return resp;
    }


    @ApiOperation(value = "查询待处理任务")
    @PostMapping("/pendingTaskList")
    @ResponseBody
    public BpmResponse pendingTaskList(PendingTaskListRequest req,PageUtil pageUtil) {
        BpmResponse resp = new BpmResponse();
        try {
            //数据校验
            String error = ValidateUtil.check_pendingTaskList(req);
            if (error != null) {
                Log.error("查询待处理任务，数据校验失败" + error);
                resp.setCode(SysCode.VALIDATE_ERROR);
                resp.setMessage(error);
                resp.setSuccess(false);
                return resp;
            }
            //任务办理人
            PageHelper.startPage(pageUtil.getPageNumber(), pageUtil.getPageSize());
            List<Task> taskList = taskService.createTaskQuery().taskAssignee(req.getAssignee()).listPage(pageUtil.getPageNumber(), pageUtil.getPageSize());
            if (taskList != null && taskList.size() > 0) {
                List<PendingTaskListBean> dataList = new ArrayList<>();
                for (Task task : taskList) {
                    ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
                    PendingTaskListBean bean = new PendingTaskListBean();
                    //业务密钥
                    bean.setBusinessKey(pi.getBusinessKey());
                    //发起人
                    bean.setStartUserId(pi.getStartUserId());
                    //开始时间
                    bean.setStartTime(pi.getStartTime());
                    //executionId
                    bean.setExecutionId(task.getExecutionId());
                    //流程名称
                    bean.setName(pi.getProcessDefinitionName());
                    //任务id
                    bean.setTaskId(task.getId());
                    //流程实例id
                    bean.setProcessInstanceId(task.getProcessInstanceId());
                    dataList.add(bean);
                }
                PageInfo pageInfo = new PageInfo(dataList);
                resp.setData(pageInfo);
            }
            resp.setSuccess(true);
            resp.setCode(SysCode.SUCCESS_CODE);
            resp.setMessage("查询待处理任务成功");
        } catch (Exception e) {
            Log.error("查询待处理任务失败", e);
            resp.setSuccess(false);
            resp.setCode(SysCode.SYS_ERROR);
            resp.setMessage("查询待处理任务失败" + e.getMessage());
        }
        return resp;
    }

    @ApiOperation(value = "改变任务处理人")
    @GetMapping("/appointTaskTo")
    @ResponseBody
    public BpmResponse appointTaskTo(String taskId, String userId) {
        BpmResponse resp = new BpmResponse();

        try {
            //校验参数
            if (StringUtils.isBlank(taskId) || StringUtils.isBlank(userId)) {
                resp.setMessage("请求参数" + SysCode.NOT_ALLOW_NULL);
                resp.setCode(SysCode.VALIDATE_ERROR);
                resp.setSuccess(false);
                return resp;
            }
            Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
            //校验参数
            if (task == null || task.getId() == null) {
                resp.setMessage("任务不存在或已完成");
                resp.setCode(SysCode.VALIDATE_ERROR);
                resp.setSuccess(false);
                return resp;
            }
            //任务处理人id
            taskService.delegateTask(taskId, userId);
            resp.setSuccess(true);
            resp.setMessage("改变任务处理人成功");
            resp.setCode(SysCode.SUCCESS_CODE);
        } catch (Exception e) {
            Log.error("改变任务处理人失败", e);
            resp.setSuccess(false);
            resp.setMessage("改变任务处理人失败" + e.getMessage());
            resp.setCode(SysCode.SYS_ERROR);
        }
        return resp;
    }

    @ApiOperation(value = "删除任务")
    @GetMapping("/deleteTask")
    @ResponseBody
    public BpmResponse deleteTask(String taskId) {
        BpmResponse resp = new BpmResponse();
        //todo
        try {
            taskService.deleteTask(taskId);
            resp.setSuccess(true);
            resp.setMessage("删除任务成功");
        } catch (Exception e) {
            Log.error("删除任务失败", e);
            resp.setSuccess(false);
        }
        return resp;
    }

    @ApiOperation(value = "任务办理")
    @PostMapping("/completeTask")
    @ResponseBody
    public BpmResponse completeTask(CompleteTaskRequest req) {
        BpmResponse resp = new BpmResponse();
        try {
            //数据校验
            String error = ValidateUtil.check_completeTask(req);
            if (error != null) {
                Log.error("任务办理，数据校验失败" + error);
                resp.setCode(SysCode.VALIDATE_ERROR);
                resp.setMessage(error);
                resp.setSuccess(false);
                return resp;
            }

            Task task = taskService.createTaskQuery().taskId(req.getTaskId()).singleResult();
            //校验参数
            if (task == null || task.getId() == null) {
                resp.setMessage("任务不存在或已完成");
                resp.setCode(SysCode.VALIDATE_ERROR);
                resp.setSuccess(false);
                return resp;
            }
            //增加批注
            if (req.getComments() != null) {
                taskService.addComment(req.getTaskId(), null, req.getComments());
            }
            Map<String, Object> variables = null;
            if (req.getVariables() == null) {
                variables = new HashMap<String, Object>();
            } else {
                variables = req.getVariables();
            }
            variables.put("userId", task.getAssignee());
            taskService.complete(req.getTaskId(), variables);
            resp.setSuccess(true);
            resp.setMessage("任务办理成功");
            resp.setCode(SysCode.SUCCESS_CODE);
        } catch (Exception e) {
            Log.error("任务办理失败", e);
            resp.setSuccess(false);
            resp.setMessage("任务办理失败" + e.getMessage());
            resp.setCode(SysCode.SYS_ERROR);
        }
        return resp;
    }


    /**
     * 带当前节点的流程图
     *
     * @param request
     * @return
     */

    @GetMapping("/process/trace/current")
    @ApiOperation(value = "流程图获取接口", notes = "获取当前流程的流程图")
    @ResponseBody
    public byte[] traceProcessImage(SpecialRequest request, HttpServletResponse response) {
        try {
            byte[] bytes = activitiService.traceProcessImage(request);
            /*OutputStream toClient=response.getOutputStream();
            toClient.write(bytes);
            toClient.flush();
            toClient.close();*/
            return bytes;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @GetMapping("/process/trace")
    @ApiOperation(value = "流程图接口", notes = "获取流程图信息")
    public byte[] processImage(SpecialRequest request, HttpServletResponse response) {
        try {
            byte[] bytes = activitiService.getProcessImage(request);
            return bytes;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    @GetMapping("/process/getdeployMent")
    @ApiOperation(value = "流程图接口", notes = "获取流程图信息")
    public byte[] getdeployMent(SpecialRequest request, HttpServletResponse response) {
        try {
            byte[] bytes = activitiService.getdeployMent(request);
            return bytes;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @ApiOperation(value = "根据任务id获取本节点的所有出路")
    @GetMapping("/outGoing")
    @ResponseBody
    public BpmResponse outGoing(String taskId) {
        BpmResponse resp = new BpmResponse();
        try {

            Task myTask = taskService.createTaskQuery().taskId(taskId).singleResult();
            BpmnModel bpmnModel = repositoryService.getBpmnModel(myTask.getProcessDefinitionId());
            UserTask userTask = (UserTask)bpmnModel.getFlowElement(myTask.getTaskDefinitionKey());
            List<SequenceFlow> outgoingFlows = userTask.getOutgoingFlows();
            List<BtnBean> buttons = new ArrayList<>();
            outgoingFlows.forEach(sequenceFlow -> {
                FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement();
                if(targetFlowElement instanceof ExclusiveGateway){
                    List<SequenceFlow> out = ((ExclusiveGateway) targetFlowElement).getOutgoingFlows();
                    out.forEach(sequenceFlow1 -> {
                        if (StringUtils.isNotBlank(sequenceFlow1.getName())) {
                            BtnBean btn = new BtnBean();
                            btn.setBtnKey(sequenceFlow1.getName());
                            btn.setBtnValue(sequenceFlow1.getId());
                            buttons.add(btn);
                        }
                    });


                }
                if (targetFlowElement instanceof UserTask) {
                    if (StringUtils.isNotBlank(targetFlowElement.getName())) {
                        BtnBean btn = new BtnBean();
                        btn.setBtnValue(targetFlowElement.getName());
                        btn.setBtnKey(targetFlowElement.getName());
                        buttons.add(btn);
                    } else {
                        BtnBean btn = new BtnBean();
                        btn.setBtnValue("提交");
                        btn.setBtnKey("提交");
                        buttons.add(btn);
                    }
                }
                if (targetFlowElement instanceof EndEvent) {
                    BtnBean btn = new BtnBean();
                    btn.setBtnValue("结束");
                    btn.setBtnKey("结束");
                    buttons.add(btn);
                }

            });
            resp.setData(buttons);
            resp.setSuccess(true);
            resp.setMessage("根据任务id获取本节点的所有出路成功");
        } catch (Exception e) {
            Log.error("根据任务id获取本节点的所有出路失败", e);
            resp.setSuccess(false);
        }
        return resp;
    }

}
