<?php

/**
 * Клас для роботи з actions (подіями) у стилі 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;

/**
 * Статичний клас для роботи з actions
 *
 * Приклад використання:
 * Action::add('init', function() { echo 'Init hook'; });
 * Action::do('init');
 */
final class Action
{
    /**
     * Отримання екземпляра HookManager
     *
     * @return HookManagerInterface
     */
    private static function getHookManager(): HookManagerInterface
    {
        static $hookManager = null;

        if ($hookManager === null) {
            // Спробуємо отримати з контейнера
            try {
                $container = App::container();
                if ($container->has(HookManagerInterface::class)) {
                    $hookManager = $container->make(HookManagerInterface::class);
                    if ($hookManager instanceof HookManagerInterface) {
                        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;
    }

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

    /**
     * Виконання action (події)
     *
     * @param string $hookName Назва хука
     * @param mixed ...$args Аргументи для передачі в callback
     * @return void
     */
    public static function do(string $hookName, mixed ...$args): void
    {
        self::getHookManager()->dispatch($hookName, ...$args);
    }

    /**
     * Видалення action
     *
     * @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);
    }

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