package org.springblade.flow.engine.custom.type;

import static org.springblade.flow.base.util.BpmnModelUtils.getAttributeValueByTaskDefinitionKey;
import static org.springblade.flow.engine.custom.constants.BasicActivitiConstants.exActivitiPrefixURL;
import static org.springblade.flow.engine.custom.constants.BasicActivitiConstants.extensionAttributeName;

import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.Process;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.delegate.event.impl.FlowableEntityEventImpl;
import org.flowable.engine.impl.RepositoryServiceImpl;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.runtime.Execution;
import org.flowable.task.api.Task;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.springblade.flow.base.util.SpringContextHolder;
import org.springblade.flow.engine.assembly.UserTaskExPropertyDTO;
import org.springblade.flow.engine.assembly.prop.UserTaskBasicPropDTO;
import org.springblade.flow.engine.assembly.prop.UserTaskNodeEventDTO;
import org.springblade.flow.engine.custom.constants.GlobalProcessVariableConstants;
import org.springblade.flow.engine.custom.helper.UserTaskNodeHelper;
import org.springblade.flow.engine.entity.FlowEngineEntity;
import org.springblade.flow.engine.entity.FlowTaskOperatorEntity;
import org.springblade.flow.engine.entity.FlowTaskOperatorRecordEntity;
import org.springblade.flow.engine.enums.FlowTaskOperatorEnum;
import org.springblade.flow.engine.service.FlowEngineService;
import org.springblade.flow.engine.service.FlowTaskOperatorRecordService;
import org.springblade.flow.engine.service.SendMessageService;
import org.springblade.flow.util.wxutil.HttpUtil;
import org.springblade.message.model.MsgResponse;
import org.springblade.system.client.MessageClient;
import org.springblade.system.client.UserClient;
import org.springblade.system.client.model.MessageModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;

import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/**
 * @author LoveMyOrange
 * @create 2022-01-18 17:22
 */
@Slf4j
@Component
public class TaskCompletedListener implements FlowableEventListener {

    @Autowired
    private FlowTaskOperatorRecordService flowTaskOperatorRecordService;

    @Autowired
    private MessageClient messageClient;

    @Autowired
    private UserClient userClient;

    @Autowired
    private SendMessageService sendMessageService;

    @Autowired
    @Lazy
    private FlowEngineService flowEngineService;

    @Autowired
    @Lazy
    private TaskService taskService;

    @Override
    public void onEvent(FlowableEvent activitiEvent) {
        //本地消息提醒
        List<MessageModel> messageModels =new ArrayList<>();

        if (!(activitiEvent instanceof FlowableEntityEventImpl)) {
            return;
        }
        FlowableEntityEventImpl activitiEntityEventImpl = (FlowableEntityEventImpl) activitiEvent;
        Object entity = activitiEntityEventImpl.getEntity();

        if (!(entity instanceof TaskEntity)) {
            return;
        }
        TaskEntity taskEntity = (TaskEntity) entity;
        Map<String, Object> processVariables = taskEntity.getProcessVariables();
        String taskDefinitionKey = taskEntity.getTaskDefinitionKey();
        RepositoryServiceImpl repositoryService = SpringContextHolder.getBean(RepositoryServiceImpl.class);

        Process mainProcess = repositoryService.getBpmnModel(taskEntity.getProcessDefinitionId()).getMainProcess();
        String property = getAttributeValueByTaskDefinitionKey(mainProcess, taskDefinitionKey, "userTask");
        UserTaskExPropertyDTO exPropertyDTO = null;
        if (StringUtils.isNotBlank(property)) {
            exPropertyDTO = JSONObject.parseObject(property, new TypeReference<UserTaskExPropertyDTO>() {
            });
        }
//        根据process.id=activiti_testuserprofile截取流程code,通过唯一code查询流程
        String[] split = mainProcess.getId().split("_");
        String code = split[1];
        LambdaQueryWrapper<FlowEngineEntity> lambdaQueryWrapper = new LambdaQueryWrapper();
        lambdaQueryWrapper.eq(FlowEngineEntity::getEnCode, code);
        FlowEngineEntity engine = flowEngineService.getOne(lambdaQueryWrapper);


        UserTaskNodeEventDTO userTaskNodeEventDTO = exPropertyDTO.getUserTaskNodeEventDTO();
        UserTaskBasicPropDTO userTaskBasicPropDTO = exPropertyDTO.getUserTaskBasicPropDTO();
        if (!userTaskBasicPropDTO.getAssigneeType().equals(FlowTaskOperatorEnum.InitiatorMe.getCode())){//发起者本人
            RuntimeService runtimeService = SpringContextHolder.getBean(RuntimeService.class);
            //判断当前节点是或签还是会签，会签是否有加签，判断会签比例
            Execution execution = runtimeService.createExecutionQuery()
                    .executionId(taskEntity.getExecutionId()).singleResult();
            ExecutionEntity executionEntity = (ExecutionEntity) execution;
            String currentActivityId = execution.getActivityId();
            BpmnModel bpmnModel = repositoryService.getBpmnModel(taskEntity.getProcessDefinitionId());
            FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(currentActivityId);
            // 输出连线
            List<SequenceFlow> outFlows = flowNode.getOutgoingFlows();
            SequenceFlow sequenceFlow=outFlows.get(0);
            // 下一个审批节点
            FlowElement targetFlow = sequenceFlow.getTargetFlowElement();
            Boolean flag=false;
            if (userTaskBasicPropDTO.getCounterSign() ==1){//会签
                int completedInstance = (int)executionEntity.getVariable("nrOfCompletedInstances")+1;
                int nrOfInstances = (int)executionEntity.getVariable("nrOfInstances");
                if(new BigDecimal(completedInstance).divide(new BigDecimal(nrOfInstances),2, RoundingMode.HALF_UP).multiply(new BigDecimal(100)).intValue() >= userTaskBasicPropDTO.getCountersignRatio().intValue()){//完成会签
                    flag=true;
                }

            }else if (userTaskBasicPropDTO.getCounterSign() ==0){//或签
                flag=true;
            }
            if (flag){
                //判断是审批节点还是结束节点
                if (targetFlow instanceof UserTask) {
                    UserTaskNodeHelper userTaskNodeHelper = SpringContextHolder.getBean(UserTaskNodeHelper.class);
                    UserTask userTask = (UserTask) targetFlow;
                    String activityId = targetFlow.getId();
                    String prop = userTask.getAttributeValue(exActivitiPrefixURL, extensionAttributeName);
                    UserTaskExPropertyDTO exPropertyDTO1 = JSONObject.parseObject(prop, new TypeReference<UserTaskExPropertyDTO>() {});
                    UserTaskBasicPropDTO userTaskBasicPropDTO1 = exPropertyDTO1.getUserTaskBasicPropDTO();
                    String flowId = MapUtil.getStr(processVariables, GlobalProcessVariableConstants.FLOW_ENGINE_ID);
                    HashMap<String, String> taskInfoMap = MapUtil.newHashMap();
                    taskInfoMap.put("processDefinitionId",taskEntity.getProcessDefinitionId());
                    taskInfoMap.put("taskDefinitionKey",userTask.getId());
                    taskInfoMap.put("processInstanceId",execution.getProcessInstanceId());
                    List<String> assignUserList = userTaskNodeHelper.getAssignUserList(exPropertyDTO1, taskInfoMap, flowId);
                    String subject="流程待审批"; String content= "您的任务"+engine.getFullName()+"，需要审批!";
                    for (String userId : assignUserList){
                        MessageModel messageModel=new MessageModel();
                        messageModel.setStatus(0);
                        messageModel.setCreateTime(new Date());
                        messageModel.setModule("engine");
                        messageModel.setSubject(subject);
                        messageModel.setContent(content);
                        messageModel.setType(0);
                        messageModel.setUserId(Long.valueOf(userId));
                        messageModels.add(messageModel);
                    }

                    if (engine.getMessageOn()==1){//开启三方推送
                        //三方推送的userid集合
                        List<String>approverList=new ArrayList<>();
                        List<String> approversts = userTaskBasicPropDTO1.getApproversts();
                        if (approversts!= null && approversts.size()>0 ){
                            for (String approver : approversts){
                                if (!approverList.contains(approver)){
                                    approverList.add(approver);
                                }
                            }
                        }
                        if (approverList.size()>0){
                            MsgResponse msgResponse = sendMessageService.sendMsg(approverList, engine.getNotifyType(), subject, content);
                            log.info(msgResponse.getMsg());
                        }
                    }
                }else if (targetFlow instanceof EndEvent){//提醒发起人
                    LambdaQueryWrapper<FlowTaskOperatorRecordEntity> queryWrapper = new LambdaQueryWrapper();
                    queryWrapper.eq(FlowTaskOperatorRecordEntity::getTaskId, taskEntity.getProcessInstanceId());
                    queryWrapper.orderByAsc(FlowTaskOperatorRecordEntity::getHandleTime);
                    List<FlowTaskOperatorRecordEntity> list = flowTaskOperatorRecordService.list(queryWrapper);
                    //消息提醒
                    String subject="审批完成"; String content= engine.getFullName()+"审批完成!";
                    MessageModel messageModel=new MessageModel();
                    messageModel.setStatus(0);
                    messageModel.setCreateTime(new Date());
                    messageModel.setModule("engine");
                    messageModel.setSubject(subject);
                    messageModel.setContent(content);
                    messageModel.setType(2);
                    messageModel.setUserId(Long.valueOf(list.get(0).getHandleId()));
                    messageModels.add(messageModel);
                    if (engine.getMessageOn()==1){//开启三方推送
                        //三方推送的userid集合
                        List<String>userIds=new ArrayList<>();
                        userIds.add(list.get(0).getHandleId());
                        MsgResponse msgResponse = sendMessageService.sendMsg(userIds, engine.getNotifyType(), subject, content);
                        log.info(msgResponse.getMsg());
                        }
                }else if(targetFlow instanceof ParallelGateway){// 下个节点是网关（调用下面的方法）
//                    ParallelGateway parallelGateway=(ParallelGateway)targetFlow;
//                    List<SequenceFlow> outgoingFlows = parallelGateway.getOutgoingFlows();
//                    SequenceFlow flow = outgoingFlows.get(0);
//                    // 下一个审批节点
//                    FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement();
//                    //判断是审批节点还是结束节点
//                    if (targetFlowElement instanceof UserTask) {
//                        UserTaskNodeHelper userTaskNodeHelper = SpringContextHolder.getBean(UserTaskNodeHelper.class);
//                        UserTask userTask = (UserTask) targetFlow;
//                        String activityId = targetFlow.getId();
//                        String prop = userTask.getAttributeValue(exActivitiPrefixURL, extensionAttributeName);
//                        UserTaskExPropertyDTO exPropertyDTO1 = JSONObject.parseObject(prop, new TypeReference<UserTaskExPropertyDTO>() {});
//                        String flowId = MapUtil.getStr(processVariables, GlobalProcessVariableConstants.FLOW_ENGINE_ID);
//                        HashMap<String, String> taskInfoMap = MapUtil.newHashMap();
//                        taskInfoMap.put("processDefinitionId",taskEntity.getProcessDefinitionId());
//                        taskInfoMap.put("taskDefinitionKey",userTask.getId());
//                        taskInfoMap.put("processInstanceId",execution.getProcessInstanceId());
//                        List<String> assignUserList = userTaskNodeHelper.getAssignUserList(exPropertyDTO1, taskInfoMap, flowId);
//                        String subject="流程待审批"; String content= "您的任务"+engine.getFullName()+"，需要审批!";
//                        for (String userId : assignUserList){
//                            MessageModel messageModel=new MessageModel();
//                            messageModel.setStatus(0);
//                            messageModel.setCreateTime(new Date());
//                            messageModel.setModule("engine");
//                            messageModel.setSubject(subject);
//                            messageModel.setContent(content);
//                            messageModel.setType(0);
//                            messageModel.setUserId(Long.valueOf(userId));
//                            messageModels.add(messageModel);
//                        }
//
//                        if (engine.getMessageOn()==1){//开启三方推送
//                            //三方推送的userid集合
//                            List<String>approverList=new ArrayList<>();
//                            List<String> approversts = userTaskBasicPropDTO.getApproversts();
//                            if (approversts!= null && approversts.size()>0 ){
//                                for (String approver : approversts){
//                                    if (!approverList.contains(approver)){
//                                        approverList.add(approver);
//                                    }
//                                }
//                            }
//                            if (approverList.size()>0){
//                                MsgResponse msgResponse = sendMessageService.sendMsg(approverList, engine.getNotifyType(), subject, content);
//                                log.info(msgResponse.getMsg());
//                            }
//                        }
//                    }

                } else if(targetFlow instanceof ExclusiveGateway){
                    List<SequenceFlow> outgoingFlows = ((ExclusiveGateway) targetFlow).getOutgoingFlows();
                    SequenceFlow flow = outgoingFlows.get(0);
                    FlowElement flowElement = flow.getTargetFlowElement();
                    if (flowElement instanceof ParallelGateway){
                        List<SequenceFlow> sequenceFlowList = ((ParallelGateway) flowElement).getOutgoingFlows();
                        if (sequenceFlowList != null && sequenceFlowList.size()>0){
                            for (SequenceFlow s : sequenceFlowList){
                                FlowElement targetFlowElement = s.getTargetFlowElement();
                                if (targetFlowElement instanceof UserTask){
                                    UserTask task=(UserTask)targetFlowElement;
                                    //获取节点信息
                                    String prop = task.getAttributeValue(exActivitiPrefixURL, extensionAttributeName);
                                    UserTaskExPropertyDTO exProperty = JSONObject.parseObject(prop, new TypeReference<UserTaskExPropertyDTO>() {});
                                    UserTaskBasicPropDTO basicPropDTO = exProperty.getUserTaskBasicPropDTO();
                                    List<String> approvers = basicPropDTO.getApprovers();
                                    String subject="流程待审批"; String content= "您的任务"+engine.getFullName()+"，需要审批!";
                                    for (String userId : approvers){
                                        MessageModel messageModel=new MessageModel();
                                        messageModel.setStatus(0);
                                        messageModel.setCreateTime(new Date());
                                        messageModel.setModule("engine");
                                        messageModel.setSubject(subject);
                                        messageModel.setContent(content);
                                        messageModel.setType(0);
                                        messageModel.setUserId(Long.valueOf(userId));
                                        messageModels.add(messageModel);
                                    }
                                    if (engine.getMessageOn()==1){//开启三方推送
                                        //三方推送的userid集合
                                        List<String>approverList=new ArrayList<>();
                                        List<String> approversts = basicPropDTO.getApproversts();
                                        if (approversts!= null && approversts.size()>0 ){
                                            for (String approver : approversts){
                                                if (!approverList.contains(approver)){
                                                    approverList.add(approver);
                                                }
                                            }
                                        }
                                        if (approverList.size()>0){
                                            MsgResponse msgResponse = sendMessageService.sendMsg(approverList, engine.getNotifyType(), subject, content);
                                        }
                                    }


                                }
                            }
                        }
                    }
                }
            }
        }
        if (messageModels.size()>0){
            messageClient.saveBatch(messageModels);
        }

        //目前只有发起节点才有结束事件
       Boolean endFlag= userTaskNodeEventDTO.getHasStartActivityEndEventEnable()!=null ? userTaskNodeEventDTO.getHasStartActivityEndEventEnable():false;
       if(endFlag){
           String startActivityEndEventInterfaceType = userTaskNodeEventDTO.getStartActivityEndEventInterfaceType();
           String startActivityEndEventURL = userTaskNodeEventDTO.getStartActivityEndEventURL();
           HttpUtil.httpRequestAll(startActivityEndEventURL, "GET", null);
       }
        log.info("任务完成监听器触发.."+activitiEvent.getClass());
    }

    @Override
    public boolean isFailOnException() {
        return true;
    }

    @Override
    public boolean isFireOnTransactionLifecycleEvent() {
        return false;
    }

    @Override
    public String getOnTransaction() {
        return null;
    }



}
