<?php

declare(strict_types=1);

class PluginManager
{
    private static array $plugins = [];
    private static array $instances = [];

    

    private static function load(string $slug): ?PluginInterface
    {
        if (array_key_exists($slug, self::$instances)) {
            return self::$instances[$slug];
        }
        if (!preg_match('/^[a-z0-9_-]+$/i', $slug)) {
            return self::$instances[$slug] = null;
        }
        $path = APP_ROOT . '/plugins/' . $slug . '/plugin.php';
        if (!file_exists($path)) {
            return self::$instances[$slug] = null;
        }
        $plugin = require $path;
        return self::$instances[$slug] = ($plugin instanceof PluginInterface) ? $plugin : null;
    }

    public static function bootAll(): void
    {
        $rows = Database::fetchAll('SELECT slug FROM plugins WHERE is_active = 1');
        foreach ($rows as $row) {
             
             
            if (!LicenseGuard::isAllowed('plugin', (string) $row['slug'])) {
                continue;
            }
            self::boot($row['slug']);
        }
    }

    public static function boot(string $slug): void
    {
        try {
            $plugin = self::load($slug);
            if ($plugin !== null && !isset(self::$plugins[$slug])) {
                self::$plugins[$slug] = $plugin;
                $plugin->boot();
            }
        } catch (\Throwable $e) {
            error_log("PluginManager: failed to boot plugin '{$slug}': " . $e->getMessage());
        }
    }

    public static function activate(string $slug): bool
    {
        $plugin = self::load($slug);
        if ($plugin === null) {
            return false;
        }

         
         
        try {
            $plugin->activate();
        } catch (\Throwable $e) {
            error_log("PluginManager: activate() failed for '{$slug}': " . $e->getMessage());
            return false;
        }

        $existing = Database::fetchOne('SELECT id FROM plugins WHERE slug = ?', [$slug]);
        if ($existing) {
            Database::update('plugins', ['is_active' => 1], 'slug = ?', [$slug]);
        } else {
            Database::insert('plugins', ['slug' => $slug, 'is_active' => 1]);
        }

        self::$plugins[$slug] = $plugin;

        $iconSrc = APP_ROOT . '/plugins/' . $slug . '/icon.svg';
        if (file_exists($iconSrc)) {
            $iconDir = APP_ROOT . '/public/uploads/plugins';
            if (!is_dir($iconDir)) mkdir($iconDir, 0755, true);
            @copy($iconSrc, $iconDir . '/' . $slug . '.svg');
        }

        return true;
    }

    public static function deactivate(string $slug): bool
    {
        Database::update('plugins', ['is_active' => 0], 'slug = ?', [$slug]);

        if (isset(self::$plugins[$slug])) {
            self::$plugins[$slug]->deactivate();
            unset(self::$plugins[$slug]);
        }

        return true;
    }

    public static function isActive(string $slug): bool
    {
        return isset(self::$plugins[$slug]);
    }

    public static function getAll(): array
    {
        $plugins = [];
        $dir = APP_ROOT . '/plugins';
        if (!is_dir($dir)) {
            return $plugins;
        }

        $dirs = scandir($dir);
        foreach ($dirs as $slug) {
            if ($slug === '.' || $slug === '..') {
                continue;
            }

            $jsonPath = $dir . '/' . $slug . '/plugin.json';
            if (!file_exists($jsonPath)) {
                continue;
            }

            $info = json_decode(file_get_contents($jsonPath), true) ?? [];
            $info['slug'] = $slug;

            $row = Database::fetchOne('SELECT is_active FROM plugins WHERE slug = ?', [$slug]);
            $info['is_active'] = $row ? (bool) $row['is_active'] : false;

            $plugins[] = $info;
        }

        return $plugins;
    }

    public static function getPlugin(string $slug): ?PluginInterface
    {
        return self::$plugins[$slug] ?? null;
    }
}
