package com.flowable.devops.workflow.node.registry;

import com.flowable.devops.entity.NodeType;
import com.flowable.devops.repository.NodeTypeRepository;
import com.flowable.devops.workflow.node.WorkflowNode;
import com.flowable.devops.workflow.plugin.PluginDescriptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import jakarta.annotation.PostConstruct;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 节点类型注册中心
 * 
 * 注意：现在由PluginManager统一管理插件注册
 * 本类主要负责节点类型元数据的查询和管理
 */
@Slf4j
@Service
public class NodeTypeRegistry {

    private final Map<String, NodeType> nodeTypeMetadata = new ConcurrentHashMap<>();

    private final Map<String, WorkflowNode> nodeInstances = new ConcurrentHashMap<>();

    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private NodeTypeRepository nodeTypeRepository;

    @PostConstruct
    public void initialize() {
        log.info("开始初始化节点类型注册中心...");
        log.info("注意：节点类型现在由PluginManager统一管理");

        try {
            // 保留旧的扫描逻辑作为后备方案（兼容性）
            // scanAndRegisterNodes();
            
            loadNodesFromDatabase();
            log.info("节点类型注册中心初始化完成，共注册 {} 个节点类型", nodeTypeMetadata.size());
        } catch (Exception e) {
            log.error("节点类型注册中心初始化失败", e);
        }
    }

    private void scanAndRegisterNodes() {
        Map<String, WorkflowNode> nodeBeans = applicationContext.getBeansOfType(WorkflowNode.class);
        log.info("发现 {} 个WorkflowNode实现类", nodeBeans.size());

        for (Map.Entry<String, WorkflowNode> entry : nodeBeans.entrySet()) {
            try {
                registerNode(entry.getValue(), entry.getKey());
            } catch (Exception e) {
                log.error("注册节点失败: {} - {}", entry.getKey(), e.getMessage());
            }
        }
    }

    private void loadNodesFromDatabase() {
        try {
            List<NodeType> dbNodeTypes = nodeTypeRepository.findByEnabledTrueOrderByDisplayOrderAsc();
            for (NodeType nodeType : dbNodeTypes) {
                if (!nodeTypeMetadata.containsKey(nodeType.getId())) {
                    nodeTypeMetadata.put(nodeType.getId(), nodeType);
                }
            }
        } catch (Exception e) {
            log.warn("从数据库加载节点类型失败: {}", e.getMessage());
        }
    }

    private void registerNode(WorkflowNode node, String beanName) {
        NodeType metadata = node.getMetadata();
        validateNodeMetadata(metadata, beanName);

        String nodeTypeId = metadata.getId();
        if (nodeTypeMetadata.containsKey(nodeTypeId)) {
            log.warn("节点类型ID重复，跳过注册: {}", nodeTypeId);
            return;
        }

        nodeTypeMetadata.put(nodeTypeId, metadata);
        nodeInstances.put(nodeTypeId, node);

        try {
            nodeTypeRepository.save(metadata);
        } catch (Exception e) {
            log.warn("保存节点类型到数据库失败: {}", e.getMessage());
        }

        log.info("✓ 注册节点: {} ({})", metadata.getDisplayName(), nodeTypeId);
    }

    private void validateNodeMetadata(NodeType metadata, String beanName) {
        if (metadata == null || metadata.getId() == null || metadata.getDisplayName() == null) {
            throw new IllegalArgumentException("节点元数据不完整: " + beanName);
        }
    }

    public NodeType getNodeMetadata(String nodeTypeId) {
        return nodeTypeMetadata.get(nodeTypeId);
    }

    public WorkflowNode getNodeInstance(String nodeTypeId) {
        return nodeInstances.get(nodeTypeId);
    }

    public List<NodeType> getAllNodeTypes() {
        return new ArrayList<>(nodeTypeMetadata.values());
    }

    public List<NodeType> getEnabledNodeTypes() {
        return nodeTypeMetadata.values().stream()
            .filter(NodeType::isEnabled)
            .sorted(Comparator.comparing(NodeType::getDisplayName))
            .toList();
    }

    public List<NodeType> getNodeTypesByCategory(NodeType.NodeCategory category) {
        return nodeTypeMetadata.values().stream()
            .filter(nodeType -> Objects.equals(nodeType.getCategory(), category))
            .filter(NodeType::isEnabled)
            .sorted(Comparator.comparing(NodeType::getDisplayName))
            .toList();
    }

    public boolean hasNodeType(String nodeTypeId) {
        return nodeTypeMetadata.containsKey(nodeTypeId);
    }

    public boolean hasNodeImplementation(String nodeTypeId) {
        return nodeInstances.containsKey(nodeTypeId);
    }

    /**
     * 从数据库节点类型注册到注册表
     */
    public void registerFromDatabase(NodeType nodeType) {
        if (nodeType == null || nodeType.getId() == null) {
            log.warn("无效的节点类型，跳过注册");
            return;
        }

        nodeTypeMetadata.put(nodeType.getId(), nodeType);
        log.debug("从数据库注册节点类型: {}", nodeType.getId());
    }
    
    /**
     * 从插件注册节点类型（由PluginManager调用）
     * 
     * @param descriptor 插件描述符
     * @param node 节点实例
     */
    public void registerFromPlugin(PluginDescriptor descriptor, WorkflowNode node) {
        if (descriptor == null || descriptor.getId() == null) {
            log.warn("无效的插件描述符，跳过注册");
            return;
        }
        
        if (node == null) {
            log.warn("节点实例为null，跳过注册: {}", descriptor.getId());
            return;
        }
        
        String nodeId = descriptor.getId();
        
        // 检查是否已注册
        if (nodeTypeMetadata.containsKey(nodeId)) {
            log.debug("节点类型已存在，更新: {}", nodeId);
        }
        
        // 注册元数据
        NodeType metadata = descriptor.getMetadata();
        if (metadata != null) {
            nodeTypeMetadata.put(nodeId, metadata);
            
            // 保存到数据库
            try {
                nodeTypeRepository.save(metadata);
            } catch (Exception e) {
                log.warn("保存节点类型到数据库失败: {} - {}", nodeId, e.getMessage());
            }
        }
        
        // 注册实例
        nodeInstances.put(nodeId, node);
        
        log.debug("插件节点已注册: {} ({})", descriptor.getDisplayName(), nodeId);
    }

    /**
     * 注销节点类型
     */
    public void unregister(String nodeTypeId) {
        if (nodeTypeId != null) {
            nodeTypeMetadata.remove(nodeTypeId);
            nodeInstances.remove(nodeTypeId);
            log.debug("注销节点类型: {}", nodeTypeId);
        }
    }

    /**
     * 清空所有注册的节点类型
     */
    public void clear() {
        nodeTypeMetadata.clear();
        nodeInstances.clear();
        log.debug("清空节点类型注册表");
    }
}