package com.cmvr.test.flow.runtime.interceptor;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.cmvr.common.exception.GlobalException;
import com.cmvr.test.flow.context.TaskInstHolder;
import com.cmvr.test.flow.runtime.event.FlowExecutionEventPublisher;
import com.cmvr.test.flow.runtime.message.TaskNodeExecuteMessage;
import com.cmvr.test.flow.runtime.message.TaskNodeExecuteResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.function.Function;

@Slf4j
@Component
@Order(3)
public class FlowExceptionInterceptor extends AbstractFlowMsgPreInterceptor {

    private final TaskInstHolder taskInstHolder;

    public FlowExceptionInterceptor(FlowExecutionEventPublisher eventPublisher, TaskInstHolder taskInstHolder) {
        super(eventPublisher);
        this.taskInstHolder = taskInstHolder;
    }

    @Override
    public TaskNodeExecuteResult doIntercept(TaskNodeExecuteMessage message,
                                           Function<TaskNodeExecuteMessage, TaskNodeExecuteResult> next) {
        try {
            return next.apply(message);
        } catch (Exception e) {
            log.error("节点执行异常：instId={}, nodeId={}, action={}",
                    message.getInstId(), message.getNodeId(), message.getAction(), e);

            if (ExceptionUtil.getRootCause(e) instanceof InterruptedException) {
                log.info("节点被中断退出: {}", message.getNodeId());
                return null;
            }
            taskInstHolder.markFailed(
                    message.getInstId(),
                    message.getTaskId(),
                    message.getItemId(),
                    message.getNodeId(),
                    message.getNodeType(),
                    message.getAction().getOperate(), message.getAction().getOperate(),
                    ObjUtil.isEmpty(message.getInputParams()) ? null : message.getInputParams().toJSONString(),
                    "执行异常：" + StrUtil.sub(ExceptionUtil.getMessage(e), 0, 480),
                    message.getIterations()
            );
            throw new GlobalException("任务执行失败", e);
        }
    }
}
