<?php

declare(strict_types=1);

abstract class AbstractController
{
	protected string $route;
	protected ApiResponse $response;

	protected Session $session;
	protected string $requestUrl;
	protected ?string $requestBody = null;
	protected ?object $jsonBody = null;
	protected ?string $contentType = null;

	/** @var string[] */
	protected array $mandatoryAttributes = [];

	public function __construct(string $url)
	{
		$this->requestUrl = $url;
		$this->response = new ApiResponse();
		$this->session = new Session();
	}

	public function setRequestBody(string $contentType, string $content): void
	{
		$this->requestBody = $content;
		$this->contentType = $contentType;
	}

	public function getResponse(): ApiResponse
	{
		return $this->response;
	}

	public function handle(): void
	{
		if (!$this->validateJsonBody()) {
			$this->response = new ApiJsonResponse(ServerStatus::BAD_REQUEST);
			$this->response->setSuccess(false);
			$this->response->setMessage('The request body has not the required json attributes!');
		}
	}

	protected function getUrlParam(string $name): ?string
	{
		foreach (explode('/', $this->route) as $index => $fragment) {
			if ($fragment === '{' . $name . '}') {
				return explode('/', $this->requestUrl)[$index];
			}
		}

		return null;
	}

	protected function getUrlParamInt(string $name): ?int
	{
		$param = $this->getUrlParam($name);

		return $param !== null ? (int)$param : null;
	}

	public function isUserLoggedIn(): bool
	{
		if (!$this->session->IsLoggedIn()) {
			$this->response = new ApiJsonResponse(ServerStatus::UNAUTHORIZED);

			$this->response->setParameter('success', false);
			$this->response->setMessage('You are not logged in!');

			return false;
		}

		return true;
	}

	public function hasUserPermission(int $userId): bool
	{
		$this->response = new ApiJsonResponse();

		$hasPermission = $this->session->isAdmin() || $this->session->getUserId() === $userId;

		if (!$hasPermission) {
			$this->response->setSuccess(false);
			$this->response->setMessage('You don\'t have the permission!');
			$this->response->setStatus(ServerStatus::UNAUTHORIZED);
		}

		return $hasPermission;
	}

	protected function validateJsonBody(): bool
	{
		if (count($this->mandatoryAttributes) === 0) {
			return true;
		}

		if ($this->contentType === MimeType::JSON && $this->requestBody === null) {
			return false;
		}

		try {
			$json = json_decode($this->requestBody);

			foreach ($this->mandatoryAttributes as $attribute) {
				if (!isset($json->{$attribute})) {
					return false;
				}
			}

			$this->jsonBody = $json;

			return true;
		} catch (Throwable $e) {
			return false;
		}
	}
}