<?php

declare(strict_types=1);

namespace Flowaxy\Support\Base;

use Flowaxy\Support\Containers\PluginContainer;
use Flowaxy\Support\Isolation\PluginIsolation;
use Flowaxy\Support\Helpers\DatabaseHelper;
use Flowaxy\Support\Helpers\UrlHelper;
use Flowaxy\Support\Helpers\SessionHelper;
use Flowaxy\Support\Helpers\CacheHelper;
use Flowaxy\Core\Contracts\HookManagerInterface;
use Flowaxy\Core\Hooks\HookManager;
use Flowaxy\Core\Routing\Router;
use Flowaxy\Support\Managers\SessionManager;
use Flowaxy\Support\Managers\PluginManager;
use Flowaxy\Support\Facades\Log;
use Flowaxy\Support\Facades\App;
use Flowaxy\Core\Contracts\ContainerInterface;
use PDO;
use Exception;
use ReflectionClass;

use function class_exists;
use function dirname;
use function file_exists;
use function file_get_contents;
use function json_decode;
use const DS;

// Базовий клас для всіх плагінів
abstract class BasePlugin
{
    protected ?array $pluginData = null;
    protected ?PDO $db = null;
    protected array $config = [];
    protected ?PluginContainer $container = null;
    protected string $pluginSlug;
    protected string $pluginDir;

    public function __construct(?PluginContainer $container = null)
    {
        $this->container = $container;

        if ($container !== null) {
            $this->pluginSlug = $container->getPluginSlug();
            $this->pluginDir = $container->getPluginDir();
            $this->config = $container->getConfig();
        } else {
            // Fallback для зворотної сумісності
            $reflection = new ReflectionClass($this);
            $this->pluginDir = dirname($reflection->getFileName()) . DS;
            $this->pluginSlug = $this->getSlug();
        }

        try {
            if (class_exists(DatabaseHelper::class)) {
                $this->db = DatabaseHelper::getConnection();
            }
            $this->loadConfig();
        } catch (Exception $e) {
            Log::Error('BasePlugin constructor error: ' . $e->getMessage());
            $this->db = null;
        }
    }

    // Завантаження конфігурації плагіна
    private function loadConfig(): void
    {
        if (!empty($this->config)) {
            return; // Конфігурація вже завантажена з контейнера
        }

        // Читаем метаданные из Plugin.php
        $pluginSlug = basename(rtrim($this->pluginDir, '/\\'));
        $config = \Flowaxy\Support\Helpers\PluginMetadataHelper::readMetadata($pluginSlug);
        if (!empty($config)) {
            $this->config = $config;
        }
    }

    // Ініціалізація плагіна (викликається при завантаженні)
    public function init(): void
    {
        // Автоматично виконуємо оновлення з папки updates
        $this->runUpdates();

        // Реєструємо хуки та роути
        $this->registerHooks();
        $this->registerRoutes();

        // Перевизначається в дочірніх класах
    }

    // Реєстрація хуків плагіна
    // Перевизначається в дочірніх класах для реєстрації хуків
    // Хуки автоматично реєструються з ізоляцією через PluginContainer
    public function registerHooks(): void
    {
        // Перевизначається в дочірніх класах
    }

    // Реєстрація роутів плагіна
    // Перевизначається в дочірніх класах для реєстрації роутів
    public function registerRoutes(): void
    {
        // Перевизначається в дочірніх класах
    }

    // Активування плагіна
    // Викликається при активації плагіна через адмінку
    // Може використовуватися для створення таблиць, налаштувань тощо
    public function activate(): void
    {
        // Оновлюємо статус в контейнері
        if ($this->container !== null && method_exists($this->container, 'activate')) {
            $this->container->activate();
        }

        // Перевизначається в дочірніх класах
    }

    // Деактивування плагіна
    // Викликається при деактивації плагіна через адмінку
    // Може використовуватися для очищення тимчасових даних
    public function deactivate(): void
    {
        // Оновлюємо статус в контейнері
        if ($this->container !== null && method_exists($this->container, 'deactivate')) {
            $this->container->deactivate();
        }

        // Перевизначається в дочірніх класах
    }

    // Встановлення плагіна (створення таблиць, налаштувань тощо)
    // Викликається один раз при встановленні плагіна
    // Може використовуватися для створення таблиць БД, налаштувань тощо
    public function install(): void
    {
        // Перевизначається в дочірніх класах
    }

    // Видалення плагіна (очищення даних)
    // Викликається при видаленні плагіна
    // Може використовуватися для видалення таблиць БД, налаштувань тощо
    public function uninstall(): void
    {
        // Перевизначається в дочірніх класах
    }

    // Отримання налаштувань плагіна з кешуванням
    public function getSettings(): array
    {
        $slug = $this->getSlug();
        $cacheKey = "plugin_settings_{$slug}";

        return CacheHelper::remember($cacheKey, function () use ($slug) {
            try {
                if (class_exists(\Flowaxy\Infrastructure\Config\PluginSettingsManager::class)) {
                    return \Flowaxy\Infrastructure\Config\PluginSettingsManager::getSettings($slug);
                }
            } catch (Throwable $e) {
                try {
                    Log::Error('BasePlugin getSettings помилка: ' . $e->getMessage());
                } catch (Throwable $logError) {
                    // Ignore logging errors
                }
            }

            return [];
        }, 1800); // Кешуємо на 30 хвилин
    }

    // Збереження налаштування плагіна
    public function setSetting(string $key, $value): bool
    {
        if (empty($key)) {
            return false;
        }

        try {
            if (class_exists(\Flowaxy\Infrastructure\Config\PluginSettingsManager::class)) {
                $result = \Flowaxy\Infrastructure\Config\PluginSettingsManager::setValue($this->getSlug(), $key, $value);

                if ($result) {
                    // Очищаємо кеш налаштувань
                    CacheHelper::forget('plugin_settings_' . $this->getSlug());
                }

                return $result;
            }
        } catch (Throwable $e) {
            try {
                Log::Error('BasePlugin setSetting помилка: ' . $e->getMessage());
            } catch (Throwable $logError) {
                // Ignore logging errors
            }
        }

        return false;
    }

    // Отримання налаштування плагіна
    public function getSetting(string $key, $default = null)
    {
        $settings = $this->getSettings();

        return $settings[$key] ?? $default;
    }

    // Валідація налаштування
    public function validateSetting(string $key, mixed $value): array
    {
        $schema = $this->getSettingsSchema();

        if (!isset($schema[$key])) {
            return []; // Невідоме налаштування - не валідуємо
        }

        $fieldSchema = $schema[$key];
        $errors = [];

        // Перевірка обов'язковості
        if (!empty($fieldSchema['required']) && empty($value) && $value !== '0') {
            $errors[] = "Поле '{$key}' обов'язкове";
        }

        // Перевірка типу
        if (isset($fieldSchema['type'])) {
            $type = $fieldSchema['type'];

            switch ($type) {
                case 'string':
                    if (!\is_string($value)) {
                        $errors[] = "Поле '{$key}' має бути рядком";
                    }
                    break;

                case 'integer':
                case 'int':
                    if (!\is_numeric($value)) {
                        $errors[] = "Поле '{$key}' має бути числом";
                    }
                    break;

                case 'boolean':
                case 'bool':
                    if (!\is_bool($value) && !\in_array($value, ['0', '1', 'true', 'false', 'yes', 'no'], true)) {
                        $errors[] = "Поле '{$key}' має бути булевим значенням";
                    }
                    break;

                case 'email':
                    if (!empty($value) && !filter_var($value, FILTER_VALIDATE_EMAIL)) {
                        $errors[] = "Поле '{$key}' має бути валідною email адресою";
                    }
                    break;

                case 'url':
                    if (!empty($value) && !filter_var($value, FILTER_VALIDATE_URL)) {
                        $errors[] = "Поле '{$key}' має бути валідною URL адресою";
                    }
                    break;
            }
        }

        // Перевірка мінімальної/максимальної довжини
        if (isset($fieldSchema['min_length']) && \strlen((string)$value) < $fieldSchema['min_length']) {
            $errors[] = "Поле '{$key}' має містити мінімум {$fieldSchema['min_length']} символів";
        }

        if (isset($fieldSchema['max_length']) && \strlen((string)$value) > $fieldSchema['max_length']) {
            $errors[] = "Поле '{$key}' має містити максимум {$fieldSchema['max_length']} символів";
        }

        // Перевірка значень з переліку
        if (isset($fieldSchema['enum']) && !in_array($value, $fieldSchema['enum'], true)) {
            $errors[] = "Поле '{$key}' має бути одним з: " . implode(', ', $fieldSchema['enum']);
        }

        // Кастомна валідація
        if (isset($fieldSchema['validate']) && is_callable($fieldSchema['validate'])) {
            $customError = $fieldSchema['validate']($value);
            if (!empty($customError)) {
                $errors[] = $customError;
            }
        }

        return $errors;
    }

    // Отримання схеми налаштувань плагіна
    // Перевизначається в дочірніх класах для визначення структури налаштувань
    public function getSettingsSchema(): array
    {
        return [];
    }

    // Встановлення налаштування з валідацією
    public function setSettingWithValidation(string $key, mixed $value): array
    {
        $errors = $this->validateSetting($key, $value);

        if (empty($errors)) {
            $this->setSetting($key, $value);
        }

        return $errors;
    }

    // Масове встановлення налаштувань з валідацією
    public function setSettingsWithValidation(array $settings): array
    {
        $allErrors = [];

        foreach ($settings as $key => $value) {
            $errors = $this->validateSetting($key, $value);

            if (!empty($errors)) {
                $allErrors[$key] = $errors;
            } else {
                $this->setSetting($key, $value);
            }
        }

        return $allErrors;
    }

    // Отримання слагу плагіна
    public function getSlug(): string
    {
        if (isset($this->pluginSlug)) {
            return $this->pluginSlug;
        }

        return $this->config['slug'] ?? strtolower(str_replace('\\', '_', get_class($this)));
    }

    // Отримання імені плагіна
    public function getName(): string
    {
        return $this->config['name'] ?? get_class($this);
    }

    // Отримання версії плагіна
    public function getVersion(): string
    {
        return $this->config['version'] ?? '1.0.0';
    }

    // Отримання опису плагіна
    public function getDescription(): string
    {
        return $this->config['description'] ?? '';
    }

    // Отримання автора плагіна
    public function getAuthor(): string
    {
        return $this->config['author'] ?? '';
    }

    // Отримання URL плагіна
    public function getPluginUrl(): string
    {
        $pluginDir = basename(dirname(new ReflectionClass($this)->getFileName()));
        // Використовуємо UrlHelper для отримання актуального URL з правильним протоколом
        if (class_exists(UrlHelper::class)) {
            return UrlHelper::site("/plugins/{$pluginDir}/");
        }
        // Fallback на константу, якщо UrlHelper не доступний
        $siteUrl = \defined('SITE_URL') ? SITE_URL : '';

        return "{$siteUrl}/plugins/{$pluginDir}/";
    }

    // Отримання шляху до плагіна
    public function getPluginPath(string $filePath = ''): string
    {
        if ($this->container !== null && method_exists($this->container, 'getPluginPath')) {
            return $this->container->getPluginPath($filePath);
        }

        // Fallback для зворотної сумісності
        $basePath = dirname((new ReflectionClass($this))->getFileName()) . DS;

        if (empty($filePath)) {
            return $basePath;
        }

        return $basePath . ltrim($filePath, '/\\');
    }

    // Отримання контейнера плагіна
    public function getContainer()
    {
        return $this->container;
    }

    // Реєстрація хука з ізоляцією
    // Автоматично реєструє хук через HookManager з підтримкою ізоляції
    protected function registerHook(string $hookName, callable $callback, int $priority = 10, bool $once = false): void
    {
        $hookManager = null;

        // Основний шлях: глобальний hooks() (якщо визначений)
        if (\function_exists('hooks')) {
            // @phpstan-ignore-next-line - hooks() may be defined globally by bootstrap
            $hookManager = \hooks();
        }

        // Fallback: беремо HookManager з DI контейнера
        if (!($hookManager instanceof HookManagerInterface) && class_exists(App::class)) {
            try {
                $container = App::container();
                if ($container && $container->has(HookManagerInterface::class)) {
                    $hookManager = $container->make(HookManagerInterface::class);
                }
            } catch (\Throwable $e) {
                // Ignore container errors, fallback below
            }
        }

        // Fallback: створюємо HookManager напрямую (краще ніж "тихо" не реєструвати хук)
        if (!($hookManager instanceof HookManagerInterface) && class_exists(HookManager::class)) {
            $hookManager = new HookManager();
        }

        // Останній fallback: legacy addHook (якщо доступний)
        if (!($hookManager instanceof HookManagerInterface)) {
            if (\function_exists('addHook')) {
                // @phpstan-ignore-next-line
                \addHook($hookName, $callback, $priority);
            }
            return;
        }

        $pluginSlug = $this->getSlug();

        // Використовуємо метод з ізоляцією, якщо доступний
        if (method_exists($hookManager, 'onFromPlugin')) {
            $hookManager->onFromPlugin($hookName, $callback, $pluginSlug, $this->container, $priority, $once);
        } else {
            // Fallback на стандартний метод
            $hookManager->on($hookName, $callback, $priority, $once);
        }
    }

    // Реєстрація фільтра з ізоляцією
    // Автоматично реєструє фільтр через HookManager з підтримкою ізоляції
    protected function registerFilter(string $hookName, callable $callback, int $priority = 10): void
    {
        $hookManager = null;

        if (\function_exists('hooks')) {
            // @phpstan-ignore-next-line - hooks() may be defined globally by bootstrap
            $hookManager = \hooks();
        }

        if (!($hookManager instanceof HookManagerInterface) && class_exists(App::class)) {
            try {
                $container = App::container();
                if ($container && $container->has(HookManagerInterface::class)) {
                    $hookManager = $container->make(HookManagerInterface::class);
                }
            } catch (\Throwable $e) {
                // Ignore container errors, fallback below
            }
        }

        if (!($hookManager instanceof HookManagerInterface) && class_exists(HookManager::class)) {
            $hookManager = new HookManager();
        }

        if (!($hookManager instanceof HookManagerInterface)) {
            if (\function_exists('addHook')) {
                // @phpstan-ignore-next-line
                \addHook($hookName, $callback, $priority);
            }
            return;
        }

        $pluginSlug = $this->getSlug();

        // Використовуємо метод з ізоляцією, якщо доступний
        if (method_exists($hookManager, 'filterFromPlugin')) {
            $hookManager->filterFromPlugin($hookName, $callback, $pluginSlug, $this->container, $priority);
        } else {
            // Fallback на стандартний метод
            $hookManager->filter($hookName, $callback, $priority);
        }
    }

    // Реєстрація роута плагіна
    // Додає роут до глобального Router з префіксом плагіна
    protected function registerRoute($methods, string $path, $handler, array $options = []): void
    {
        // Додаємо префікс плагіна до шляху
        $pluginSlug = $this->getSlug();
        $prefixedPath = '/plugins/' . $pluginSlug . '/' . ltrim($path, '/');

        if (!class_exists('Router')) {
            return;
        }

        // Створюємо або отримуємо екземпляр Router
        static $router = null;
        if ($router === null) {
            // Спробуємо отримати Router з контейнера або створити новий
            if (class_exists(App::class)) {
                try {
                    /** @var ContainerInterface|null $container */
                    $container = App::container();
                    if ($container?->has('Router')) {
                        $router = $container->make('Router');
                    }
                } catch (\Exception $e) {
                    // Fallback нижче
                }
            }

            if ($router === null) {
                $router = new Router();
            }
        }

        // Додаємо роут
        $router->add($methods, $prefixedPath, $handler, $options);
    }

    // Підключення CSS файлу плагіна
    // Використовує хук theme_head для підключення стилів
    public function enqueueStyle(string $handle, string $file, array $dependencies = []): void
    {
        $url = $this->getPluginUrl() . $file;

        $this->registerHook('theme_head', function () use ($url, $handle) {
            echo "<link rel='stylesheet' id='{$handle}-css' href='{$url}' type='text/css' media='all' />\n";
        });
    }

    // Підключення JS файлу плагіна
    // Використовує хук theme_footer для підключення скриптів
    public function enqueueScript(string $handle, string $file, array $dependencies = [], bool $inFooter = true): void
    {
        $url = $this->getPluginUrl() . $file;

        $hookName = $inFooter ? 'theme_footer' : 'theme_head';

        $this->registerHook($hookName, function () use ($url, $handle) {
            echo "<script id='{$handle}-js' src='{$url}'></script>\n";
        });
    }

    // Додавання пункту меню в адмінку
    public function addAdminMenu(string $title, string $capability, string $menuSlug, callable $callback, string $icon = ''): void
    {
        $this->registerHook('admin_menu', function () use ($title, $menuSlug, $capability, $callback, $icon) {});
    }

    // Локалізація скрипту (аналог wp_localize_script)
    protected function localizeScript(string $handle, string $objectName, array $data): void
    {
        // Додаємо JavaScript змінну
        // $handle не використовується в closure, але зберігається для майбутнього використання
        $this->registerHook('theme_footer', function () use ($objectName, $data) {
            echo "<script>var {$objectName} = " . json_encode($data, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR) . ";</script>\n";
        });
    }

    // Створення nonce (аналог wp_create_nonce)
    protected function createNonce(string $action): string
    {
        $session = SessionHelper::getManager();
        if ($session !== null) {
            $session->setPrefix('plugin');
        } else {
            // Fallback: используем SessionManager напрямую
            $session = SessionManager::getInstance();
            $session->setPrefix('plugin');
        }
        $nonces = $session->get('nonces', []);

        $nonce = bin2hex(random_bytes(32));
        $nonces[$action] = [
            'nonce' => $nonce,
            'expires' => time() + 3600, // 1 година
        ];

        $session->set('nonces', $nonces);

        return $nonce;
    }

    // Перевірка nonce (аналог wp_verify_nonce)
    protected function verifyNonce(?string $nonce, string $action): bool
    {
        if (empty($nonce)) {
            return false;
        }

        $session = SessionHelper::getManager();
        if ($session !== null) {
            $session->setPrefix('plugin');
        } else {
            // Fallback: используем SessionManager напрямую
            $session = SessionManager::getInstance();
            $session->setPrefix('plugin');
        }
        $nonces = $session->get('nonces', []);

        if (! isset($nonces[$action])) {
            return false;
        }

        $stored = $nonces[$action];

        // Перевіряємо термін дії
        if (isset($stored['expires']) && $stored['expires'] < time()) {
            unset($nonces[$action]);
            $session->set('nonces', $nonces);

            return false;
        }

        // Перевіряємо nonce
        if (isset($stored['nonce']) && hash_equals($stored['nonce'], $nonce)) {
            // Видаляємо використаний nonce (одноразове використання)
            unset($nonces[$action]);
            $session->set('nonces', $nonces);

            return true;
        }

        return false;
    }

    // Відправка JSON відповіді
    private function sendJsonResponse(bool $success, $data): void
    {
        if (! headers_sent()) {
            header('Content-Type: application/json; charset=UTF-8');
        }
        echo json_encode(['success' => $success, 'data' => $data], JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);
        exit;
    }

    // Відправка JSON успіху (аналог wp_send_json_success)
    protected function sendJsonSuccess($data): void
    {
        $this->sendJsonResponse(true, $data);
    }

    // Відправка JSON помилки (аналог wp_send_json_error)
    protected function sendJsonError($data): void
    {
        $this->sendJsonResponse(false, $data);
    }

    // Логування дій плагіна
    public function log(string $message, string $level = 'info'): void
    {
        $logMessage = '[' . date('Y-m-d H:i:s') . "] [{$this->getName()}] [{$level}] {$message}";
        Log::Error($logMessage);
    }

    // Перевірка залежностей плагіна
    public function checkDependencies(): bool
    {
        if (! isset($this->config['dependencies']) || ! \is_array($this->config['dependencies'])) {
            return true;
        }

        try {
            if (! \function_exists('pluginManager')) {
                return false;
            }

            $pluginManagerFunc = 'pluginManager';
            /** @var PluginManager|null $pluginManager */
            $pluginManager = \function_exists($pluginManagerFunc) ? $pluginManagerFunc() : null;
            if ($pluginManager === null) {
                // Fallback: используем PluginManager напрямую
                $pluginManager = PluginManager::getInstance();
            }
            foreach ($this->config['dependencies'] as $dependency) {
                if (! \is_string($dependency)) {
                    continue;
                }

                // Перевіряємо формат залежності (може бути просто slug або масив з версією)
                $depSlug = \is_array($dependency) ? ($dependency['slug'] ?? '') : $dependency;
                $depVersion = \is_array($dependency) ? ($dependency['version'] ?? null) : null;

                if (empty($depSlug)) {
                    continue;
                }

                // Перевіряємо, чи плагін встановлений
                if (! $pluginManager->isPluginInstalled($depSlug)) {
                    return false;
                }

                // Перевіряємо, чи плагін активний
                if (! $pluginManager->isPluginActive($depSlug)) {
                    return false;
                }

                // Перевіряємо версію, якщо вказана
                if ($depVersion !== null) {
                    $installedPlugin = $pluginManager->getPlugin($depSlug);
                    if ($installedPlugin && version_compare($installedPlugin->getVersion(), $depVersion, '<')) {
                        return false;
                    }
                }
            }
        } catch (\Exception $e) {
            Log::Error('Помилка перевірки залежностей плагіна: ' . $e->getMessage());

            return false;
        }

        return true;
    }

    // Отримання списку залежностей
    public function getDependencies(): array
    {
        return $this->config['dependencies'] ?? [];
    }

    // Отримання помилок залежностей
    public function getDependencyErrors(): array
    {
        $errors = [];

        if (! isset($this->config['dependencies']) || ! \is_array($this->config['dependencies'])) {
            return $errors;
        }

        if (! \function_exists('pluginManager')) {
            return ['general' => 'PluginManager недоступний'];
        }

        try {
            $pluginManagerFunc = 'pluginManager';
            /** @var PluginManager|null $pluginManager */
            $pluginManager = \function_exists($pluginManagerFunc) ? $pluginManagerFunc() : null;
            if ($pluginManager === null) {
                // Fallback: используем PluginManager напрямую
                $pluginManager = PluginManager::getInstance();
            }

            foreach ($this->config['dependencies'] as $dependency) {
                $depSlug = \is_array($dependency) ? ($dependency['slug'] ?? '') : $dependency;
                $depVersion = \is_array($dependency) ? ($dependency['version'] ?? null) : null;

                if (empty($depSlug)) {
                    continue;
                }

                if (! $pluginManager->isPluginInstalled($depSlug)) {
                    $errors[$depSlug] = "Плагін '{$depSlug}' не встановлений";
                    continue;
                }

                if (! $pluginManager->isPluginActive($depSlug)) {
                    $errors[$depSlug] = "Плагін '{$depSlug}' не активований";
                    continue;
                }

                if ($depVersion !== null) {
                    $installedPlugin = $pluginManager->getPlugin($depSlug);
                    if ($installedPlugin && version_compare($installedPlugin->getVersion(), $depVersion, '<')) {
                        $errors[$depSlug] = "Плагін '{$depSlug}' потребує версію {$depVersion} або вищу";
                    }
                }
            }
        } catch (\Exception $e) {
            $errors['general'] = 'Помилка перевірки залежностей: ' . $e->getMessage();
        }

        return $errors;
    }

    // Отримання конфігурації плагіна
    public function getConfig(): array
    {
        return $this->config ?? [];
    }

    // Автоматично виконує файли-оновлення з папки updates
    // Знаходить всі PHP файли в папці updates плагіна та виконує їх,
    // якщо вони ще не були виконані. Файли повинні повертати callable,
    // який приймає PDO як параметр.
    protected function runUpdates(): void
    {
        if (!$this->db) {
            return;
        }

        $pluginDir = $this->getPluginPath();
        $updatesDir = $pluginDir . 'updates';

        if (!is_dir($updatesDir)) {
            return;
        }

        // Знаходимо всі PHP файли в папці updates
        $updateFiles = glob("{$updatesDir}/*.php");

        if (empty($updateFiles)) {
            return;
        }

        // Сортуємо файли за назвою (версії)
        sort($updateFiles);

        foreach ($updateFiles as $updateFile) {
            $updateName = basename($updateFile, '.php');
            $pluginSlug = $this->getSlug();
            $migrationName = "{$pluginSlug}_{$updateName}";

            // Перевіряємо, чи вже виконано це оновлення
            if ($this->isUpdateExecuted($migrationName)) {
                continue;
            }

            try {
                // Завантажуємо файл оновлення (він повинен повертати callable)
                $update = require $updateFile;

                if (is_callable($update)) {
                    $update($this->db);

                    // Позначаємо оновлення як виконане
                    $this->markUpdateAsExecuted($migrationName);

                    if (function_exists('logger')) {
                        Log::Info("Plugin {$pluginSlug}: Update executed", ['update' => $updateName]);
                    }
                }
            } catch (Exception $e) {
                if (function_exists('logger')) {
                    Log::Error("Plugin {$pluginSlug}: Error executing update", [
                        'update' => $updateName,
                        'exception' => $e
                    ]);
                }
            }
        }
    }

    // Перевірити, чи виконано оновлення
    private function isUpdateExecuted(string $migrationName): bool
    {
        if (!$this->db) {
            return false;
        }

        try {
            // Перевіряємо через таблицю migrations
            $stmt = $this->db->prepare("SELECT COUNT(*) FROM migrations WHERE migration = ?");
            $stmt->execute([$migrationName]);
            return (int)$stmt->fetchColumn() > 0;
        } catch (\Exception $e) {
            // Якщо таблиці migrations немає, повертаємо false
            return false;
        }
    }

    // Позначити оновлення як виконане
    private function markUpdateAsExecuted(string $migrationName): void
    {
        if (!$this->db) {
            return;
        }

        try {
            // Створюємо таблицю migrations, якщо її немає (використовуємо той самий формат, що й MigrationRunner)
            $sql = 'CREATE TABLE IF NOT EXISTS `migrations` (
                `id` INT AUTO_INCREMENT PRIMARY KEY,
                `migration` VARCHAR(255) NOT NULL UNIQUE,
                `executed_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                INDEX `idx_migration` (`migration`)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci';
            // @phpstan-ignore-next-line - это метод PDO, а не системная команда exec()
            $this->db->exec($sql);

            // Додаємо запис про виконане оновлення
            $stmt = $this->db->prepare('INSERT IGNORE INTO migrations (migration) VALUES (?)');
            $stmt->execute([$migrationName]);
        } catch (\Exception $e) {
            // Ігноруємо помилки
        }
    }
}
