package com.zcxk.process.activiti.listener;

import com.alibaba.fastjson.JSON;

import com.zcxk.process.activiti.model.RejectConfig;
import com.zcxk.process.activiti.model.TaskExtendConfig;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.TaskListener;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmActivity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationContext;

import java.util.*;

/**
 * 当任务上有驳回操作时候配置次任务监听器，解决驳回业务回退问题
 *
 * @author wilian.peng
 * @Description
 * @date 2019年7月12日 下午4:50:32
 */
@Slf4j
public class ReturnTaskListener implements TaskListener {
    /**
     *
     */
    private static final long serialVersionUID = -7696985494244116795L;

    private ApplicationContext context;


    @Override
    public void notify(DelegateTask currentTask) {
        log.info("begin ReturnTaskListener currentTask ={}", currentTask.getId());
        String eventName = currentTask.getEventName();
        if ("create".endsWith(eventName)) {
            // 1,获取任务的上一任务
            DelegateExecution execution = currentTask.getExecution();

            String currentActivityId = execution.getCurrentActivityId();
            String processInstanceId = currentTask.getProcessInstanceId();
            String currentTaskId = currentTask.getId();
            ProcessInstance processInstance = getProcessInstance(processInstanceId, execution);
            if (processInstance == null) { // 找不到流程实例
                return;
            }

            HistoricTaskInstance preTask = getPrevTaskByCurrentTaskId(processInstanceId, currentTaskId, currentActivityId, execution);
            String var_action = (String) currentTask.getVariable("action");
            // 2,判断是否由驳回后进入的任务
            if (preTask != null && "reject".equals(var_action)) {
                // 3,获取驳回后的处理人信息
                String description = currentTask.getDescription(); // 任务描述中包含驳回后的处理人信息
                TaskExtendConfig config = JSON.parseObject(description, TaskExtendConfig.class);
                List<RejectConfig> rejectConfigList = config.getRejectConfig();
                if (rejectConfigList != null && rejectConfigList.size() != 0) {
                    RejectConfig cfg = getRejectConfig(rejectConfigList, preTask.getTaskDefinitionKey());
                    if (cfg != null && StringUtils.isNotBlank(cfg.getAssignee())) {
                        // 4,设置当前步骤的处理人,从节点的历史处理任务中查找
                        String taskAssignee = getTaskAssigneeByRejectConfig(processInstanceId, currentTask.getTaskDefinitionKey(), cfg, execution);
                        currentTask.setAssignee(taskAssignee);
                        // 5,微信通知驳回人
                        if (StringUtils.isNotEmpty(taskAssignee)) {
                            String waterMeterNo = String.valueOf(currentTask.getVariable("waterMeterNo"));
                            String comment = getTaskComment(preTask.getId(), execution);
                            try {
                                // TODO
//								WechatNotifyService wechatNotifyService = ApplicationContextHelper.popBean(WechatNotifyService.class) ;
//							    UserMapper userMapper = ApplicationContextHelper.popBean(UserMapper.class);
//								String auditUserId = preTask.getAssignee() ;
//								if(auditUserId ==null) log.info("auditUserId为空");
//								if(userMapper ==null) log.info("userMapper为空");
//								if(wechatNotifyService ==null) log.info("wechatNotifyService为空");
//								log.info("get audit user information , auditUserId={} ",auditUserId);
//								User auditUser = userMapper.findUserById(Integer.parseInt(auditUserId));
//								log.info("get audit user information , auditUserId={},auditUser ={}",auditUserId, JSON.toJSONString(auditUser));
//								wechatNotifyService.sendWorkOrderRejectNotice(Integer.parseInt(taskAssignee),
//										processInstance.getBusinessKey(), // 工单内容
//										"您的工单未通过验收,请及时处理。",  // 工单内容
//										processInstance.getBusinessKey(), // 工单号
//										waterMeterNo, // 水表电子号
//										auditUser.getName(), // 验收人
//										comment, // 驳回原因
//										"");//
                            } catch (Exception e) {
                                log.error("微信通知驳回人失败", e);
                            }

                        }
                    }
                }
            }

        }
    }

    protected String getTaskComment(String taskId, DelegateExecution execution) {
        TaskService taskService = execution.getEngineServices().getTaskService();
        List<Comment> taskComments = taskService.getTaskComments(taskId);
        if (taskComments.size() != 0) {
            return taskComments.get(0).getFullMessage();
        } else
            return null;
    }

    protected ProcessInstance getProcessInstance(String processInstanceId, DelegateExecution execution) {
        RuntimeService runtimeService = execution.getEngineServices().getRuntimeService();
        ProcessInstance pi = runtimeService.createProcessInstanceQuery().
                processInstanceId(processInstanceId).
                singleResult();
        return pi;
    }

    protected String getTaskAssigneeByRejectConfig(String instanceId, String taskKey, RejectConfig cfg, DelegateExecution execution) {
        log.info("begin getTaskAssigneeByRejectConfig,instanceId ={}, taskKey={},cfg ={}", instanceId, taskKey, JSON.toJSONString(cfg));
        HistoryService historyService = execution.getEngineServices().getHistoryService();
        List<HistoricTaskInstance> tasks = historyService.createHistoricTaskInstanceQuery().
                processInstanceId(instanceId).
                taskDefinitionKey(taskKey).
                orderByHistoricTaskInstanceEndTime().
                desc().
                list();
        int size = tasks.size();
        String assignee = null;
        if ("last".equals(cfg.getAssignee())) {
            assignee = tasks.get(0).getAssignee();
        } else if ("first".equals(cfg.getAssignee())) {
            assignee = tasks.get(size - 1).getOwner();
        } else {
            System.out.println("unsuport assign type !");
        }
        log.info("end getTaskAssigneeByRejectConfig assignee = {} ", assignee);
        return assignee;
    }


    /**
     * @param instanceId
     * @param taskKey
     * @return
     */
    protected HistoricTaskInstance getHistoryTaskInstance(String instanceId, String taskKey, DelegateExecution execution) {
        HistoryService historyService = execution.getEngineServices().getHistoryService();
        List<HistoricTaskInstance> tasks = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(instanceId).taskDefinitionKey(taskKey).orderByHistoricTaskInstanceEndTime().desc()
                .listPage(0, 1);
        return tasks.get(0);
    }

    /**
     * 根据上一个任务来查找驳回配置信息
     *
     * @param rejectConfigList
     * @param preTaskKey
     * @return
     */
    protected RejectConfig getRejectConfig(List<RejectConfig> rejectConfigList, String preTaskKey) {
        RejectConfig cfg = null;
        for (RejectConfig f : rejectConfigList) {
            if (preTaskKey.equals(f.getFrom())) {
                cfg = f;
                break;
            }
        }
        return cfg;
    }

    /**
     * 获取所有任务信息
     *
     * @param processInstanceId
     * @return
     */
    protected List<ActivityImpl> getAllActivities(String processInstanceId, DelegateExecution execution) {
        List<ActivityImpl> activities = null;
        ProcessInstance processInstance = getProcessInstance(processInstanceId, execution);
        RepositoryService repositoryService = execution.getEngineServices().getRepositoryService();
        ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService).
                getDeployedProcessDefinition(processInstance.getProcessDefinitionId());
        activities = processDefinition.getActivities();
        return activities;
    }

    /**
     * 获取上一步骤任务
     *
     * @param processInstanceId
     * @param taskId
     * @param activityId
     * @return
     */
    protected HistoricTaskInstance getPrevTaskByCurrentTaskId(String processInstanceId, String taskId, String activityId, DelegateExecution execution) {
        log.info("begin getPrevTaskByCurrentTaskId processInstanceId = {}, taskId = {} ,activityId={}", processInstanceId, activityId);
        HistoryService historyService = execution.getEngineServices().getHistoryService();
        HistoricTaskInstance historicTaskInstance = null;
        List<String> prevTaskIds = getPrevTasksByCurrentActivity(processInstanceId, activityId, execution);
        if (prevTaskIds != null && prevTaskIds.size() > 0) {
            Map<String, HistoricActivityInstance> instanceMap = new HashMap<>();
            // 遍历当前节点的所有incoming节点。判断最新的节点是哪个
            for (String preact : prevTaskIds) {
                List<HistoricActivityInstance> activityInstances = historyService.createHistoricActivityInstanceQuery().
                        processInstanceId(processInstanceId).
                        activityId(preact).
                        orderByHistoricActivityInstanceStartTime().
                        desc().list();
                HistoricActivityInstance activityInstance = null;
                if (activityInstances == null || activityInstances.size() == 0) {
                    continue;
                }
                activityInstance = activityInstances.get(0);

                Date endTime = activityInstance.getEndTime();
                HistoricActivityInstance activityInstance1 = instanceMap.get(taskId);
                if (activityInstance1 != null) {
                    Date endTime1 = activityInstance1.getEndTime();
                    if (endTime1.after(endTime)) {
                        continue;
                    }
                    instanceMap.put(taskId, activityInstance);
                } else {
                    instanceMap.put(taskId, activityInstance);
                }

            }
            HistoricActivityInstance activityInstance = instanceMap.get(taskId);
            if (activityInstance != null) {
                String hisTaskId = activityInstance.getTaskId();
                historicTaskInstance = historyService.createHistoricTaskInstanceQuery()
                        .processInstanceId(processInstanceId).taskId(hisTaskId).singleResult();
            }
        }
        log.info("end getPrevTaskByCurrentTaskId historicTaskInstance = {}", JSON.toJSONString(historicTaskInstance));
        return historicTaskInstance;
    }

    protected List<String> getPrevTasksByCurrentActivity(String processInstanceId, String activityId, DelegateExecution execution) {
        List<String> preTaskIds = new ArrayList<>();
        List<ActivityImpl> allActivities = getAllActivities(processInstanceId, execution);
        for (ActivityImpl activity : allActivities) {
            String id = activity.getId();
            if (!id.equals(activityId)) {
                continue;
            }
            List<PvmTransition> incomingTransitions = activity.getIncomingTransitions();

            for (PvmTransition transition : incomingTransitions) {
                PvmActivity source = transition.getSource();
                String preTaskId = source.getId();
                preTaskIds.add(preTaskId);
            }
        }
        return preTaskIds;
    }
}
