<?php

namespace EasyLinkAutomations\HTTP\Request;

if (!defined('ABSPATH')) {
    exit;
}

/**
 * HTTP request abstraction.
 *
 * Merges POST, GET, and JSON body into a single data store.
 * Provides get(), has(), and magic property access for convenience.
 */
final class Request
{
    private array $data;

    public function __construct()
    {
        // WordPress applies wp_magic_quotes() to $_POST/$_GET, adding slashes.
        // wp_unslash() removes those before we store or JSON-decode any values.
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing -- Nonce is verified in AuthMiddleware before controller dispatch.
        $this->data = array_merge(
            wp_unslash($_GET),
            wp_unslash($_POST)
        );

        // Also try to decode JSON body (for REST API requests)
        $contentType = isset($_SERVER['CONTENT_TYPE'])
            ? sanitize_text_field(wp_unslash($_SERVER['CONTENT_TYPE']))
            : '';
        if (str_contains($contentType, 'application/json')) {
            $rawBody = file_get_contents('php://input');
            if ($rawBody) {
                $json = json_decode($rawBody, true);
                if (is_array($json)) {
                    $this->data = array_merge($this->data, $json);
                }
            }
        }
    }

    /**
     * Get a value from the request data.
     */
    public function get(string $key, mixed $default = null): mixed
    {
        return $this->data[$key] ?? $default;
    }

    /**
     * Check if a key exists in the request data.
     */
    public function has(string $key): bool
    {
        return isset($this->data[$key]) && $this->data[$key] !== '';
    }

    /**
     * Get all request data.
     */
    public function all(): array
    {
        return $this->data;
    }

    /**
     * Magic property getter — allows $request->_ajax_nonce syntax.
     */
    public function __get(string $key): mixed
    {
        return $this->data[$key] ?? null;
    }

    /**
     * Magic isset check.
     */
    public function __isset(string $key): bool
    {
        return isset($this->data[$key]);
    }
}
