<?php
/**
 * Plugin Manager System
 * Version: 2.0
 * PHP: 7.4+
 */

declare(strict_types=1);

class PluginManager {
    private static ?PluginManager $instance = null;
    private array $plugins = [];
    private array $enabledPlugins = [];
    private string $pluginsPath;
    
    private function __construct() {
        $this->pluginsPath = __DIR__ . '/plugins/';
        $this->loadEnabledPlugins();
        $this->discoverPlugins();
    }
    
    public static function getInstance(): PluginManager {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    /**
     * Discover all plugins
     */
    private function discoverPlugins(): void {
        if (!is_dir($this->pluginsPath)) {
            mkdir($this->pluginsPath, 0755, true);
            return;
        }
        
        $files = glob($this->pluginsPath . '*Plugin.php');
        
        foreach ($files as $file) {
            $className = basename($file, '.php');
            
            if (!class_exists($className)) {
                require_once $file;
            }
            
            if (class_exists($className)) {
                $plugin = new $className();
                
                if ($plugin instanceof BasePlugin) {
                    $this->plugins[$plugin->getName()] = $plugin;
                }
            }
        }
    }
    
    /**
     * Load enabled plugins from database
     */
    private function loadEnabledPlugins(): void {
        $db = Database::getInstance();
        
        // Check if plugins table exists
        $tableExists = $db->query("SHOW TABLES LIKE 'plugins'")->num_rows > 0;
        
        if (!$tableExists) {
            $db->query("CREATE TABLE IF NOT EXISTS `plugins` (
                `name` VARCHAR(100) PRIMARY KEY,
                `enabled` BOOLEAN DEFAULT TRUE,
                `config` JSON NULL,
                `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
        }
        
        $plugins = $db->fetchAll("SELECT name FROM `plugins` WHERE enabled = 1");
        
        foreach ($plugins as $plugin) {
            $this->enabledPlugins[] = $plugin['name'];
        }
    }
    
    /**
     * Enable plugin
     */
    public function enablePlugin(string $name): bool {
        if (!isset($this->plugins[$name])) {
            return false;
        }
        
        $db = Database::getInstance();
        
        // Check if plugin exists in database
        $exists = $db->fetchOne("SELECT name FROM `plugins` WHERE name = ?", [$name]);
        
        if ($exists) {
            $db->update('plugins', ['enabled' => 1], 'name = ?', [$name]);
        } else {
            $db->insert('plugins', ['name' => $name, 'enabled' => 1]);
        }
        
        if (!in_array($name, $this->enabledPlugins)) {
            $this->enabledPlugins[] = $name;
        }
        
        // Call plugin's onEnable method
        $this->plugins[$name]->onEnable();
        
        return true;
    }
    
    /**
     * Disable plugin
     */
    public function disablePlugin(string $name): bool {
        if (!isset($this->plugins[$name])) {
            return false;
        }
        
        $db = Database::getInstance();
        $db->update('plugins', ['enabled' => 0], 'name = ?', [$name]);
        
        $key = array_search($name, $this->enabledPlugins);
        if ($key !== false) {
            unset($this->enabledPlugins[$key]);
        }
        
        // Call plugin's onDisable method
        $this->plugins[$name]->onDisable();
        
        return true;
    }
    
    /**
     * Check if plugin is enabled
     */
    public function isEnabled(string $name): bool {
        return in_array($name, $this->enabledPlugins);
    }
    
    /**
     * Get plugin
     */
    public function getPlugin(string $name): ?BasePlugin {
        return $this->plugins[$name] ?? null;
    }
    
    /**
     * Get all plugins
     */
    public function getAllPlugins(): array {
        return $this->plugins;
    }
    
    /**
     * Get enabled plugins
     */
    public function getEnabledPlugins(): array {
        $enabled = [];
        foreach ($this->enabledPlugins as $name) {
            if (isset($this->plugins[$name])) {
                $enabled[$name] = $this->plugins[$name];
            }
        }
        return $enabled;
    }
    
    /**
     * Trigger event for all enabled plugins
     */
    public function triggerEvent(string $event, array $data = []): void {
        foreach ($this->getEnabledPlugins() as $plugin) {
            $method = 'on' . ucfirst($event);
            
            if (method_exists($plugin, $method)) {
                try {
                    $plugin->$method($data);
                } catch (Exception $e) {
                    $this->logError("Plugin {$plugin->getName()} error in {$method}: " . $e->getMessage());
                }
            }
        }
    }
    
    /**
     * Get plugin config
     */
    public function getPluginConfig(string $name): ?array {
        $db = Database::getInstance();
        $plugin = $db->fetchOne("SELECT config FROM `plugins` WHERE name = ?", [$name]);
        
        if ($plugin && $plugin['config']) {
            return json_decode($plugin['config'], true);
        }
        
        return null;
    }
    
    /**
     * Set plugin config
     */
    public function setPluginConfig(string $name, array $config): bool {
        $db = Database::getInstance();
        return $db->update('plugins', [
            'config' => json_encode($config)
        ], 'name = ?', [$name]);
    }
    
    /**
     * Log errors
     */
    private function logError(string $message): void {
        $logFile = LOGS_PATH . '/plugin_errors_' . date('Y-m-d') . '.log';
        $timestamp = date('Y-m-d H:i:s');
        file_put_contents($logFile, "[{$timestamp}] {$message}\n", FILE_APPEND);
    }
}

/**
 * Base Plugin Class
 */
abstract class BasePlugin {
    protected string $name;
    protected string $version;
    protected string $description;
    protected string $author;
    protected Database $db;
    protected Telegram $telegram;
    
    public function __construct() {
        $this->db = Database::getInstance();
        $this->telegram = Telegram::getInstance();
    }
    
    /**
     * Get plugin name
     */
    public function getName(): string {
        return $this->name;
    }
    
    /**
     * Get plugin version
     */
    public function getVersion(): string {
        return $this->version;
    }
    
    /**
     * Get plugin description
     */
    public function getDescription(): string {
        return $this->description;
    }
    
    /**
     * Get plugin author
     */
    public function getAuthor(): string {
        return $this->author;
    }
    
    /**
     * Called when plugin is enabled
     */
    public function onEnable(): void {
        // Override in child class
    }
    
    /**
     * Called when plugin is disabled
     */
    public function onDisable(): void {
        // Override in child class
    }
    
    /**
     * Get plugin config
     */
    protected function getConfig(): ?array {
        return PluginManager::getInstance()->getPluginConfig($this->name);
    }
    
    /**
     * Set plugin config
     */
    protected function setConfig(array $config): bool {
        return PluginManager::getInstance()->setPluginConfig($this->name, $config);
    }
}
