package com.huigou.topsun.base;

import org.activiti.engine.HistoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.DelegateTask;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

/**
 * 在处理完流程事件之后检查bizCode是否重复。
 *
 * @author yonghuan
 */
@Component
@Aspect
public class DuplicatedBizCodeInspector {

    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private HistoryService historyService;

    /**
     * 拦截用户任务事件
     */
    @Around("execution(* notify(org.activiti.engine.delegate.DelegateTask))")
    public Object onTaskEvent(ProceedingJoinPoint pjp) throws Throwable {
        DelegateTask task = (DelegateTask) pjp.getArgs()[0];
        Object returnVal = pjp.proceed(pjp.getArgs());
        doInspect(task.getExecution());
        return returnVal;
    }

    /**
     * 拦截流程执行事件
     */
    @Around("execution(* notify(org.activiti.engine.delegate.DelegateExecution))")
    public Object onExecutionEvent(ProceedingJoinPoint pjp) throws Throwable {
        DelegateExecution execution = (DelegateExecution) pjp.getArgs()[0];
        Object returnVal = pjp.proceed(pjp.getArgs());
        doInspect(execution);
        return returnVal;
    }

    /**
     * 检查bizCode是否重复
     */
    private void doInspect(DelegateExecution delegateExecution) {
        if (delegateExecution != null) {
            String bizId = delegateExecution.getProcessBusinessKey();
            if (bizId != null) {
                // 判断正在运行的流程中是否存在重复的bizId
                boolean existsDuplicatedBizId = runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(bizId).list()
                        .stream()
                        .filter(pi -> !pi.getId().equals(delegateExecution.getProcessInstanceId()))
                        .findAny()
                        .isPresent();
                if (existsDuplicatedBizId == false) {
                    // 判断历史流程中是否存在重复的bizId
                    existsDuplicatedBizId = historyService.createHistoricProcessInstanceQuery().processInstanceBusinessKey(bizId).list()
                            .stream()
                            .filter(hpi -> !hpi.getId().equals(delegateExecution.getProcessInstanceId()))
                            .findAny()
                            .isPresent();
                }
                Assert.isTrue(existsDuplicatedBizId == false, String.format("重复的bizId:%s", bizId));
            }
        }
    }
}
