package cn.axzo.workflow.server.controller.listener.error;

import cn.axzo.workflow.core.listener.BpmnAsyncJobEventListener;
import cn.axzo.workflow.server.common.annotation.ReporterType;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.common.engine.impl.event.FlowableEntityExceptionEventImpl;
import org.flowable.job.api.JobInfo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.util.Objects;

import static org.flowable.common.engine.api.delegate.event.FlowableEngineEventType.JOB_EXECUTION_FAILURE;

/**
 * 异步任务执行异常的扩展监听器
 *
 * @author wangli
 * @since 2024/4/17 16:59
 */
@Slf4j
@Component
@Scope("prototype")
public class ErrorReporterEventListener implements BpmnAsyncJobEventListener {
    @Value("${spring.profiles.active}")
    private String profile;
    @Value("${workflow.sendDingTalk:true}")
    private Boolean sendDingTalk;

    @Override
    public boolean support(FlowableEngineEventType eventType) {
        return Objects.equals(JOB_EXECUTION_FAILURE, eventType);
    }

    @Override
    public void notify(FlowableEvent flowableEvent) {
        if (!(flowableEvent instanceof FlowableEntityExceptionEventImpl)) {
            return;
        }
        FlowableEntityExceptionEventImpl event = (FlowableEntityExceptionEventImpl) flowableEvent;
        JobInfo job = (JobInfo) event.getEntity();
        Throwable throwable = event.getCause();
        ReporterType reporterType = ReporterType.ONLY_LOG;
        if (Lists.newArrayList("dev", "test", "pre").contains(profile)) {
            reporterType = ReporterType.BOTH;
        } else if (Lists.newArrayList("live", "master").contains(profile)) {
            reporterType = ReporterType.ONLY_LOG;
        }
        if (job.getRetries() <= 1) {
            reporterType.executeAction(profile, "异步任务执行异常, 重试 3 次后仍未成功", sendDingTalk, new Object[]{job}, "act_ru_job", throwable, false);
        }
    }

    @Override
    public int getOrder() {
        return Integer.MIN_VALUE;
    }

}
