<?php

/**
 * Хелпер для роботи з безпекою
 * Обгортка над Security класом
 * Оптимізовано для PHP 8.4+
 *
 * @package Flowaxy\Support\Helpers
 * @version 1.0.0 Alpha prerelease
 */

declare(strict_types=1);

namespace Flowaxy\Support\Helpers;

use Flowaxy\Infrastructure\Security\Security;
use Flowaxy\Infrastructure\Security\Session;
use Flowaxy\Support\Facades\Hash as SecurityHash;
use Flowaxy\Infrastructure\Security\Encryption;
use Flowaxy\Infrastructure\Filesystem\Json;
use Flowaxy\Infrastructure\Logging\Logger;
use Flowaxy\Infrastructure\Persistence\Repositories\AdminUserRepository;
use Flowaxy\Contracts\Domain\User\AdminUserRepositoryInterface;
use Flowaxy\Domain\User\Services\AuthenticateAdminUserService;
use Flowaxy\Domain\User\Services\AuthenticationResult;
use Flowaxy\Domain\User\Services\LogoutUserService;
use Flowaxy\Infrastructure\Config\SystemConfig;
use Flowaxy\Interface\Http\Response;
use Flowaxy\Interface\Http\AjaxHandler;
use Flowaxy\Support\Facades\Session as SessionFacade;
use Flowaxy\Support\Facades\App;
use Flowaxy\Support\Facades\Log;
use Flowaxy\Support\Helpers\UrlHelper;
use Flowaxy\Support\Helpers\SessionHelper;
use Flowaxy\Support\Helpers\ClassLoaderHelper;
use Flowaxy\Core\System\PathResolver;

use const DIRECTORY_SEPARATOR as DS;

// Імпорт вбудованих функцій PHP для оптимізації компілятора та чистого коду
use function array_diff;
use function array_shift;
use function array_slice;
use function base64_decode;
use function base64_encode;
use function bin2hex;
use function class_exists;
use function escapeshellarg;
use function explode;
use function file_get_contents;
use function get_declared_classes;
use function implode;
use function shell_exec;
use function strpos;
use function date;
use function debug_backtrace;
use function defined;
use function dirname;
use function file_exists;
use function filter_var;
use function function_exists;
use function is_readable;
use function str_replace;
use function header;
use function http_response_code;
use function interface_exists;
use function is_array;
use function is_bool;
use function is_numeric;
use function is_object;
use function is_string;
use function json_encode;
use function ob_end_clean;
use function ob_get_level;
use function password_hash;
use function password_verify;
use function random_bytes;
use function session_status;
use function spl_autoload_call;
use function str_ends_with;
use function strtotime;
use function time;
use function trim;

/**
 * Хелпер для роботи з безпекою
 */
final class SecurityHelper
{
    private const int DEFAULT_SESSION_LIFETIME = 7200; // 2 години

    /**
     * Генерація CSRF токена
     *
     * @return string
     */
    public static function csrfToken(): string
    {
        if (!class_exists(Security::class)) {
            return '';
        }

        // Переконуємося, що Session ініціалізовано
        if (session_status() !== PHP_SESSION_ACTIVE && class_exists(Session::class)) {
            Session::start();
        }

        return Security::csrfToken();
    }

    /**
     * Перевірка CSRF токена
     *
     * @param string|null $token Токен для перевірки
     * @return bool
     */
    public static function verifyCsrfToken(?string $token = null): bool
    {
        if (!class_exists(Security::class)) {
            return false;
        }

        // Переконуємося, що Session ініціалізовано
        if (session_status() !== PHP_SESSION_ACTIVE && class_exists(Session::class)) {
            Session::start();
        }

        return Security::verifyCsrfToken($token);
    }

    /**
     * Генерація CSRF поля для форми
     *
     * @return string
     */
    public static function csrfField(): string
    {
        if (!class_exists(Security::class)) {
            return '';
        }

        // Переконуємося, що Session ініціалізовано
        if (session_status() !== PHP_SESSION_ACTIVE && class_exists(Session::class)) {
            Session::start();
        }

        return Security::csrfField();
    }

    /**
     * Авторизация пользователя админки
     * Обертка над сервисом аутентификации
     *
     * @param string $username
     * @param string $password
     * @return array{success: bool, error?: string, user?: array}
     */
    public static function authenticateAdminUser(string $username, string $password): array
    {
        // Логируем начало авторизации
        try {
            Log::Debug('authenticateAdminUser: Starting authentication', [
                'username' => $username,
                'session_status' => session_status(),
                'session_id' => session_id() ?: 'none',
                'Session::class_exists' => class_exists(Session::class),
                'Session::isStarted()' => class_exists(Session::class) ? Session::isStarted() : 'N/A'
            ]);
        } catch (\Throwable $e) {
            // Игнорируем ошибки логирования
        }

        $serviceClass = AuthenticateAdminUserService::class;
        $resultClass = AuthenticationResult::class;

        // Загружаем Hash facade и его зависимости перед загрузкой AuthenticateAdminUserService
        // AuthenticateAdminUserService использует Hash::check(), поэтому Hash должен быть загружен
        if (!class_exists('Flowaxy\Support\Facades\Hash')) {
            // Сначала загружаем зависимости базового класса Facade
            // ContainerInterface нужен для Facade
            if (!interface_exists('Flowaxy\Core\Contracts\ContainerInterface')) {
                if (class_exists(ClassLoaderHelper::class)) {
                    ClassLoaderHelper::ensureLoaded('Flowaxy\Core\Contracts\ContainerInterface');
                } else if (function_exists('spl_autoload_call')) {
                    spl_autoload_call('Flowaxy\Core\Contracts\ContainerInterface');
                }
            }

            // Container нужен для Facade
            if (!class_exists('Flowaxy\Core\System\Container\Container')) {
                if (class_exists(ClassLoaderHelper::class)) {
                    ClassLoaderHelper::ensureLoaded('Flowaxy\Core\System\Container\Container');
                } else if (function_exists('spl_autoload_call')) {
                    spl_autoload_call('Flowaxy\Core\System\Container\Container');
                }
            }

            // Загружаем базовый класс Facade
            if (!class_exists('Flowaxy\Support\Facades\Facade')) {
                if (class_exists(ClassLoaderHelper::class)) {
                    ClassLoaderHelper::ensureLoaded('Flowaxy\Support\Facades\Facade');
                } else if (class_exists(PathResolver::class)) {
                    try {
                        $flowaxyDir = PathResolver::flowaxy();
                        $facadeFile = $flowaxyDir . DS . 'Support' . DS . 'Facades' . DS . 'Facade.php';
                        if (file_exists($facadeFile) && is_readable($facadeFile)) {
                            require_once $facadeFile;
                        }
                    } catch (\Throwable $e) {
                        // Игнорируем ошибки загрузки
                    }
                }
            }

            // Загружаем HashInterface (интерфейс для Hash)
            if (!interface_exists('Flowaxy\Contracts\Security\HashInterface')) {
                if (class_exists(ClassLoaderHelper::class)) {
                    ClassLoaderHelper::ensureLoaded('Flowaxy\Contracts\Security\HashInterface');
                } else if (function_exists('spl_autoload_call')) {
                    spl_autoload_call('Flowaxy\Contracts\Security\HashInterface');
                }
            }

            // Загружаем HashInstance (зависимость Hash facade)
            if (!class_exists('Flowaxy\Infrastructure\Security\Hash')) {
                if (class_exists(ClassLoaderHelper::class)) {
                    ClassLoaderHelper::ensureLoaded('Flowaxy\Infrastructure\Security\Hash');
                } else if (function_exists('spl_autoload_call')) {
                    spl_autoload_call('Flowaxy\Infrastructure\Security\Hash');
                }
            }

            // Загружаем Hash facade
            if (class_exists(ClassLoaderHelper::class)) {
                ClassLoaderHelper::ensureLoaded('Flowaxy\Support\Facades\Hash');
            } else if (class_exists(PathResolver::class)) {
                try {
                    $flowaxyDir = PathResolver::flowaxy();
                    $hashFacadeFile = $flowaxyDir . DS . 'Support' . DS . 'Facades' . DS . 'Hash.php';
                    if (file_exists($hashFacadeFile) && is_readable($hashFacadeFile)) {
                        require_once $hashFacadeFile;
                    }
                } catch (\Throwable $e) {
                    // Игнорируем ошибки загрузки
                }
            } else if (function_exists('spl_autoload_call')) {
                spl_autoload_call('Flowaxy\Support\Facades\Hash');
            }
        }

        // Загружаем AuthenticationResult через ClassLoaderHelper (согласно документации)
        if (!class_exists($resultClass, false)) {
            if (class_exists(ClassLoaderHelper::class)) {
                ClassLoaderHelper::ensureLoaded($resultClass);
            } else {
                // Fallback: пробуем через PathResolver
                if (class_exists(PathResolver::class)) {
                    try {
                        $flowaxyDir = PathResolver::flowaxy();
                        $relativePath = 'Domain' . DS . 'User' . DS . 'Services' . DS . 'AuthenticationResult.php';
                        $filePath = $flowaxyDir . DS . $relativePath;

                        if (file_exists($filePath) && is_readable($filePath)) {
                            require_once $filePath;
                        }
                    } catch (\Throwable $e) {
                        // Игнорируем ошибки загрузки
                    }
                }
                // Пробуем через autoloader
                if (function_exists('spl_autoload_call')) {
                    spl_autoload_call($resultClass);
                }
            }
        }

        // Загружаем класс через ClassLoaderHelper (согласно документации)
        if (!class_exists($serviceClass, false)) {
            // Сначала пробуем через ClassLoaderHelper
            if (class_exists(ClassLoaderHelper::class)) {
                if (!ClassLoaderHelper::ensureLoaded($serviceClass)) {
                    // Fallback: пробуем через PathResolver
                    if (class_exists(PathResolver::class)) {
                        try {
                            $flowaxyDir = PathResolver::flowaxy();
                            $relativePath = 'Domain' . DS . 'User' . DS . 'Services' . DS . 'AuthenticateAdminUserService.php';
                            $filePath = $flowaxyDir . DS . $relativePath;

                            if (file_exists($filePath) && is_readable($filePath)) {
                                require_once $filePath;
                            }
                        } catch (\Throwable $e) {
                            // Игнорируем ошибки загрузки
                        }
                    }

                    // Пробуем через autoloader
                    if (function_exists('spl_autoload_call')) {
                        spl_autoload_call($serviceClass);
                    }
                }
            } else {
                // Fallback: пробуем через PathResolver напрямую
                if (class_exists(PathResolver::class)) {
                    try {
                        $flowaxyDir = PathResolver::flowaxy();
                        $relativePath = 'Domain' . DS . 'User' . DS . 'Services' . DS . 'AuthenticateAdminUserService.php';
                        $filePath = $flowaxyDir . DS . $relativePath;

                        if (file_exists($filePath) && is_readable($filePath)) {
                            require_once $filePath;
                        }
                    } catch (\Throwable $e) {
                        // Игнорируем ошибки загрузки
                    }
                }

                // Пробуем через autoloader
                if (function_exists('spl_autoload_call')) {
                    spl_autoload_call($serviceClass);
                }
            }

            // Проверяем еще раз
            if (!class_exists($serviceClass, false)) {
                // Последняя попытка: явная загрузка через PathResolver
                if (class_exists(PathResolver::class)) {
                    try {
                        $flowaxyDir = PathResolver::flowaxy();
                        // Правильно формируем путь: убираем префикс "Flowaxy\" из namespace
                        $namespaceParts = explode('\\', $serviceClass);
                        if ($namespaceParts[0] === 'Flowaxy') {
                            // Убираем первый элемент (Flowaxy) и формируем путь
                            array_shift($namespaceParts);
                            $relativePath = implode(DS, $namespaceParts) . '.php';
                        } else {
                            // Fallback: используем весь namespace
                            $relativePath = str_replace('\\', DS, $serviceClass) . '.php';
                        }
                        $filePath = $flowaxyDir . DS . $relativePath;

                        error_log("SecurityHelper::authenticateAdminUser: Attempting explicit load. Path: {$filePath}, Exists: " . (file_exists($filePath) ? 'yes' : 'no') . ", Readable: " . (is_readable($filePath) ? 'yes' : 'no'));

                        if (file_exists($filePath) && is_readable($filePath)) {
                            // Сначала загружаем зависимости
                            $dependencies = [
                                'Flowaxy\Contracts\Domain\User\AdminUserRepositoryInterface' => $flowaxyDir . DS . 'Contracts' . DS . 'Domain' . DS . 'User' . DS . 'AdminUserRepositoryInterface.php',
                                'Flowaxy\Domain\User\Services\RootUserConfig' => $flowaxyDir . DS . 'Domain' . DS . 'User' . DS . 'Services' . DS . 'RootUserConfig.php',
                                'Flowaxy\Domain\User\Services\AuthenticationResult' => $flowaxyDir . DS . 'Domain' . DS . 'User' . DS . 'Services' . DS . 'AuthenticationResult.php',
                            ];

                            foreach ($dependencies as $depClass => $depPath) {
                                if (!class_exists($depClass, false) && !interface_exists($depClass, false)) {
                                    if (file_exists($depPath) && is_readable($depPath)) {
                                        error_log("SecurityHelper::authenticateAdminUser: Loading dependency: {$depClass}");
                                        @require_once $depPath;
                                        if (class_exists($depClass, false) || interface_exists($depClass, false)) {
                                            error_log("SecurityHelper::authenticateAdminUser: Dependency loaded: {$depClass}");
                                        } else {
                                            error_log("SecurityHelper::authenticateAdminUser: Dependency not loaded: {$depClass}");
                                        }
                                    }
                                }
                            }

                            // Сохраняем текущий уровень ошибок
                            $prevErrorReporting = error_reporting(E_ALL);
                            $prevDisplayErrors = ini_get('display_errors');
                            ini_set('display_errors', '0');

                            // Загружаем файл и перехватываем ошибки
                            $loadError = null;
                            set_error_handler(function($errno, $errstr, $errfile, $errline) use (&$loadError) {
                                $loadError = "Error {$errno}: {$errstr} in {$errfile} on line {$errline}";
                                return true; // Подавляем вывод ошибки
                            });

                            // Проверяем синтаксис файла перед загрузкой
                            $syntaxCheck = shell_exec("php -l " . escapeshellarg($filePath) . " 2>&1");
                            if ($syntaxCheck !== null && strpos($syntaxCheck, 'No syntax errors') === false) {
                                error_log("SecurityHelper::authenticateAdminUser: Syntax error in file: {$syntaxCheck}");
                            } else {
                                error_log("SecurityHelper::authenticateAdminUser: Syntax check passed");
                            }

                            $loaded = @require_once $filePath;

                            restore_error_handler();
                            error_reporting($prevErrorReporting);
                            ini_set('display_errors', $prevDisplayErrors);

                            if ($loadError !== null) {
                                error_log("SecurityHelper::authenticateAdminUser: Error loading file: {$loadError}");
                            }

                            // Проверяем, какие классы были объявлены до и после загрузки
                            $classesBefore = get_declared_classes();
                            $classExists = class_exists($serviceClass, false);

                            // Проверяем все объявленные классы после загрузки
                            $classesAfter = get_declared_classes();
                            $newClasses = array_diff($classesAfter, $classesBefore);

                            error_log("SecurityHelper::authenticateAdminUser: File loaded, loaded={$loaded}, class exists: " . ($classExists ? 'yes' : 'no'));
                            if (!empty($newClasses)) {
                                error_log("SecurityHelper::authenticateAdminUser: New classes declared: " . implode(', ', array_slice($newClasses, 0, 10)));
                            }

                            if (!$classExists) {
                                // Проверяем, может быть класс загружен под другим именем
                                $declaredClasses = get_declared_classes();
                                $foundClass = null;
                                foreach ($declaredClasses as $declaredClass) {
                                    if (str_ends_with($declaredClass, 'AuthenticateAdminUserService')) {
                                        $foundClass = $declaredClass;
                                        break;
                                    }
                                }
                                if ($foundClass !== null) {
                                    error_log("SecurityHelper::authenticateAdminUser: Found similar class: {$foundClass}");
                                }

                                // Проверяем, может быть проблема с namespace
                                $namespaceCheck = "namespace " . explode('\\', $serviceClass)[0];
                                $fileContent = @file_get_contents($filePath);
                                if ($fileContent !== false) {
                                    if (strpos($fileContent, $namespaceCheck) === false) {
                                        error_log("SecurityHelper::authenticateAdminUser: Namespace mismatch. Expected: {$namespaceCheck}");
                                    }
                                    if (strpos($fileContent, 'class AuthenticateAdminUserService') === false && strpos($fileContent, 'final class AuthenticateAdminUserService') === false) {
                                        error_log("SecurityHelper::authenticateAdminUser: Class definition not found in file");
                                    } else {
                                        error_log("SecurityHelper::authenticateAdminUser: Class definition found in file");
                                    }
                                }
                            }
                        } else {
                            // Пробуем альтернативный путь (Domain\User\Services)
                            $altPath = $flowaxyDir . DS . 'Domain' . DS . 'User' . DS . 'Services' . DS . 'AuthenticateAdminUserService.php';
                            error_log("SecurityHelper::authenticateAdminUser: Trying alternative path: {$altPath}, Exists: " . (file_exists($altPath) ? 'yes' : 'no'));

                            if (file_exists($altPath) && is_readable($altPath)) {
                                // Сначала загружаем зависимости
                                $dependencies = [
                                    'Flowaxy\Contracts\Domain\User\AdminUserRepositoryInterface' => $flowaxyDir . DS . 'Contracts' . DS . 'Domain' . DS . 'User' . DS . 'AdminUserRepositoryInterface.php',
                                    'Flowaxy\Domain\User\Services\RootUserConfig' => $flowaxyDir . DS . 'Domain' . DS . 'User' . DS . 'Services' . DS . 'RootUserConfig.php',
                                    'Flowaxy\Domain\User\Services\AuthenticationResult' => $flowaxyDir . DS . 'Domain' . DS . 'User' . DS . 'Services' . DS . 'AuthenticationResult.php',
                                ];

                                foreach ($dependencies as $depClass => $depPath) {
                                    if (!class_exists($depClass, false) && !interface_exists($depClass, false)) {
                                        if (file_exists($depPath) && is_readable($depPath)) {
                                            error_log("SecurityHelper::authenticateAdminUser: Loading dependency: {$depClass}");
                                            @require_once $depPath;
                                            if (class_exists($depClass, false) || interface_exists($depClass, false)) {
                                                error_log("SecurityHelper::authenticateAdminUser: Dependency loaded: {$depClass}");
                                            } else {
                                                error_log("SecurityHelper::authenticateAdminUser: Dependency not loaded: {$depClass}");
                                            }
                                        }
                                    }
                                }

                                // Сохраняем текущий уровень ошибок
                                $prevErrorReporting = error_reporting(E_ALL);
                                $prevDisplayErrors = ini_get('display_errors');
                                ini_set('display_errors', '0');

                                // Загружаем файл и перехватываем ошибки
                                $loadError = null;
                                set_error_handler(function($errno, $errstr, $errfile, $errline) use (&$loadError) {
                                    $loadError = "Error {$errno}: {$errstr} in {$errfile} on line {$errline}";
                                    return true; // Подавляем вывод ошибки
                                });

                                $loaded = @require_once $altPath;

                                restore_error_handler();
                                error_reporting($prevErrorReporting);
                                ini_set('display_errors', $prevDisplayErrors);

                                if ($loadError !== null) {
                                    error_log("SecurityHelper::authenticateAdminUser: Error loading alternative file: {$loadError}");
                                }

                                $classExists = class_exists($serviceClass, false);
                                error_log("SecurityHelper::authenticateAdminUser: Alternative file loaded, loaded={$loaded}, class exists: " . ($classExists ? 'yes' : 'no'));
                            }
                        }
                    } catch (\Throwable $e) {
                        error_log("SecurityHelper::authenticateAdminUser: Exception during explicit load: " . $e->getMessage() . " | File: " . $e->getFile() . " | Line: " . $e->getLine() . " | Trace: " . $e->getTraceAsString());
                    }
                }

                // Финальная проверка
                if (!class_exists($serviceClass, false)) {
                    // Логируем ошибку
                    try {
                        Log::Error('AuthenticateAdminUserService class not found', [
                            'class' => $serviceClass,
                            'trace' => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3)
                        ]);
                    } catch (\Throwable $e) {
                        // Игнорируем ошибки логирования
                    }
                    error_log("SecurityHelper::authenticateAdminUser: AuthenticateAdminUserService class still not found after all loading attempts: {$serviceClass}");
                    return ['success' => false, 'error' => 'Невірний логін або пароль'];
                }
            }
        }

        try {
            // Пробуем получить сервис из контейнера
            $service = null;
            if (class_exists(App::class)) {
                try {
                    $container = App::container();
                    /** @phpstan-ignore-next-line */
                    if ($container && $container->has($serviceClass)) {
                        /** @phpstan-ignore-next-line */
                        $service = $container->make($serviceClass);
                        // Если контейнер вернул Closure, вызываем его
                        if ($service instanceof \Closure) {
                            $service = $service();
                        }
                    }
                } catch (\Throwable $e) {
                    // Логируем ошибку контейнера
                    try {
                        Log::Warning('Container error in authenticateAdminUser', [
                            'error' => $e->getMessage(),
                            'class' => $serviceClass
                        ]);
                    } catch (\Throwable $logError) {
                        // Игнорируем ошибки логирования
                    }
                }
            }

            // Если не получилось из контейнера, создаем напрямую
            if ($service === null) {
                // Получаем репозиторий пользователей
                $userRepo = null;
                $repoInterface = AdminUserRepositoryInterface::class;

                // Пробуем загрузить интерфейс
                if (!interface_exists($repoInterface)) {
                    if (function_exists('spl_autoload_call')) {
                        spl_autoload_call($repoInterface);
                    }
                }

                if (class_exists(App::class)) {
                    try {
                        $container = App::container();
                        if ($container && $container->has($repoInterface)) {
                            $userRepo = $container->make($repoInterface);
                            if ($userRepo instanceof \Closure) {
                                $userRepo = $userRepo();
                            }
                        }
                    } catch (\Throwable $e) {
                        // Игнорируем ошибки контейнера
                    }
                }

                // Если репозиторий не получен, создаем напрямую
                if ($userRepo === null) {
                    $repoClass = AdminUserRepository::class;

                    // Сначала загружаем все необходимые зависимости
                    // Важно: загружаем правильный интерфейс AdminUserRepositoryInterface из Contracts
                    $repoInterface = AdminUserRepositoryInterface::class;
                    if (!interface_exists($repoInterface)) {
                        if (class_exists(ClassLoaderHelper::class)) {
                            ClassLoaderHelper::ensureLoaded($repoInterface);
                        } else if (function_exists('spl_autoload_call')) {
                            spl_autoload_call($repoInterface);
                        }
                    }

                    $dependencies = [
                        'Flowaxy\Domain\User\Entities\AdminUser',
                        'Flowaxy\Support\Helpers\DatabaseHelper',
                        'Flowaxy\Support\Facades\Log',
                    ];

                    foreach ($dependencies as $depClass) {
                        if (!class_exists($depClass) && !interface_exists($depClass)) {
                            if (class_exists(ClassLoaderHelper::class)) {
                                ClassLoaderHelper::ensureLoaded($depClass);
                            } else if (function_exists('spl_autoload_call')) {
                                spl_autoload_call($depClass);
                            }
                        }
                    }

                    // Пробуем загрузить класс репозитория через ClassLoaderHelper
                    if (!class_exists($repoClass)) {
                        // Спочатку пробуем через PathResolver напрямую (найнадійніший спосіб)
                        if (class_exists(PathResolver::class)) {
                            try {
                                $flowaxyDir = PathResolver::flowaxy();
                                $relativePath = 'Infrastructure' . DS . 'Persistence' . DS . 'Repositories' . DS . 'AdminUserRepository.php';
                                $filePath = $flowaxyDir . DS . $relativePath;

                                if (file_exists($filePath) && is_readable($filePath)) {
                                    require_once $filePath;
                                }
                            } catch (\Throwable $e) {
                                // Игнорируем ошибки загрузки
                            }
                        }

                        // Потім пробуем через ClassLoaderHelper
                        if (!class_exists($repoClass) && class_exists(ClassLoaderHelper::class)) {
                            ClassLoaderHelper::ensureLoaded($repoClass);
                        }

                        // І нарешті пробуем через autoloader
                        if (!class_exists($repoClass) && function_exists('spl_autoload_call')) {
                            spl_autoload_call($repoClass);
                        }
                    }

                    // Проверяем, что класс загружен и реализует интерфейс
                    if (class_exists($repoClass)) {
                        try {
                            $userRepo = new $repoClass();

                            // Проверяем, что репозиторий реализует нужный интерфейс
                            if (!($userRepo instanceof AdminUserRepositoryInterface)) {
                                try {
                                    Log::Error('AdminUserRepository does not implement AdminUserRepositoryInterface', [
                                        'class' => $repoClass,
                                        'implements' => class_implements($repoClass)
                                    ]);
                                } catch (\Throwable $logError) {
                                    // Игнорируем ошибки логирования
                                }
                                error_log("SecurityHelper::authenticateAdminUser: AdminUserRepository does not implement AdminUserRepositoryInterface: {$repoClass}");
                                return ['success' => false, 'error' => 'Невірний логін або пароль'];
                            }
                        } catch (\Throwable $e) {
                            // Логируем ошибку создания репозитория
                            try {
                                Log::Error('Failed to create AdminUserRepository', [
                                    'class' => $repoClass,
                                    'error' => $e->getMessage(),
                                    'trace' => $e->getTraceAsString()
                                ]);
                            } catch (\Throwable $logError) {
                                // Игнорируем ошибки логирования
                            }
                            error_log("SecurityHelper::authenticateAdminUser: Failed to create AdminUserRepository: {$repoClass}, Error: " . $e->getMessage());
                            return ['success' => false, 'error' => 'Невірний логін або пароль'];
                        }
                    } else {
                        // Логируем ошибку
                        try {
                            Log::Error('AdminUserRepository class not found', [
                                'class' => $repoClass,
                                'class_exists' => class_exists($repoClass),
                                'interface_exists' => interface_exists(AdminUserRepositoryInterface::class)
                            ]);
                        } catch (\Throwable $logError) {
                            // Игнорируем ошибки логирования
                        }
                        error_log("SecurityHelper::authenticateAdminUser: AdminUserRepository class not found: {$repoClass}");
                        return ['success' => false, 'error' => 'Невірний логін або пароль'];
                    }
                }

                // Получаем репозиторий ролей
                $roleRepo = null;
                $roleRepoInterface = \Flowaxy\Contracts\Domain\User\AdminRoleRepositoryInterface::class;

                // Пробуем загрузить интерфейс
                if (!interface_exists($roleRepoInterface)) {
                    if (class_exists(ClassLoaderHelper::class)) {
                        ClassLoaderHelper::ensureLoaded($roleRepoInterface);
                    } else if (function_exists('spl_autoload_call')) {
                        spl_autoload_call($roleRepoInterface);
                    }
                }

                // Пробуем получить из контейнера
                if (class_exists(App::class)) {
                    try {
                        $container = App::container();
                        if ($container && $container->has($roleRepoInterface)) {
                            $roleRepo = $container->make($roleRepoInterface);
                            if ($roleRepo instanceof \Closure) {
                                $roleRepo = $roleRepo();
                            }
                        }
                    } catch (\Throwable $e) {
                        // Игнорируем ошибки контейнера
                    }
                }

                // Если не получили из контейнера, создаем напрямую
                if ($roleRepo === null) {
                    $roleRepoClass = \Flowaxy\Infrastructure\Persistence\Repositories\AdminRoleRepository::class;

                    // Загружаем класс репозитория
                    if (!class_exists($roleRepoClass)) {
                        if (class_exists(ClassLoaderHelper::class)) {
                            ClassLoaderHelper::ensureLoaded($roleRepoClass);
                        } else if (function_exists('spl_autoload_call')) {
                            spl_autoload_call($roleRepoClass);
                        }
                    }

                    if (class_exists($roleRepoClass)) {
                        try {
                            $roleRepo = new $roleRepoClass();
                            error_log("SecurityHelper::authenticateAdminUser: AdminRoleRepository created successfully");
                        } catch (\Throwable $e) {
                            // Логируем ошибку
                            error_log("SecurityHelper::authenticateAdminUser: Failed to create AdminRoleRepository: " . $e->getMessage());
                            try {
                                Log::Error('Failed to create AdminRoleRepository in SecurityHelper', [
                                    'error' => $e->getMessage(),
                                    'trace' => $e->getTraceAsString()
                                ]);
                            } catch (\Throwable $logError) {
                                // Ignore logging errors
                            }
                        }
                    } else {
                        error_log("SecurityHelper::authenticateAdminUser: AdminRoleRepository class not found: {$roleRepoClass}");
                    }
                }

                error_log("SecurityHelper::authenticateAdminUser: RoleRepository available: " . ($roleRepo !== null ? 'yes' : 'no'));

                /** @phpstan-ignore-next-line */
                $service = new $serviceClass($userRepo, $roleRepo);
            }

            // Вызываем метод execute (не authenticate!)
            $result = $service->execute($username, $password);

            // Преобразуем AuthenticationResult в массив
            if ($result->success) {
                // Логируем успешную авторизацию
                try {
                    Log::Info('authenticateAdminUser: Authentication successful', [
                        'user_id' => $result->userId,
                        'username' => $username,
                        'session_status_before' => session_status()
                    ]);
                } catch (\Throwable $e) {
                    // Игнорируем ошибки логирования
                }

                // Убеждаемся, что сессия запущена
                $sessionWasStarted = false;
                if (class_exists(Session::class)) {
                    if (!Session::isStarted()) {
                        Session::start();
                        $sessionWasStarted = true;
                    }
                } elseif (session_status() !== PHP_SESSION_ACTIVE) {
                    if (function_exists('session_start')) {
                        session_start();
                        $sessionWasStarted = true;
                    }
                }

                // Логируем статус сессии
                try {
                    Log::Debug('authenticateAdminUser: Session status after start', [
                        'session_status' => session_status(),
                        'session_id' => session_id() ?: 'none',
                        'session_was_started' => $sessionWasStarted,
                        'Session::isStarted()' => class_exists(Session::class) ? Session::isStarted() : 'N/A'
                    ]);
                } catch (\Throwable $e) {
                    // Игнорируем ошибки логирования
                }

                // Сохраняем сессию пользователя - используем прямой доступ к $_SESSION для надежности
                try {
                    // Убеждаемся, что сессия активна
                    if (session_status() !== PHP_SESSION_ACTIVE) {
                        if (class_exists(Session::class)) {
                            Session::start();
                        } elseif (function_exists('session_start')) {
                            session_start();
                        }
                    }

                    // Сохраняем напрямую в $_SESSION для надежности
                    if (session_status() === PHP_SESSION_ACTIVE) {
                        $_SESSION['admin_user_id'] = $result->userId;

                        // Логируем сохранение в $_SESSION с полной диагностикой
                        try {
                            Log::Debug('authenticateAdminUser: Saved to $_SESSION', [
                                'user_id' => $result->userId,
                                'session_key' => 'admin_user_id',
                                'session_value' => $_SESSION['admin_user_id'] ?? 'NOT SET',
                                'all_session_keys' => array_keys($_SESSION ?? []),
                                'session_id' => session_id() ?: 'none',
                                'session_status' => session_status(),
                                'session_name' => session_name(),
                                'session_cookie_params' => session_get_cookie_params(),
                                'headers_sent' => headers_sent(),
                                'cookies' => $_COOKIE ?? []
                            ]);
                        } catch (\Throwable $e) {
                            // Игнорируем ошибки логирования
                        }

                        // Также пробуем через SessionFacade для совместимости
                        if (class_exists(SessionFacade::class)) {
                            try {
                                $session = SessionFacade::manager();
                                if ($session) {
                                    $session->set('admin_user_id', $result->userId);

                                    // Логируем сохранение через SessionFacade
                                    try {
                                        Log::Debug('authenticateAdminUser: Saved via SessionFacade', [
                                            'user_id' => $result->userId,
                                            'session_manager_class' => get_class($session)
                                        ]);
                                    } catch (\Throwable $e) {
                                        // Игнорируем ошибки логирования
                                    }
                                }
                            } catch (\Throwable $e) {
                                // Логируем ошибку SessionFacade
                                try {
                                    Log::Warning('authenticateAdminUser: SessionFacade error', [
                                        'error' => $e->getMessage(),
                                        'trace' => $e->getTraceAsString()
                                    ]);
                                } catch (\Throwable $logError) {
                                    // Игнорируем ошибки логирования
                                }
                            }
                        }
                    } else {
                        // Логируем проблему с сессией
                        try {
                            Log::Error('authenticateAdminUser: Session not active, cannot save', [
                                'user_id' => $result->userId,
                                'session_status' => session_status(),
                                'Session::isStarted()' => class_exists(Session::class) ? Session::isStarted() : 'N/A'
                            ]);
                        } catch (\Throwable $logError) {
                            // Игнорируем ошибки логирования
                        }
                    }
                } catch (\Throwable $e) {
                    // Логируем ошибку сохранения сессии
                    try {
                        Log::Error('authenticateAdminUser: Failed to save admin session', [
                            'user_id' => $result->userId,
                            'error' => $e->getMessage(),
                            'trace' => $e->getTraceAsString(),
                            'session_status' => session_status()
                        ]);
                    } catch (\Throwable $logError) {
                        // Игнорируем ошибки логирования
                    }
                }

                // Финальная проверка сохранения
                try {
                    $savedUserId = $_SESSION['admin_user_id'] ?? null;
                    Log::Debug('authenticateAdminUser: Final session check', [
                        'user_id_to_save' => $result->userId,
                        'saved_user_id' => $savedUserId,
                        'session_status' => session_status(),
                        'session_id' => session_id() ?: 'none',
                        'session_saved' => ($savedUserId === $result->userId)
                    ]);
                } catch (\Throwable $e) {
                    // Игнорируем ошибки логирования
                }

                return [
                    'success' => true,
                    'user' => ['id' => $result->userId],
                ];
            }

            return [
                'success' => false,
                'error' => $result->message ?: 'Невірний логін або пароль',
            ];
        } catch (\Throwable $e) {
            // Логируем полную ошибку в лог, но не показываем технические детали пользователю
            try {
                Log::Error('authenticateAdminUser: Authentication error', [
                    'exception' => $e,
                    'error' => $e->getMessage(),
                    'code' => $e->getCode(),
                    'file' => $e->getFile(),
                    'line' => $e->getLine(),
                    'trace' => $e->getTraceAsString(),
                    'username' => $username
                ]);
            } catch (\Throwable $logError) {
                // Игнорируем ошибки логирования
            }

            // Показываем пользователю общее сообщение, не технические детали
            return [
                'success' => false,
                'error' => $result->message ?: 'Невірний логін або пароль',
            ];
        }
    }

    /**
     * Перевірка, чи залогінений адмін
     * Перевірка тільки через базу даних (без перевірки сесії)
     *
     * @return bool
     */
    public static function isAdminLoggedIn(): bool
    {
        // Логируем начало проверки
        try {
            Log::Debug('isAdminLoggedIn: Starting check', [
                    'session_status' => session_status(),
                    'session_id' => session_id() ?: 'none',
                    'Session::class_exists' => class_exists(Session::class),
                    'Session::isStarted()' => class_exists(Session::class) ? Session::isStarted() : 'N/A',
                    'SessionFacade::class_exists' => class_exists(SessionFacade::class),
                    '$_SESSION_exists' => isset($_SESSION),
                    '$_SESSION_keys' => isset($_SESSION) ? array_keys($_SESSION) : [],
                    '$_SESSION_admin_user_id_direct' => $_SESSION['admin_user_id'] ?? 'NOT SET'
                ]);
        } catch (\Throwable $e) {
            // Игнорируем ошибки логирования
        }

        // Сначала проверяем напрямую $_SESSION - это самый надежный способ
        $userId = null; // Используем null вместо 0, чтобы различать "не установлен" и "root (0)"
        $method = 'none';

        if (session_status() === PHP_SESSION_ACTIVE && isset($_SESSION['admin_user_id'])) {
            $userId = (int)$_SESSION['admin_user_id'];
            $method = '$_SESSION';
        }

        // Если не получили из $_SESSION, пробуем через SessionFacade
        // ВАЖНО: userId = 0 (root) считается валидным только если он явно установлен в сессии
        if ($userId === null) {
            // Убеждаемся, что сессия запущена
            if (!class_exists(Session::class) || !Session::isStarted()) {
                // Пробуем запустить сессию
                if (session_status() !== PHP_SESSION_ACTIVE) {
                    if (class_exists(Session::class)) {
                        try {
                            Session::start();
                        } catch (\Throwable $e) {
                            // Игнорируем ошибки запуска сессии
                        }
                    } elseif (function_exists('session_start') && !headers_sent()) {
                        @session_start();
                    }
                }

                // Проверяем еще раз после запуска
                if (session_status() === PHP_SESSION_ACTIVE && isset($_SESSION['admin_user_id'])) {
                    $userId = (int)$_SESSION['admin_user_id'];
                    $method = '$_SESSION (after start)';
                }
            }

            // Если все еще не получили, пробуем через SessionFacade
            // ВАЖНО: userId = 0 (root) считается валидным только если он явно установлен в сессии
            if ($userId === null && class_exists(SessionFacade::class)) {
                try {
                    $session = SessionFacade::manager();
                    $sessionUserId = $session->get('admin_user_id');
                    // Принимаем userId только если он явно установлен (включая 0 для root)
                    if ($sessionUserId !== null && $sessionUserId !== false) {
                        $userId = (int)$sessionUserId;
                        $method = 'SessionFacade';
                    }
                } catch (\Throwable $e) {
                    // Логируем ошибку SessionFacade
                    try {
                        Log::Warning('isAdminLoggedIn: SessionFacade error', [
                            'error' => $e->getMessage()
                        ]);
                    } catch (\Throwable $logError) {
                        // Игнорируем ошибки логирования
                    }
                }
            }
        }

        // Логируем результат проверки
        try {
            Log::Debug('isAdminLoggedIn: Check result', [
                'user_id' => $userId,
                'user_id_type' => gettype($userId),
                'method' => $method,
                'session_status' => session_status(),
                '$_SESSION_admin_user_id' => $_SESSION['admin_user_id'] ?? 'NOT SET',
                'is_logged_in' => ($userId !== null && $userId >= 0) // Root user (userId = 0) считается авторизованным только если явно установлен
            ]);
        } catch (\Throwable $e) {
            // Игнорируем ошибки логирования
        }

        // Если userId не установлен (null), пользователь не авторизован
        if ($userId === null) {
            return false;
        }

        // Root пользователь (userId = 0) считается авторизованным только если он явно установлен в сессии
        if ($userId === 0) {
            return true;
        }

        // Если userId < 0, пользователь не авторизован
        if ($userId < 0) {
            return false;
        }

        // Перевіряємо авторизацію через доменний репозиторій
        try {
            // Загружаем AdminUserRepository перед использованием
            ClassLoaderHelper::ensureLoaded(AdminUserRepository::class);
            ClassLoaderHelper::ensureLoaded(AdminUserRepositoryInterface::class);

            $containerFunc = 'container';
            $repository = null;

            // Пробуем получить из контейнера
            if (function_exists($containerFunc) && interface_exists(AdminUserRepositoryInterface::class)) {
                try {
                    $container = $containerFunc();
                    if ($container && method_exists($container, 'make') && $container->has(AdminUserRepositoryInterface::class)) {
                        $repository = $container->make(AdminUserRepositoryInterface::class);
                    }
                } catch (\Throwable $e) {
                    // Игнорируем ошибки контейнера
                }
            }

            // Если не получили из контейнера, создаем напрямую
            if ($repository === null && class_exists(AdminUserRepository::class)) {
                $repository = new AdminUserRepository();
            }

            if ($repository) {
                // Отримуємо час життя сесії з налаштувань
                $sessionLifetime = self::DEFAULT_SESSION_LIFETIME;
                if (class_exists(SystemConfig::class)) {
                    $systemConfig = SystemConfig::getInstance();
                    $sessionLifetime = $systemConfig->getSessionLifetime();
                }

                $user = $repository->findById($userId);

                if (!$user) {
                    // Користувача не знайдено
                    self::logout();
                    return false;
                }

                // Перевіряємо, чи активний користувач
                if (!$user->isActive) {
                    // Користувач неактивний
                    self::logout();
                    return false;
                }

                // Перевіряємо наявність токена сесії
                if (empty($user->sessionToken)) {
                    // Токен відсутній - користувач не авторизований
                    self::logout();
                    return false;
                }

                // Перевіряємо валідність сесії за часом останньої активності
                if (!empty($user->lastActivity)) {
                    $lastActivity = strtotime($user->lastActivity);
                    $currentTime = time();
                    $timeDiff = $currentTime - $lastActivity;

                    // Якщо пройшло більше часу життя сесії - сесія закінчилася
                    if ($timeDiff > $sessionLifetime) {
                        // Сесія закінчилася - позначаємо користувача як неактивного
                        $repository->clearSession($userId);
                        self::logout();
                        return false;
                    }

                    $repository->updateLastActivity($userId, date('Y-m-d H:i:s'));
                } elseif (!empty($user->sessionToken)) {
                    // Якщо last_activity відсутня, але є токен - встановлюємо час активності
                    $now = date('Y-m-d H:i:s');
                    $repository->updateLastActivity($userId, $now);
                }

                return true;
            }
        } catch (\Exception $e) {
            if (class_exists(Logger::class)) {
                Logger::getInstance()->logError('Помилка перевірки авторизації адміна', ['error' => $e->getMessage()]);
            }

            // У разі помилки БД дозволяємо доступ (щоб не блокувати користувача)
            return true;
        }

        return false;
    }

    /**
     * Вихід з системи (очищення сесії та позначка користувача як неактивного)
     *
     * @return void
     */
    public static function logout(): void
    {
        // Перевіряємо, чи клас завантажений перед використанням
        if (!class_exists(SessionFacade::class)) {
            return;
        }

        $session = SessionFacade::manager();
        $userId = (int)$session->get('admin_user_id');

        // Позначаємо користувача як неактивного та очищаємо токен у базі даних
        if ($userId > 0) {
            try {
                $logoutService = null;
                $logoutServiceClass = LogoutUserService::class;

                if (class_exists($logoutServiceClass)) {
                    $containerFunc = 'container';
                    if (function_exists($containerFunc)) {
                        try {
                            /** @phpstan-ignore-next-line */
                            $logoutService = $containerFunc()->make($logoutServiceClass);
                            // Перевіряємо, що контейнер повернув об'єкт, а не Closure
                            if ($logoutService instanceof \Closure) {
                                $logoutService = null;
                            }
                        } catch (\Exception $e) {
                            $logoutService = null;
                        }
                    }

                    // Fallback: створюємо екземпляр напряму
                    if ($logoutService === null) {
                        // Загружаем классы перед использованием
                        ClassLoaderHelper::ensureLoaded($logoutServiceClass);
                        ClassLoaderHelper::ensureLoaded(AdminUserRepository::class);
                        ClassLoaderHelper::ensureLoaded(AdminUserRepositoryInterface::class);

                        if (class_exists($logoutServiceClass) && class_exists(AdminUserRepository::class)) {
                            /** @phpstan-ignore-next-line */
                            $logoutService = new $logoutServiceClass(new AdminUserRepository());
                        }
                    }
                }

                if ($logoutService && !($logoutService instanceof \Closure) && method_exists($logoutService, 'execute')) {
                    $logoutService->execute($userId);
                } else {
                    // Загружаем классы перед использованием
                    ClassLoaderHelper::ensureLoaded(AdminUserRepository::class);
                    ClassLoaderHelper::ensureLoaded(AdminUserRepositoryInterface::class);

                    $containerFunc = 'container';
                    $repository = null;

                    // Пробуем получить из контейнера
                    if (function_exists($containerFunc) && interface_exists(AdminUserRepositoryInterface::class)) {
                        try {
                            $container = $containerFunc();
                            if ($container && method_exists($container, 'make') && $container->has(AdminUserRepositoryInterface::class)) {
                                $repository = $container->make(AdminUserRepositoryInterface::class);
                            }
                        } catch (\Throwable $e) {
                            // Игнорируем ошибки контейнера
                        }
                    }

                    // Если не получили из контейнера, создаем напрямую
                    if ($repository === null && class_exists(AdminUserRepository::class)) {
                        $repository = new AdminUserRepository();
                    }

                    if ($repository !== null) {
                        $repository->clearSession($userId);
                    }
                }
            } catch (\Exception $e) {
                if (class_exists(Logger::class)) {
                    Logger::getInstance()->logError('Помилка очищення сесії', ['error' => $e->getMessage()]);
                }
            }
        }

        // Очищаємо сесію
        $session->remove(ADMIN_SESSION_NAME);
        $session->remove('admin_user_id');
        $session->remove('admin_username');
    }

    /**
     * Вимагає авторизації адміна
     *
     * @return void
     */
    public static function requireAdmin(): void
    {
        // Переконуємося, що сесія запущена перед перевіркою
        if (!class_exists(Session::class) || !Session::isStarted()) {
            if (class_exists(Session::class)) {
                Session::start();
            }
        }

        if (!self::isAdminLoggedIn()) {
            // Для AJAX запитів повертаємо JSON помилку
            if (class_exists(AjaxHandler::class) && AjaxHandler::isAjax()) {
                // Очищаємо буфер виводу
                while (ob_get_level() > 0) {
                    ob_end_clean();
                }

                if (class_exists(Response::class)) {
                    Response::jsonResponse([
                        'success' => false,
                        'error' => 'Потрібна авторизація',
                        'auth_required' => true,
                    ], 401);
                } else {
                    http_response_code(401);
                    header('Content-Type: application/json; charset=UTF-8');
                    echo json_encode([
                        'success' => false,
                        'error' => 'Потрібна авторизація',
                        'auth_required' => true,
                    ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                    exit;
                }
            }

            // Для звичайних запитів робимо редірект
            if (class_exists(Response::class)) {
                $adminLoginUrl = class_exists(UrlHelper::class) ? UrlHelper::admin('login') : (defined('ADMIN_URL') ? ADMIN_URL . '/login' : '/admin/login');
                Response::redirectStatic($adminLoginUrl);
            } else {
                $adminLoginUrl = class_exists(UrlHelper::class) ? UrlHelper::admin('login') : (defined('ADMIN_URL') ? ADMIN_URL . '/login' : '/admin/login');
                header('Location: ' . $adminLoginUrl);
                exit;
            }
        }
    }

    /**
     * Безпечний вивід HTML
     *
     * @param mixed $value Значення для виводу
     * @param string $default Значення за замовчуванням
     * @return string
     */
    public static function safeHtml(mixed $value, string $default = ''): string
    {
        if (!class_exists(Security::class)) {
            return '';
        }

        if (is_array($value) || is_object($value)) {
            return Security::clean(Json::stringify($value));
        }

        return Security::clean((string)($value ?: $default));
    }

    /**
     * Санітизація вхідних даних
     *
     * @param mixed $input Вхідні дані
     * @return string
     */
    public static function sanitizeInput(mixed $input): string
    {
        if (!class_exists(Security::class)) {
            return '';
        }

        if (is_string($input)) {
            return Security::clean(trim($input), true);
        }

        if (is_numeric($input)) {
            return (string)$input;
        }

        if (is_array($input)) {
            try {
                return Json::stringify($input);
            } catch (\Exception $e) {
                if (class_exists(Logger::class)) {
                    Logger::getInstance()->logError('Помилка кодування JSON', ['error' => $e->getMessage()]);
                }
                return '';
            }
        }

        if (is_bool($input)) {
            return $input ? '1' : '0';
        }

        return '';
    }

    /**
     * Хешування значення
     *
     * @param string $value
     * @return string
     */
    public static function hash(string $value): string
    {
        // Загружаем Hash класс перед использованием
        ClassLoaderHelper::ensureLoaded(SecurityHash::class);

        if (class_exists(SecurityHash::class)) {
            return SecurityHash::make($value);
        }

        return password_hash($value, PASSWORD_DEFAULT);
    }

    /**
     * Перевірка хешу
     *
     * @param string $value
     * @param string $hash
     * @return bool
     */
    public static function verifyHash(string $value, string $hash): bool
    {
        // Загружаем Hash класс перед использованием
        ClassLoaderHelper::ensureLoaded(SecurityHash::class);

        if (class_exists(SecurityHash::class)) {
            return SecurityHash::check($value, $hash);
        }

        return password_verify($value, $hash);
    }

    /**
     * Шифрування значення
     *
     * @param string $value
     * @return string
     */
    public static function encrypt(string $value): string
    {
        if (class_exists(Encryption::class)) {
            try {
                $encryption = new Encryption();
                return $encryption->encrypt($value);
            } catch (\Throwable $e) {
                // Fallback на base64
            }
        }

        return base64_encode($value);
    }

    /**
     * Розшифрування значення
     *
     * @param string $value
     * @return string
     */
    public static function decrypt(string $value): string
    {
        if (class_exists(Encryption::class)) {
            try {
                $encryption = new Encryption();
                return $encryption->decrypt($value);
            } catch (\Throwable $e) {
                // Fallback на base64
            }
        }

        return base64_decode($value, true) ?: '';
    }

    /**
     * Генерація випадкового токена
     *
     * @param int $length
     * @return string
     */
    public static function generateToken(int $length = 32): string
    {
        return bin2hex(random_bytes($length));
    }

    /**
     * Перевірка, чи рядок є валідним email
     *
     * @param string $email
     * @return bool
     */
    public static function isValidEmail(string $email): bool
    {
        return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
    }

    /**
     * Перевірка, чи рядок є валідним URL
     *
     * @param string $url
     * @return bool
     */
    public static function isValidUrl(string $url): bool
    {
        return filter_var($url, FILTER_VALIDATE_URL) !== false;
    }

    /**
     * Отримання ID поточного адміністратора з сесії
     *
     * @return int ID користувача або 0, якщо не знайдено
     */
    public static function getCurrentAdminUserId(): int
    {
        return SessionHelper::getUserId();
    }

    /**
     * Перевірка доступу до адмін-панелі
     *
     * @param int|null $userId ID користувача (якщо null, береться з сесії)
     * @return bool
     */
    public static function checkAdminAccess(?int $userId = null): bool
    {
        // Якщо userId не вказано, отримуємо з сесії
        if ($userId === null) {
            $userId = self::getCurrentAdminUserId();
        }

        // Root пользователь (userId = 0) всегда имеет полный доступ
        if ($userId === 0) {
            return true;
        }

        // Все остальные пользователи (включая userId = 1) должны иметь право 'admin.access'
        // Якщо користувач не залогінений, доступу немає
        if ($userId === null || $userId < 1) {
            return false;
        }

        // Перевіряємо через current_user_can()
        if (function_exists('current_user_can')) {
            return current_user_can('admin.access');
        }

        // Якщо функція не доступна, НЕ дозволяємо доступ - это ошибка конфигурации
        return false;
    }

    /**
     * Вимагаємо доступ до адмін-панелі з редиректом, якщо доступу немає
     *
     * @param int|null $userId ID користувача (якщо null, береться з сесії)
     * @return void
     */
    public static function requireAdminAccess(?int $userId = null): void
    {
        if (!self::checkAdminAccess($userId)) {
            $userId ??= self::getCurrentAdminUserId();

            // Логуємо спробу доступу без прав
            try {
                Log::Warning('Access denied to admin panel', ['user_id' => $userId]);
            } catch (\Throwable $e) {
                // Игнорируем ошибки логирования
            }

            // Встановлюємо HTTP статус 403
            http_response_code(403);

            // Якщо це AJAX запит, повертаємо JSON
            if (class_exists(AjaxHandler::class) && AjaxHandler::isAjax()) {
                header('Content-Type: application/json; charset=UTF-8');
                echo json_encode([
                    'success' => false,
                    'error' => 'Доступ заборонено. У вас немає прав для доступу до адміністративної панелі.'
                ], JSON_UNESCAPED_UNICODE);
                exit;
            }

            // Для звичайних запитів показуємо текст помилки
            echo 'Доступ заборонено. У вас немає прав для доступу до адміністративної панелі.';
            exit;
        }
    }
}
