<?php

/**
 * Клас для роботи з filters (фільтрами) у стилі WordPress
 *
 * @package Flowaxy\Core\Hooks
 * @version 1.0.0
 */

declare(strict_types=1);

namespace Flowaxy\Core\Hooks;

use Flowaxy\Core\Contracts\HookManagerInterface;
use Flowaxy\Core\Hooks\HookManager;
use Flowaxy\Core\Hooks\HookType;
use Flowaxy\Support\Facades\App;
use Exception;

use function class_exists;
use function function_exists;
use function method_exists;

/**
 * Статичний клас для роботи з filters
 *
 * Приклад використання:
 * Filter::add('the_title', function($title) { return strtoupper($title); });
 * $title = Filter::apply('the_title', 'Hello World');
 */
final class Filter
{
    /**
     * Отримання екземпляра HookManager
     *
     * @return HookManagerInterface
     */
    private static function getHookManager(): HookManagerInterface
    {
        static $hookManager = null;

        if ($hookManager === null) {
            // Спробуємо отримати з контейнера
            try {
                $container = App::container();
                if ($container !== null && method_exists($container, 'has') && $container->has(HookManagerInterface::class)) {
                    $resolved = $container->make(HookManagerInterface::class);
                    if ($resolved instanceof HookManagerInterface) {
                        $hookManager = $resolved;
                        return $hookManager;
                    }
                }
            } catch (Exception $e) {
                // Fallback нижче
            }

            // Спробуємо отримати через hooks() функцію
            if (function_exists('hooks')) {
                try {
                    // @phpstan-ignore-next-line - hooks() is a global function
                    $hookManager = \hooks();
                    if ($hookManager instanceof HookManagerInterface) {
                        return $hookManager;
                    }
                } catch (Exception $e) {
                    // Fallback нижче
                }
            }

            // Fallback: створюємо новий екземпляр
            $hookManager = new HookManager();
        }

        return $hookManager;
    }

    /**
     * Додавання filter (фільтра)
     *
     * @param string $hookName Назва хука
     * @param callable $callback Callback функція
     * @param int $priority Пріоритет (за замовчуванням 10)
     * @return void
     */
    public static function add(string $hookName, callable $callback, int $priority = 10): void
    {
        self::getHookManager()->filter($hookName, $callback, $priority);
    }

    /**
     * Застосування filter (фільтра)
     *
     * @param string $hookName Назва хука
     * @param mixed $value Значення для фільтрації
     * @param array<string, mixed> $context Контекст (додаткові дані)
     * @return mixed Відфільтроване значення
     */
    public static function apply(string $hookName, mixed $value = null, array $context = []): mixed
    {
        return self::getHookManager()->apply($hookName, $value, $context);
    }

    /**
     * Видалення filter
     *
     * @param string $hookName Назва хука
     * @param callable|null $callback Callback для видалення (null = видалити всі)
     * @return void
     */
    public static function remove(string $hookName, ?callable $callback = null): void
    {
        self::getHookManager()->remove($hookName, $callback);
    }

    /**
     * Перевірка наявності filter
     *
     * @param string $hookName Назва хука
     * @return bool
     */
    public static function has(string $hookName): bool
    {
        return self::getHookManager()->has($hookName);
    }
}
