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

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.List;

/**
 * 流程执行事件发布器
 * <p>
 * 自动收集所有 Spring 容器中实现了 {@link FlowExecutionListener} 的 Bean，
 * 在流程执行的关键节点发布事件通知。
 */
@Slf4j
@Component
public class FlowExecutionEventPublisher {

    private final List<FlowExecutionListener> listeners;

    public FlowExecutionEventPublisher(List<FlowExecutionListener> listeners) {
        this.listeners = listeners != null ? listeners : Collections.emptyList();
        if (!this.listeners.isEmpty()) {
            log.info("已注册 {} 个流程执行监听器: {}", this.listeners.size(),
                    this.listeners.stream().map(l -> l.getClass().getSimpleName()).toArray());
        }
    }

    /**
     * 发布流程执行事件，通知所有监听器
     *
     * @param event 事件对象
     */
    public void publishEvent(FlowExecutionEvent event) {
        if (listeners.isEmpty()) {
            return;
        }
        for (FlowExecutionListener listener : listeners) {
            if (!shouldDispatch(listener, event)) {
                continue;
            }
            try {
                listener.onEvent(event);
            } catch (Exception e) {
                log.error("流程执行监听器 [{}] 处理事件 [{}] 异常: {}",
                        listener.getClass().getSimpleName(), event.getEventType(), e.getMessage(), e);
            }
        }
    }

    /**
     * 判断是否应该将事件分发给指定监听器
     * <p>
     * 分发规则：
     * 1. 如果事件的 moduleCode 为空，则不发送给任何监听器（避免无效调用）
     * 2. 如果监听器的 moduleCode 为空，则不接收任何事件
     * 3. 只有当两者的 moduleCode 匹配时才分发
     *
     * @param listener 监听器
     * @param event    事件对象
     * @return true 表示应该分发，false 表示跳过
     */
    private boolean shouldDispatch(FlowExecutionListener listener, FlowExecutionEvent event) {
        // 事件或模块编码为空，不分发
        if (event == null || StrUtil.isBlank(event.getModuleCode())) {
            log.warn("事件模块编码为空，跳过分发: eventType={}", event != null ? event.getEventType() : null);
            return false;
        }
        
        // 监听器模块编码为空，不接收事件
        String listenerModuleCode = listener.getModuleCode();
        if (StrUtil.isBlank(listenerModuleCode)) {
            log.warn("监听器 [{}] 模块编码为空，不接收事件", listener.getClass().getSimpleName());
            return false;
        }
        
        // 精确匹配模块编码（忽略大小写）
        boolean matched = StrUtil.equalsIgnoreCase(event.getModuleCode(), listenerModuleCode);
        if (!matched) {
            log.debug("监听器 [{}] 模块编码 [{}] 与事件模块编码 [{}] 不匹配，跳过",
                    listener.getClass().getSimpleName(), listenerModuleCode, event.getModuleCode());
        }
        return matched;
    }
}
