package com.openosrs.client.plugins;

import com.openosrs.client.api.AgentAPI;
import com.openosrs.client.core.ClientCore;
import com.openosrs.client.core.EventSystem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import java.util.Set;
import java.util.HashSet;

/**
 * Plugin system for extending agent capabilities.
 */
public class PluginManager {
    private static final Logger logger = LoggerFactory.getLogger(PluginManager.class);
    
    private final AgentAPI agentAPI;
    private final ClientCore clientCore;
    private final EventSystem eventSystem;
    private final Map<String, Plugin> plugins;
    private final Map<String, PluginInfo> pluginInfo;
    private final Set<String> enabledPlugins;
    
    public PluginManager(AgentAPI agentAPI, ClientCore clientCore) {
        this.agentAPI = agentAPI;
        this.clientCore = clientCore;
        this.eventSystem = clientCore.getEventSystem();
        this.plugins = new ConcurrentHashMap<>();
        this.pluginInfo = new ConcurrentHashMap<>();
        this.enabledPlugins = new HashSet<>();
        
        logger.info("Plugin manager initialized");
    }
    
    /**
     * Register a plugin.
     */
    public void registerPlugin(Plugin plugin) {
        String name = plugin.getMetadata().getName();
        
        if (plugins.containsKey(name)) {
            throw new IllegalArgumentException("Plugin already registered: " + name);
        }
        
        plugins.put(name, plugin);
        pluginInfo.put(name, new PluginInfo(
            plugin.getMetadata(),
            PluginState.REGISTERED,
            false,
            null
        ));
        
        logger.info("Registered plugin: {}", name);
    }
    
    /**
     * Enable a plugin.
     */
    public boolean enablePlugin(String name) {
        Plugin plugin = plugins.get(name);
        if (plugin == null) {
            logger.warn("Plugin not found: {}", name);
            return false;
        }
        
        if (enabledPlugins.contains(name)) {
            logger.debug("Plugin already enabled: {}", name);
            return true;
        }
        
        try {
            PluginContext context = new PluginContext(agentAPI, clientCore, eventSystem);
            plugin.onEnable(context);
            
            enabledPlugins.add(name);
            updatePluginInfo(name, PluginState.ENABLED, true, null);
            
            logger.info("Enabled plugin: {}", name);
            return true;
            
        } catch (Exception e) {
            logger.error("Failed to enable plugin: {}", name, e);
            updatePluginInfo(name, PluginState.ERROR, false, e.getMessage());
            return false;
        }
    }
    
    /**
     * Disable a plugin.
     */
    public boolean disablePlugin(String name) {
        Plugin plugin = plugins.get(name);
        if (plugin == null) {
            logger.warn("Plugin not found: {}", name);
            return false;
        }
        
        if (!enabledPlugins.contains(name)) {
            logger.debug("Plugin already disabled: {}", name);
            return true;
        }
        
        try {
            plugin.onDisable();
            
            enabledPlugins.remove(name);
            updatePluginInfo(name, PluginState.DISABLED, false, null);
            
            logger.info("Disabled plugin: {}", name);
            return true;
            
        } catch (Exception e) {
            logger.error("Failed to disable plugin: {}", name, e);
            updatePluginInfo(name, PluginState.ERROR, false, e.getMessage());
            return false;
        }
    }
    
    /**
     * Get plugin information.
     */
    public PluginInfo getPluginInfo(String name) {
        return pluginInfo.get(name);
    }
    
    /**
     * Get all plugin information.
     */
    public Map<String, PluginInfo> getAllPlugins() {
        return new ConcurrentHashMap<>(pluginInfo);
    }
    
    /**
     * Get enabled plugins.
     */
    public Set<String> getEnabledPlugins() {
        return new HashSet<>(enabledPlugins);
    }
    
    /**
     * Check if a plugin is enabled.
     */
    public boolean isPluginEnabled(String name) {
        return enabledPlugins.contains(name);
    }
    
    /**
     * Disable all plugins.
     */
    public void disableAllPlugins() {
        logger.info("Disabling all plugins");
        
        for (String name : new ArrayList<>(enabledPlugins)) {
            disablePlugin(name);
        }
    }
    
    /**
     * Notify plugins of events.
     */
    public void notifyEvent(String eventType, Object eventData) {
        for (String name : enabledPlugins) {
            try {
                Plugin plugin = plugins.get(name);
                if (plugin != null) {
                    plugin.onEvent(eventType, eventData);
                }
            } catch (Exception e) {
                logger.error("Plugin {} failed to handle event {}", name, eventType, e);
            }
        }
    }
    
    private void updatePluginInfo(String name, PluginState state, boolean enabled, String error) {
        PluginInfo current = pluginInfo.get(name);
        if (current != null) {
            pluginInfo.put(name, new PluginInfo(
                current.getMetadata(),
                state,
                enabled,
                error
            ));
        }
    }
}