<?php

/**
 * Фасад для роботи з сесіями
 *
 * @package Flowaxy\Support\Facades
 */

declare(strict_types=1);

namespace Flowaxy\Support\Facades;

use Flowaxy\Support\Managers\SessionManager;
use Flowaxy\Core\System\PathResolver;

use RuntimeException;
use Throwable;
use Closure;

use function class_exists;
use function interface_exists;
use function file_exists;
use function is_readable;

final class Session extends Facade
{
    protected static function getFacadeAccessor(): string
    {
        return SessionManager::class;
    }

    /**
     * Отримання менеджера сесій
     */
    public static function manager(string $prefix = ''): SessionManager
    {
        // Спочатку пробуємо отримати через контейнер
        try {
            $manager = static::getFacadeRoot();
            // Якщо повернуто Closure, викликаємо його
            if ($manager instanceof Closure) {
                $manager = $manager();
            }
            // Перевіряємо, чи це SessionManager
            if ($manager instanceof SessionManager) {
                if ($prefix) {
                    $manager->setPrefix($prefix);
                }
                return $manager;
            }
        } catch (RuntimeException $e) {
            // Контейнер не ініціалізований або SessionManager не зареєстрований
            // Продовжуємо до fallback
        } catch (Throwable $e) {
            // Будь-яка інша помилка - продовжуємо до fallback
        }

        // Fallback: використовуємо getInstance() напряму
        // Перевіряємо, чи клас завантажений
        if (!class_exists(SessionManager::class)) {
            $flowaxyDir = PathResolver::flowaxy();

            // Спочатку завантажуємо інтерфейс StorageInterface, якщо він не завантажений
            if (!interface_exists(\Flowaxy\Contracts\Filesystem\StorageInterface::class)) {
                $storageInterfaceFile = $flowaxyDir
                    . DS . 'Contracts'
                    . DS . 'Filesystem'
                    . DS . 'StorageInterface.php';
                if (file_exists($storageInterfaceFile) && is_readable($storageInterfaceFile)) {
                    require_once $storageInterfaceFile;
                }
            }

            // Завантажуємо клас Session (залежність для SessionManager)
            if (!class_exists(\Flowaxy\Infrastructure\Security\Session::class)) {
                $sessionFile = $flowaxyDir
                    . DS . 'Infrastructure'
                    . DS . 'Security'
                    . DS . 'Session.php';
                if (file_exists($sessionFile) && is_readable($sessionFile)) {
                    require_once $sessionFile;
                }
            }

            // Завантажуємо клас SessionManager
            $sessionManagerFile = $flowaxyDir
                . DS . 'Support'
                . DS . 'Managers'
                . DS . 'SessionManager.php';
            if (file_exists($sessionManagerFile) && is_readable($sessionManagerFile)) {
                require_once $sessionManagerFile;
            }
        }

        // Тепер пробуємо getInstance()
        if (class_exists(SessionManager::class)) {
            try {
                $manager = SessionManager::getInstance();
                if ($manager instanceof SessionManager) {
                    if ($prefix) {
                        $manager->setPrefix($prefix);
                    }
                    return $manager;
                }
            } catch (Throwable $e) {
                // getInstance() не спрацював
            }
        }

        throw new RuntimeException('SessionManager not found in container and getInstance() failed. Make sure SessionManager class is loaded and container is initialized.');
    }

    /**
     * Отримання значення з сесії
     */
    public static function get(string $key, mixed $default = null): mixed
    {
        return static::manager()->get($key, $default);
    }

    /**
     * Збереження значення в сесію
     */
    public static function set(string $key, mixed $value): void
    {
        static::manager()->set($key, $value);
    }

    /**
     * Видалення значення з сесії
     */
    public static function delete(string $key): void
    {
        static::manager()->remove($key);
    }

    /**
     * Очищення сесії
     */
    public static function clear(): void
    {
        static::manager()->clear();
    }
}
