<?php

namespace Core\System;

class HookManager
{
    private static array $actions = [];
    private static array $filters = [];
    private static array $events = [];
    private static bool $stopPropagation = false;

    /**
     * Register Action Hook
     */
    public static function addAction(string $hook, callable $callback, int $priority = 10)
    {
        self::$actions[$hook][$priority][] = $callback;
        ksort(self::$actions[$hook]);
    }

    /**
     * Execute an Action
     */
    public static function doAction(string $hook, ...$params)
    {
        if (!isset(self::$actions[$hook])) {
            return;
        }

        foreach (self::$actions[$hook] as $priority => $callbacks) {
            foreach ($callbacks as $callback) {
                if (self::$stopPropagation) {
                    return;
                }
                call_user_func_array($callback, $params);
            }
        }
    }

    /**
     * Register a Filter
     */
    public static function addFilter(string $hook, callable $callback, int $priority = 10)
    {
        self::$filters[$hook][$priority][] = $callback;
        ksort(self::$filters[$hook]);
    }

    /**
     * Apply filter chain
     */
    public static function applyFilter(string $hook, $value, ...$params)
    {
        if (!isset(self::$filters[$hook])) {
            return $value;
        }

        foreach (self::$filters[$hook] as $priority => $callbacks) {
            foreach ($callbacks as $callback) {
                if (self::$stopPropagation) {
                    return $value;
                }
                $value = call_user_func_array($callback, array_merge([$value], $params));
            }
        }

        return $value;
    }

    /**
     * Register an Event
     */
    public static function addEvent(string $event, callable $callback)
    {
        self::$events[$event][] = $callback;
    }

    /**
     * Trigger an Event
     */
    public static function triggerEvent(string $event, ...$params)
    {
        if (!isset(self::$events[$event])) {
            return;
        }

        foreach (self::$events[$event] as $callback) {
            if (self::$stopPropagation) {
                return;
            }
            call_user_func_array($callback, $params);
        }
    }

    /**
     * Stop propagation of hooks
     */
    public static function stop()
    {
        self::$stopPropagation = true;
    }

    /**
     * Reset stop flag
     */
    public static function resume()
    {
        self::$stopPropagation = false;
    }

    /**
     * Allow Plugins to inject their hooks
     */
    public static function loadPluginHooks(string $pluginPath)
    {
        $hookFile = rtrim($pluginPath, '/') . '/hooks.php';
        if (file_exists($hookFile)) {
            include $hookFile;
        }
    }
}

