<?php

namespace Licenzo\Framework\Http\Middleware;

use Licenzo\Framework\Foundation\Application;

/**
 * Middleware Registry for centralized middleware management
 */
class MiddlewareRegistry
{
    /**
     * The application instance.
     */
    protected Application $app;

    /**
     * Registered middleware aliases.
     */
    protected array $middleware = [];

    /**
     * Middleware groups.
     */
    protected array $alias = [];

    protected array $instances = [];

    /**
     * Create a new middleware registry.
     */
    public function __construct(Application $app)
    {
        $this->app = $app;
    }

    /**
     * Register a middleware alias.
     */
    public function register($middleware, $alias = null)
    {
        if (is_array($middleware)) {

            foreach ($middleware as $alias => $m) {
                // check if indexed array, if indexed, there is no alias
                if (is_numeric($alias)) {
                    $this->register($m);
                } else {
                    $this->register($m, $alias);
                }
            }

            return $this;
        }

        if (!isset($this->middleware[$middleware])) {
            $this->middleware[$middleware] = $middleware;
        }

        if ($alias) {
            $this->alias[$alias] = $middleware;
        }

        return $this;
    }

    public function get($middleware)
    {
        if (!$this->has($middleware)) {
            return null;
        }

        if (isset($this->instances[$middleware])) {
            return $this->instances[$middleware];
        }

        if (isset($this->alias[$middleware])) {
            return $this->alias[$middleware];
        }

        return $this->middleware[$middleware];
    }

    /**
     * Check if a middleware alias exists.
     */
    public function has($middleware): bool
    {

        if (isset($this->instances[$middleware])) {
            return true;
        }

        if (isset($this->alias[$middleware])) {
            return true;
        }

        if (isset($this->middleware[$middleware])) {
            return true;
        }

        return false;
    }

    public function resolve($middleware)
    {
        // Parse Laravel-style `alias:param1,param2` form. The base alias
        // is looked up in the registry; parameters are passed through to
        // the middleware's handle() method via ParameterizedMiddleware.
        //
        // An instance is cached per BASE alias (not per parameter set)
        // so that, e.g., `throttle:activation` and `throttle:webhook`
        // share a single RateLimit instance with different param
        // bindings.
        $parameters = [];
        $baseAlias  = $middleware;

        if (is_string($middleware) && ($colonPos = strpos($middleware, ':')) !== false) {
            $baseAlias = substr($middleware, 0, $colonPos);
            $paramStr  = substr($middleware, $colonPos + 1);
            if ($paramStr !== '') {
                $parameters = array_map('trim', explode(',', $paramStr));
            }
        }

        if (!$this->has($baseAlias)) {
            return null;
        }

        if (!isset($this->instances[$baseAlias])) {
            $this->instances[$baseAlias] = $this->app->make($this->get($baseAlias));
        }

        $instance = $this->instances[$baseAlias];

        if (empty($parameters)) {
            return $instance;
        }

        return new ParameterizedMiddleware($instance, $parameters);
    }

    public function all()
    {
        return $this->middleware;
    }
}
