<?php

namespace MintyPHP\Http\Input;

use MintyPHP\Http\Request;

final class RequestInput
{
    /**
     * @param array<string, mixed> $query
     * @param array<string, mixed> $body
     * @param array<string, mixed> $files
     */
    public function __construct(
        private readonly string $method,
        private readonly array $query,
        private readonly array $body,
        private readonly array $files
    ) {
    }

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

    public function isMethod(string ...$methods): bool
    {
        foreach ($methods as $method) {
            if ($this->method === strtoupper(trim($method))) {
                return true;
            }
        }

        return false;
    }

    /**
     * @return array<string, mixed>
     */
    public function queryAll(): array
    {
        return $this->query;
    }

    public function query(string $key, mixed $default = null): mixed
    {
        return array_key_exists($key, $this->query) ? $this->query[$key] : $default;
    }

    public function hasQuery(string $key): bool
    {
        return array_key_exists($key, $this->query);
    }

    public function queryString(string $key, string $default = ''): string
    {
        return trim((string) $this->query($key, $default));
    }

    public function queryInt(string $key, int $default = 0): int
    {
        return (int) $this->query($key, $default);
    }

    /**
     * @return array<string, mixed>
     */
    public function bodyAll(): array
    {
        return $this->body;
    }

    public function body(string $key, mixed $default = null): mixed
    {
        return array_key_exists($key, $this->body) ? $this->body[$key] : $default;
    }

    public function hasBody(string $key): bool
    {
        return array_key_exists($key, $this->body);
    }

    public function bodyString(string $key, string $default = ''): string
    {
        return trim((string) $this->body($key, $default));
    }

    public function bodyInt(string $key, int $default = 0): int
    {
        return (int) $this->body($key, $default);
    }

    /**
     * @return array<int|string, mixed>
     */
    public function bodyArray(string $key): array
    {
        $value = $this->body($key, []);
        return is_array($value) ? $value : [];
    }

    /**
     * @return array<string, mixed>
     */
    public function filesAll(): array
    {
        return $this->files;
    }

    /**
     * @return mixed
     */
    public function file(string $key, mixed $default = null): mixed
    {
        return array_key_exists($key, $this->files) ? $this->files[$key] : $default;
    }

    public function hasFile(string $key): bool
    {
        return array_key_exists($key, $this->files);
    }

    public function wantsJson(): bool
    {
        return Request::wantsJson();
    }
}
