<?php
namespace Incoviba\Middleware;

use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Psr\Log\LoggerInterface;
use Incoviba\Exception\MissingAuthorizationHeader;
use Incoviba\Service;

class API
{
    public function __construct(protected ResponseFactoryInterface $responseFactory,
                                protected LoggerInterface $logger,
                                protected Service\API $apiService,
                                protected Service\Login $loginService,
                                protected array $permittedPaths,
                                protected array $simplePaths,
                                protected string $key) {}

    public function __invoke(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        try {
            $key = $this->apiService->getKey($request);
        } catch (MissingAuthorizationHeader $exception) {
            return $this->responseFactory->createResponse(401);
        }
        if ($this->validateSimpleKey($request, $key)) {
            return $handler->handle($request);
        }
        if ($this->validate($request, $key)) {
            return $handler->handle($request);
        }
        return $this->responseFactory->createResponse(403);
    }
    protected function validate(ServerRequestInterface $request, $incoming_key): bool
    {
        $selector = null;
        $token = null;
        if (str_contains($incoming_key, $this->loginService->getSeparator())) {
            list($incoming_key, $selector, $token) = explode($this->loginService->getSeparator(), $incoming_key, 3);
            if (!$this->loginService->isIn($selector, $token)) {
                return false;
            }
        }
        if (!$this->loginService->isIn($selector, $token) and !$this->validPermitted($request)) {
            return false;
        }
        return $incoming_key === md5($this->key);
    }
    protected function validateSimpleKey(ServerRequestInterface $request, $incoming_key): bool
    {
        return $incoming_key === md5($this->key) and $this->noComplexKeyNeeded($request);
    }
    protected function noComplexKeyNeeded(ServerRequestInterface $request): bool
    {
        $uri = $request->getUri();
        return in_array($uri->getPath(), $this->simplePaths);
    }
    protected function validPermitted(ServerRequestInterface $request): bool
    {
        $uri = $request->getUri();
        return in_array($uri->getPath(), $this->permittedPaths);
    }
}
