<?php

declare(strict_types=1);

namespace apexl\Io\requestHelper;

use apexl\Io\exceptions\ValidationException;
use Psr\Http\Message\ServerRequestInterface;

abstract readonly class requestHelper
{
    protected array $body;
    protected array $query;

    /**
     * @throws ValidationException
     */
    public function __construct(protected ServerRequestInterface $request)
    {
        $body = $request->getParsedBody();

        $this->query = $request->getQueryParams();

        $this->body = (array) ($body ?? []);

        $this->validate();
    }

    /**
     * @noinspection PhpDocRedundantThrowsInspection May be thrown in child classes
     * @throws ValidationException
     */
    public function validate(): void {}

    /**
     * @throws ValidationException
     */
    public function validateSame(string $key1, string $key2, ?string $message = null, array|null $bucket = null): void
    {
        $bucket = $bucket ?? $this->body;
        $value1 = $bucket[$key1];
        $value2 = $bucket[$key2];

        if ($value1 !== $value2) {
            $message = $message ?? sprintf('%s does not match %s', $key1, $key2);

            throw new ValidationException($message);
        }

    }

    protected function bodyParam($name, $default = null)
    {
        return $this->body[$name] ?? $default;
    }

    protected function query($name, $default = null)
    {
        return $this->query[$name] ?? $default;
    }

    /**
     * @throws ValidationException
     */
    protected function requireBody(string $key, ?string $message = null): void
    {
        $this->require($key, $message, $this->body);
    }

    /**
     * @throws ValidationException
     */
    protected function require(string $key, ?string $message = null, array|null $bucket = null): void
    {
        $bucket = $bucket ?? $this->body;

        if (empty($bucket[$key])) {
            $message = $message ?? sprintf('%s is required', $key);

            throw new ValidationException($message);
        }
    }

    /**
     * @throws ValidationException
     */
    protected function requireQuery(string $key, ?string $message = null): void
    {
        $this->require($key, $message, $this->query);
    }
}
