package com.flowable.devops.workflow.plugin;

import com.flowable.devops.entity.NodeType;
import com.flowable.devops.workflow.node.WorkflowNode;
import com.flowable.devops.workflow.node.registry.NodeTypeRegistry;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import jakarta.annotation.PostConstruct;
import java.io.File;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 插件管理器
 * 
 * 职责：
 * 1. 扫描并加载所有插件（内置 + 外部）
 * 2. 管理插件生命周期（启用/禁用/重新加载）
 * 3. 解析插件依赖关系
 * 4. 插件错误处理和日志记录
 * 
 * @author Flowable Team
 * @since 1.0.0
 */
@Slf4j
@Service
public class PluginManager {
    
    /**
     * 所有已注册的插件（pluginId -> PluginDescriptor）
     */
    private final Map<String, PluginDescriptor> plugins = new ConcurrentHashMap<>();
    
    /**
     * 插件实例缓存（pluginId -> WorkflowNode instance）
     */
    private final Map<String, WorkflowNode> pluginInstances = new ConcurrentHashMap<>();
    
    @Autowired
    private ApplicationContext applicationContext;
    
    @Autowired
    private NodeTypeRegistry nodeTypeRegistry;
    
    @Value("${flowable-devops.plugins.directory:./plugins}")
    private String pluginsDirectory;
    
    @Value("${flowable-devops.plugins.auto-load:true}")
    private boolean autoLoad;
    
    /**
     * 系统启动时初始化插件系统
     */
    @PostConstruct
    public void initialize() {
        log.info("========================================");
        log.info("开始初始化插件系统...");
        log.info("插件目录: {}", pluginsDirectory);
        log.info("自动加载: {}", autoLoad);
        log.info("========================================");
        
        try {
            // 1. 扫描并加载内置插件（classpath中的@NodePlugin）
            int internalCount = loadInternalPlugins();
            log.info("✓ 加载内置插件: {} 个", internalCount);
            
            // 2. 扫描并加载外部插件（plugins目录中的JAR）
            if (autoLoad) {
                int externalCount = loadExternalPlugins();
                log.info("✓ 加载外部插件: {} 个", externalCount);
            }
            
            // 3. 解析插件依赖关系
            resolveDependencies();
            log.info("✓ 依赖关系解析完成");
            
            // 4. 注册所有插件到NodeTypeRegistry
            registerAllPlugins();
            log.info("✓ 插件注册完成");
            
            // 5. 打印插件清单
            printPluginSummary();
            
            log.info("========================================");
            log.info("插件系统初始化完成！共加载 {} 个插件", plugins.size());
            log.info("========================================");
            
        } catch (Exception e) {
            log.error("插件系统初始化失败", e);
            throw new RuntimeException("Failed to initialize plugin system", e);
        }
    }
    
    /**
     * 加载内置插件（从classpath扫描@NodePlugin注解）
     */
    private int loadInternalPlugins() {
        log.debug("开始扫描内置插件...");
        
        // 从Spring容器获取所有WorkflowNode实例
        Map<String, WorkflowNode> nodeBeans = applicationContext.getBeansOfType(WorkflowNode.class);
        
        int loadedCount = 0;
        for (Map.Entry<String, WorkflowNode> entry : nodeBeans.entrySet()) {
            String beanName = entry.getKey();
            WorkflowNode node = entry.getValue();
            
            try {
                // 检查是否有@NodePlugin注解
                NodePlugin annotation = node.getClass().getAnnotation(NodePlugin.class);
                
                if (annotation != null) {
                    // 从注解构建插件描述符
                    PluginDescriptor descriptor = buildDescriptorFromAnnotation(annotation, node);
                    
                    // 注册插件
                    registerPlugin(descriptor, node);
                    loadedCount++;
                    
                    log.debug("  ✓ {}: {} ({})", 
                            descriptor.getId(), 
                            descriptor.getDisplayName(), 
                            descriptor.getVersion());
                }
                
            } catch (Exception e) {
                log.error("加载内置插件失败: {} - {}", beanName, e.getMessage(), e);
            }
        }
        
        return loadedCount;
    }
    
    /**
     * 从@NodePlugin注解构建插件描述符
     */
    private PluginDescriptor buildDescriptorFromAnnotation(NodePlugin annotation, WorkflowNode node) {
        LocalDateTime now = LocalDateTime.now();
        
        // 获取节点元数据
        NodeType metadata = node.getMetadata();
        
        return PluginDescriptor.builder()
                .id(annotation.id())
                .name(annotation.name())
                .displayName(annotation.displayName())
                .version(annotation.version())
                .author(annotation.author())
                .description(annotation.description())
                .category(annotation.category())
                .icon(annotation.icon())
                .enabled(annotation.enabled())
                .source(PluginDescriptor.PluginSource.INTERNAL)
                .implementationClass(node.getClass().getName())
                .dependencies(Arrays.asList(annotation.dependencies()))
                .minPlatformVersion(annotation.minPlatformVersion())
                .homepage(annotation.homepage())
                .license(annotation.license())
                .metadata(metadata)
                .status(annotation.enabled() ? 
                        PluginDescriptor.PluginStatus.ACTIVE : 
                        PluginDescriptor.PluginStatus.DISABLED)
                .installedAt(now)
                .loadedAt(now)
                .updatedAt(now)
                .build();
    }
    
    /**
     * 注册插件
     */
    private void registerPlugin(PluginDescriptor descriptor, WorkflowNode node) {
        String pluginId = descriptor.getId();
        
        // 检查ID冲突
        if (plugins.containsKey(pluginId)) {
            log.warn("插件ID冲突，跳过注册: {} (已存在版本: {})", 
                    pluginId, plugins.get(pluginId).getVersion());
            return;
        }
        
        // 保存插件描述符
        plugins.put(pluginId, descriptor);
        
        // 保存插件实例
        pluginInstances.put(pluginId, node);
        
        log.debug("插件已注册: {} v{}", pluginId, descriptor.getVersion());
    }
    
    /**
     * 加载外部插件（从plugins目录扫描JAR文件）
     * 
     * 注意：第一期暂不实现，返回0
     * 第二期实现时需要：
     * 1. 扫描plugins目录
     * 2. 读取每个JAR的plugin.json
     * 3. 使用PluginClassLoader加载
     * 4. 实例化并注册
     */
    private int loadExternalPlugins() {
        File pluginsDir = new File(pluginsDirectory);
        
        if (!pluginsDir.exists() || !pluginsDir.isDirectory()) {
            log.debug("外部插件目录不存在，跳过: {}", pluginsDirectory);
            return 0;
        }
        
        log.debug("扫描外部插件目录: {}", pluginsDirectory);
        
        File[] jarFiles = pluginsDir.listFiles((dir, name) -> 
                name.toLowerCase().endsWith(".jar"));
        
        if (jarFiles == null || jarFiles.length == 0) {
            log.debug("未发现外部插件");
            return 0;
        }
        
        log.info("发现 {} 个外部插件JAR文件", jarFiles.length);
        
        // TODO: 第二期实现外部插件加载
        // for (File jarFile : jarFiles) {
        //     try {
        //         PluginDescriptor descriptor = pluginLoader.loadFromJar(jarFile);
        //         registerPlugin(descriptor, instance);
        //     } catch (Exception e) {
        //         log.error("加载外部插件失败: {}", jarFile.getName(), e);
        //     }
        // }
        
        log.warn("外部插件加载功能尚未实现（将在第二期支持）");
        return 0;
    }
    
    /**
     * 解析插件依赖关系
     */
    private void resolveDependencies() {
        log.debug("开始解析插件依赖关系...");
        
        for (PluginDescriptor plugin : plugins.values()) {
            List<String> dependencies = plugin.getDependencies();
            
            if (dependencies == null || dependencies.isEmpty()) {
                continue;
            }
            
            for (String dependency : dependencies) {
                // 解析依赖格式: pluginId:version
                String[] parts = dependency.split(":");
                String requiredPluginId = parts[0];
                String requiredVersion = parts.length > 1 ? parts[1] : null;
                
                // 检查依赖是否存在
                PluginDescriptor requiredPlugin = plugins.get(requiredPluginId);
                
                if (requiredPlugin == null) {
                    log.warn("插件 {} 依赖的插件不存在: {}", 
                            plugin.getId(), requiredPluginId);
                    plugin.setStatus(PluginDescriptor.PluginStatus.ERROR);
                    plugin.setErrorMessage("缺少依赖: " + requiredPluginId);
                    continue;
                }
                
                // 检查版本兼容性（简化版，实际应该使用版本比较库）
                if (requiredVersion != null && 
                    !requiredPlugin.getVersion().equals(requiredVersion)) {
                    log.warn("插件 {} 依赖的插件版本不匹配: {} (需要: {}, 实际: {})",
                            plugin.getId(), requiredPluginId, 
                            requiredVersion, requiredPlugin.getVersion());
                }
                
                log.debug("  ✓ {} 依赖 {} v{}", 
                        plugin.getId(), requiredPluginId, requiredPlugin.getVersion());
            }
        }
    }
    
    /**
     * 注册所有插件到NodeTypeRegistry
     */
    private void registerAllPlugins() {
        log.debug("开始注册插件到NodeTypeRegistry...");
        
        for (Map.Entry<String, PluginDescriptor> entry : plugins.entrySet()) {
            String pluginId = entry.getKey();
            PluginDescriptor descriptor = entry.getValue();
            WorkflowNode node = pluginInstances.get(pluginId);
            
            if (node == null) {
                log.warn("插件实例不存在，跳过注册: {}", pluginId);
                continue;
            }
            
            try {
                // 注册到NodeTypeRegistry
                nodeTypeRegistry.registerFromPlugin(descriptor, node);
                
                log.debug("  ✓ {} 已注册到NodeTypeRegistry", pluginId);
                
            } catch (Exception e) {
                log.error("注册插件到NodeTypeRegistry失败: {} - {}", 
                        pluginId, e.getMessage(), e);
                
                descriptor.setStatus(PluginDescriptor.PluginStatus.ERROR);
                descriptor.setErrorMessage("注册失败: " + e.getMessage());
            }
        }
    }
    
    /**
     * 打印插件清单
     */
    private void printPluginSummary() {
        log.info("========================================");
        log.info("插件清单:");
        log.info("========================================");
        
        // 按分类分组
        Map<NodeType.NodeCategory, List<PluginDescriptor>> byCategory = plugins.values().stream()
                .collect(Collectors.groupingBy(PluginDescriptor::getCategory));
        
        for (Map.Entry<NodeType.NodeCategory, List<PluginDescriptor>> entry : byCategory.entrySet()) {
            NodeType.NodeCategory category = entry.getKey();
            List<PluginDescriptor> categoryPlugins = entry.getValue();
            
            log.info("【{}】({} 个)", category.getDescription(), categoryPlugins.size());
            
            for (PluginDescriptor plugin : categoryPlugins) {
                String statusIcon = plugin.getStatus() == PluginDescriptor.PluginStatus.ACTIVE ? "✓" : "✗";
                String sourceIcon = plugin.isInternal() ? "📦" : "🔌";
                
                log.info("  {} {} {} v{} - {} ({})", 
                        statusIcon, sourceIcon,
                        plugin.getDisplayName(), 
                        plugin.getVersion(),
                        plugin.getAuthor().isEmpty() ? "匿名" : plugin.getAuthor(),
                        plugin.getSource());
            }
        }
    }
    
    // ==================== 插件生命周期管理 ====================
    
    /**
     * 启用插件
     */
    public void enablePlugin(String pluginId) {
        PluginDescriptor descriptor = plugins.get(pluginId);
        
        if (descriptor == null) {
            throw new IllegalArgumentException("插件不存在: " + pluginId);
        }
        
        if (descriptor.getEnabled()) {
            log.warn("插件已经是启用状态: {}", pluginId);
            return;
        }
        
        descriptor.setEnabled(true);
        descriptor.setStatus(PluginDescriptor.PluginStatus.ACTIVE);
        descriptor.setUpdatedAt(LocalDateTime.now());
        
        log.info("插件已启用: {}", pluginId);
    }
    
    /**
     * 禁用插件
     */
    public void disablePlugin(String pluginId) {
        PluginDescriptor descriptor = plugins.get(pluginId);
        
        if (descriptor == null) {
            throw new IllegalArgumentException("插件不存在: " + pluginId);
        }
        
        if (!descriptor.getEnabled()) {
            log.warn("插件已经是禁用状态: {}", pluginId);
            return;
        }
        
        descriptor.setEnabled(false);
        descriptor.setStatus(PluginDescriptor.PluginStatus.DISABLED);
        descriptor.setUpdatedAt(LocalDateTime.now());
        
        log.info("插件已禁用: {}", pluginId);
    }
    
    /**
     * 重新加载插件（热加载）
     * 
     * 注意：第一期不实现热加载，需要重启应用
     */
    public void reloadPlugin(String pluginId) {
        log.warn("热加载功能尚未实现，请重启应用以重新加载插件: {}", pluginId);
        throw new UnsupportedOperationException("Hot reload not implemented yet");
    }
    
    // ==================== 查询方法 ====================
    
    /**
     * 获取所有插件
     */
    public List<PluginDescriptor> getAllPlugins() {
        return new ArrayList<>(plugins.values());
    }
    
    /**
     * 获取已启用的插件
     */
    public List<PluginDescriptor> getEnabledPlugins() {
        return plugins.values().stream()
                .filter(PluginDescriptor::isAvailable)
                .collect(Collectors.toList());
    }
    
    /**
     * 获取单个插件
     */
    public PluginDescriptor getPlugin(String pluginId) {
        return plugins.get(pluginId);
    }
    
    /**
     * 检查插件是否存在
     */
    public boolean hasPlugin(String pluginId) {
        return plugins.containsKey(pluginId);
    }
    
    /**
     * 获取插件实例
     */
    public WorkflowNode getPluginInstance(String pluginId) {
        return pluginInstances.get(pluginId);
    }
    
    /**
     * 按分类获取插件
     */
    public List<PluginDescriptor> getPluginsByCategory(NodeType.NodeCategory category) {
        return plugins.values().stream()
                .filter(p -> p.getCategory() == category)
                .filter(PluginDescriptor::isAvailable)
                .collect(Collectors.toList());
    }
    
    /**
     * 获取插件统计信息
     */
    public Map<String, Object> getStatistics() {
        Map<String, Object> stats = new HashMap<>();
        
        stats.put("totalPlugins", plugins.size());
        stats.put("enabledPlugins", getEnabledPlugins().size());
        stats.put("internalPlugins", plugins.values().stream()
                .filter(PluginDescriptor::isInternal).count());
        stats.put("externalPlugins", plugins.values().stream()
                .filter(PluginDescriptor::isExternal).count());
        
        // 按分类统计
        Map<NodeType.NodeCategory, Long> byCategory = plugins.values().stream()
                .collect(Collectors.groupingBy(
                        PluginDescriptor::getCategory, 
                        Collectors.counting()));
        stats.put("byCategory", byCategory);
        
        return stats;
    }
}
