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


import static org.springblade.flow.base.util.BpmnModelUtils.getAttributeValueByTaskDefinitionKey;
import static org.springblade.flow.engine.custom.constants.GlobalProcessVariableConstants.CALL_ACTIVITY_FLAG;

import java.util.Date;
import java.util.List;

import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.StartEvent;
import org.flowable.bpmn.model.UserTask;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
import org.flowable.common.engine.impl.event.FlowableEntityEventImpl;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.TaskService;
import org.flowable.task.service.delegate.DelegateTask;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.springblade.flow.base.UserInfo;
import org.springblade.flow.base.util.ActivitiNativeTaskQueryUtils;
import org.springblade.flow.base.util.BpmnModelUtils;
import org.springblade.flow.base.util.SpringContextHolder;
import org.springblade.flow.engine.assembly.UserTaskExPropertyDTO;
import org.springblade.flow.engine.entity.FlowTaskOperatorEntity;
import org.springblade.flow.engine.entity.FlowTaskOperatorRecordEntity;
import org.springblade.flow.engine.enums.FlowNodeEnum;
import org.springblade.flow.engine.enums.FlowRecordEnum;
import org.springblade.flow.engine.enums.FlowTaskOperatorEnum;
import org.springblade.flow.engine.service.FlowTaskOperatorRecordService;
import org.springblade.flow.engine.service.FlowTaskOperatorService;
import org.springblade.flow.util.UserProvider;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import lombok.extern.slf4j.Slf4j;

/**
 * @Author:LoveMyOrange
 * @Description: 首节点自动跳过功能
 * @Date:Created in 2021/12/30 21:49
 */
@Component
@Slf4j
public class FirstActivityAutoCompleteListener implements FlowableEventListener {
    @Override
    public void onEvent(FlowableEvent activitiEvent) {
        if (!(activitiEvent instanceof FlowableEntityEventImpl)) {
            return;
        }

        FlowableEntityEventImpl activitiEntityEventImpl = (FlowableEntityEventImpl) activitiEvent;
        Object entity = activitiEntityEventImpl.getEntity();

        if (!(entity instanceof TaskEntity)) {
            return;
        }

        TaskEntity taskEntity = (TaskEntity) entity;
        Object variable = taskEntity.getVariable(CALL_ACTIVITY_FLAG);

        //只有子流程才用到 自动提交的全局监听器功能 剩下的 还是手动调用complete实现即可
        if(variable==null){
            return;
        }
        try {
            //如果是流程的第一步，则自动提交
            this.onCreate(taskEntity);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

    }
    /**
     * 如果失败 抛异常 即可回滚事务
     * @return
     */
    @Override
    public boolean isFailOnException() {
        return true;
    }

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

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

    private void onCreate(DelegateTask delegateTask) throws Exception {
        //如果是流程的第一步，则自动提交
        UserTask userTask = findFirstActivity(delegateTask.getProcessDefinitionId());
        if (!userTask.getId().equals(delegateTask.getTaskDefinitionKey())) {
            return;
        }
        //判断是否存在历史节点,存在说明第一个节点已经自动审批过
        //判断是不是第一次进入该节点, 如果不是则肯定是驳回回来的,那么 驳回回来的是需要发站内信的,
        ActivitiNativeTaskQueryUtils activitiNativeTaskQueryUtils = SpringContextHolder.getBean(ActivitiNativeTaskQueryUtils.class);
        Long count = activitiNativeTaskQueryUtils.firstActivityFlag(delegateTask.getTaskDefinitionKey(), delegateTask.getProcessInstanceId());
        //说明是第二次进入
        if(count>1) {
            return;
        }
        else{
            TaskService taskService = SpringContextHolder.getBean(TaskService.class);
            UserProvider userProvider = SpringContextHolder.getBean(UserProvider.class);
            FlowTaskOperatorService flowTaskOperatorService = SpringContextHolder.getBean(FlowTaskOperatorService.class);
            RepositoryService repositoryService = SpringContextHolder.getBean(RepositoryService.class);
            FlowTaskOperatorRecordService flowTaskOperatorRecordService = SpringContextHolder.getBean(FlowTaskOperatorRecordService.class);
            UserInfo userInfo = userProvider.get();
            taskService.complete(delegateTask.getId());

            QueryWrapper<FlowTaskOperatorEntity> queryWrapper=new QueryWrapper<>();
            queryWrapper.lambda().eq(FlowTaskOperatorEntity::getTaskNodeId,delegateTask.getId())
                    .eq(FlowTaskOperatorEntity::getTaskId,delegateTask.getProcessInstanceId())
                    .eq(FlowTaskOperatorEntity::getHandleId, userInfo.getUserId())
                    .orderByAsc(FlowTaskOperatorEntity::getCreatorTime);
            List<FlowTaskOperatorEntity> list = flowTaskOperatorService.list(queryWrapper);
            FlowTaskOperatorEntity flowTaskOperatorEntity = list.get(0);
            //提交记录
            FlowTaskOperatorRecordEntity flowTaskOperatorRecordEntity = new FlowTaskOperatorRecordEntity();
            flowTaskOperatorRecordEntity.setHandleOpinion("自动通过");
            flowTaskOperatorRecordEntity.setHandleId(userInfo.getUserId());
            flowTaskOperatorRecordEntity.setHandleName(userInfo.getUserName());
            flowTaskOperatorRecordEntity.setHandleTime(new Date());
            flowTaskOperatorRecordEntity.setHandleStatus(FlowRecordEnum.submit.getCode());
            flowTaskOperatorRecordEntity.setOperatorId(userInfo.getUserId());
            flowTaskOperatorRecordEntity.setNodeCode(delegateTask.getTaskDefinitionKey());
            flowTaskOperatorRecordEntity.setNodeName("开始");
            flowTaskOperatorRecordEntity.setTaskOperatorId(flowTaskOperatorEntity.getId());
            flowTaskOperatorRecordEntity.setTaskNodeId(delegateTask.getId());
            flowTaskOperatorRecordEntity.setTaskId(delegateTask.getProcessInstanceId());
            BpmnModel bpmnModel = repositoryService.getBpmnModel(delegateTask.getProcessDefinitionId());
            Process mainProcess = bpmnModel.getMainProcess();
            String property = getAttributeValueByTaskDefinitionKey(mainProcess, delegateTask.getTaskDefinitionKey(), "userTask");
            UserTaskExPropertyDTO exPropertyDTO = JSONObject.parseObject(property, new TypeReference<UserTaskExPropertyDTO>() {});
            String assigneeType = exPropertyDTO.getUserTaskBasicPropDTO().getAssigneeType();
            flowTaskOperatorRecordEntity.setStatus(FlowTaskOperatorEnum.FreeApprover.getCode().equals(assigneeType) ? FlowNodeEnum.Futility.getCode() : FlowNodeEnum.Process.getCode());
            flowTaskOperatorRecordService.create(flowTaskOperatorRecordEntity);

        }

    }

    /**
     * 找到第一个节点
     * @param processDefinitionId
     * @return
     */
    private UserTask findFirstActivity(String processDefinitionId) {
        Process process = BpmnModelUtils.getBpmnModelMainProcess(processDefinitionId);
        StartEvent startEvent = (StartEvent) process.getInitialFlowElement();
        FlowElement targetFlowElement = startEvent.getOutgoingFlows().get(0).getTargetFlowElement();
        if(targetFlowElement instanceof UserTask){
            return (UserTask)targetFlowElement;
        }
        else{
            return null;
        }
    }

    public RepositoryService getRepositoryService(){
        return SpringContextHolder.getBean(RepositoryService.class);
    }
}
