<?php

namespace Licenzo\Framework\Http\Middleware;

if (!defined('ABSPATH')) {
    exit;
}

use Closure;
use Licenzo\Framework\Http\Request;
use Licenzo\Framework\Http\Response;

/**
 * Wraps a middleware instance with a pre-bound parameter list.
 *
 * Routes may declare middleware with the Laravel-style `alias:param1,param2`
 * syntax (e.g. 'throttle:activation'). The parameters are lookup data
 * for the middleware's handle() method — they are NOT request-scoped
 * data, so a single middleware instance may be reused across many
 * routes, each with its own parameter binding.
 *
 * MiddlewareRegistry::resolve() returns an instance of this wrapper
 * when the alias carries parameters. The wrapper forwards handle()
 * and terminate() calls to the underlying middleware, appending
 * the bound parameters to handle().
 *
 * Design rationale:
 *   - Keeps the underlying middleware a plain singleton; parameters
 *     live outside the instance so cross-route reuse is safe.
 *   - Preserves Application::terminate()'s expectation that tracked
 *     middleware expose terminate(Request, Response): void.
 *   - Zero changes required in Pipeline — it already treats
 *     parameterized entries as object pipes with the default
 *     [$request, $next] argument set.
 */
class ParameterizedMiddleware
{
    protected object $middleware;

    /**
     * @var array<int,string>
     */
    protected array $parameters;

    /**
     * @param array<int,string> $parameters
     */
    public function __construct(object $middleware, array $parameters)
    {
        $this->middleware = $middleware;
        $this->parameters = $parameters;
    }

    public function handle(Request $request, Closure $next)
    {
        return $this->middleware->handle($request, $next, ...$this->parameters);
    }

    public function terminate(Request $request, Response $response): void
    {
        if (method_exists($this->middleware, 'terminate')) {
            $this->middleware->terminate($request, $response);
        }
    }

    /**
     * Expose the underlying middleware for debugging or introspection.
     * Not part of the middleware contract; callers should avoid
     * relying on this for runtime behavior.
     */
    public function unwrap(): object
    {
        return $this->middleware;
    }
}
