<?php

namespace apexl\Io\services;

use apexl\Io\Traits\Appends;
use Psr\Http\Message\ServerRequestInterface;
use Slim\Interfaces\RouteInterface;
use Slim\Routing\RouteContext;
use function apexl\Io\config;

final class HttpPaths
{
    use Appends;

    public RouteInterface $route;
    protected readonly array $currentPathData;

    public function __construct()
    {
        $this->currentPathData = $this->makeCurrentPathData();
    }

    /**
     * Function to set the current path based on the request.
     */
    protected function makeCurrentPathData(): array
    {
        if (!isset($_SERVER['REQUEST_URI'])) {
            return [];
        }

        //account for windows weirdness
        $requestUri = $_SERVER['REQUEST_URI'];
        //if the first 2 chars are slashes, take one off.
        if (str_starts_with((string) $requestUri, "//")) {
            $requestUri = substr((string) $requestUri, 2);
        }
        $pathInfo = pathinfo((string) $requestUri);
        $fullPath = $pathInfo['dirname'] != DIRECTORY_SEPARATOR ? ltrim(
            $pathInfo['dirname'] . DIRECTORY_SEPARATOR . $pathInfo['basename'],
            DIRECTORY_SEPARATOR
        ) : ltrim($pathInfo['dirname'] . $pathInfo['basename'], DIRECTORY_SEPARATOR);
        $pathItems = $pathInfo['dirname'] != DIRECTORY_SEPARATOR ? explode(
            DIRECTORY_SEPARATOR,
            strtok($fullPath, '?')
        ) : [strtok($fullPath, '?')];

        return [
            'full_path_no_query' => $fullPath != DIRECTORY_SEPARATOR ? implode(
                DIRECTORY_SEPARATOR,
                $pathItems
            ) : $fullPath,
            'full_path' => $fullPath,
            'path_items' => $pathItems,
            'no_path_items' => count($pathItems),
            'endpoint' => $pathInfo['basename'],
        ];
    }

    public function getRouteName(ServerRequestInterface $request): ?string
    {
        return $this->getRoute($request)?->getName();
    }

    protected function getRoute(ServerRequestInterface $request): ?RouteInterface
    {
        $routeContext = RouteContext::fromRequest($request);

        return $routeContext->getRoute();
    }

    public function getPath(bool|int $position = false, bool $withQuery = false): string
    {
        if ($position !== false) {
            return $this->currentPathData['path_items'][$position] ?? '';
        } elseif ($withQuery) {
            return $this->currentPathData['full_path'] ?? '';
        }

        return $this->currentPathData['full_path_no_query'] ?? '';

    }

    public function getNumElements(): int
    {
        return count($this->currentPathData['path_items']);
    }

    public function getCurrentRouteName(): ?string
    {
        return $this->route->getName();
    }

    public function getRouteArg(ServerRequestInterface $request, $arg, $default = ''): ?string
    {
        $route = $this->getRoute($request);

        return $route->getArgument($arg, $default);
    }

    public function setCurrentRouteArgs($arg, $value): void
    {
        if (isset($this->route)) {
            $this->route->setArgument($arg, $value);
        }
    }

    public function backendUrl(string $append = ''): string
    {
        return $this->append(config('app.site.backend_domain'), $append);
    }

    public function frontendUrl(string $append = ''): string
    {
        return $this->append(config('app.site.frontend_domain'), $append);
    }

}
