<?php

namespace apexl\Io\utilityIncludes;

use apexl\Io\enums\HttpMethod;
use apexl\Io\modules\user\interfaces\PermissionInterface;
use Psr\Http\Server\MiddlewareInterface;

final class Route
{
    /** @var array<int,MiddlewareInterface> */
    private readonly array $middleware;

    /** @var string|array|callable $callable */
    private readonly mixed $callable;

    public function __construct(
        private readonly string $name,
        private readonly string $pattern,
        string|array|callable $callable,
        private readonly HttpMethod $method,
        private array $args = [],
        array $middleware = []
    ) {
        $this->callable = $callable;
        $this->middleware = $middleware;
    }

    public function getMiddleware(): array
    {
        return $this->middleware;
    }

    public function setArg(string $arg, mixed $value): void
    {
        $this->args[$arg] = $value;
    }

    public function getArgs(): array
    {
        return $this->args;
    }

    public function getName(): string
    {
        return $this->name;
    }

    public function getFullyQualifiedPattern(
        array $replacements = [],
        bool $stripTags = true
    ): string {
        return sprintf('%s/%s', config('app.site.backend_domain'), $this->getPattern($replacements, $stripTags));
    }

    public function getPattern(
        array $replacements = [],
        bool $stripTags = true
    ): string|false {
        $pattern = $this->pattern;
        if ($stripTags) {
            return preg_replace('#/\{[^}]+\}(/|$)#', '/', $pattern);
        }

        foreach ($replacements as $token => $value) {
            $pattern = str_replace(['{' . $token . '}', '[', ']'], [$value, '', ''], $pattern);
        }

        return $pattern;
    }


    public function getCallable(): string|array|callable
    {
        return $this->callable;
    }

    public function getMethod(): HttpMethod
    {
        return $this->method;
    }

    public function getPermission(): ?PermissionInterface
    {
        $permission = $this->getArg('permission');

        if ($permission) {
            return unserialize($permission);
        }

        return null;
    }

    public function getArg(string $arg)
    {
        return $this->args[$arg] ?? null;
    }
}
