<?php
declare(strict_types=1);

namespace EHxMe\Services;

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

/**
 * Request
 * A helper class for handling Form Request Data in WordPress.
 */
class Request
{
    protected array $data;

    public function __construct()
    {
        // Initialize request data from global variables
        $this->data = [
            'post'   => wp_unslash($_POST),
            'get'    => wp_unslash($_GET),
            'cookie' => wp_unslash($_COOKIE),
        ];
    }

    /**
     * Verify nonce and check permissions
     *
     * @param string $action The nonce action name
     * @param string $nonceName The nonce parameter name (default: '__ehxme_nonce')
     * @param bool $requireLogin Whether to require user to be logged in
     * @return bool|void Returns true if verified, dies with error if not
     */
    public function verify($action, $nonceName = '__ehxme_nonce', $requireLogin = false) 
    {
        $message = null;

        if (is_admin() && !wp_doing_ajax()) {
            // Your admin-only logic here
            if (!current_user_can('manage_options')) {
                $message = esc_html__('You do not have sufficient permissions to access this page.', 'ehx-members');
            }
        }

        // Check if login is required
        if ($requireLogin && !is_user_logged_in()) {
            $message = esc_html__('You must be logged in to perform this action.', 'ehx-members');
        }

        // Verify nonce
        if (!isset($_POST[$nonceName]) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST[$nonceName])), $action)) {
            $message = esc_html__('Nonce verification failed.', 'ehx-members');
        }

        if(!empty($message)) {
            if (wp_doing_ajax()) {
                wp_die(
                    wp_json_encode(array('success' => false, 'message' => $message)),
                    esc_html__('Plugin Error', 'ehx-members'),
                    array(
                        'response' => 403,
                        'exit'     => true
                    )
                );
            }
            else {
                wp_die(esc_html($message), esc_html__('Plugin Error', 'ehx-members'), ['response' => 403]);
            }
        }

        return true;
    }

    /**
     * Get a sanitized value from the request data.
     *
     * @param string $key The key to retrieve.
     * @param mixed $default The default value if the key does not exist.
     * @return mixed The sanitized value or default.
     */
    public function input($key, $default = null, $sanitize = true)
    {
        foreach ($this->data as $values) {
            if (isset($values[$key])) {
                return $this->sanitize($values[$key], $sanitize);
            }
        }
        return $default;
    }

    /**
     * Get all request data of a specific type (e.g., POST, GET).
     *
     * @param string $type The request type (e.g., 'post', 'get').
     * @return array The sanitized array of request data.
     */
    public function all($type = 'post')
    {
        $data = [];
        if (isset($this->data[$type])) {
            foreach ($this->data[$type] as $key => $value) {
                $data[$key] = $this->sanitize($value);
            }
        }
        return $data;
    }

    /**
     * Check if a key exists in the request data.
     *
     * @param string $key The key to check.
     * @return bool True if the key exists, false otherwise.
     */
    public function has($key)
    {
        foreach ($this->data as $values) {
            if (isset($values[$key])) {
                return true;
            }
        }
        return false;
    }

    /**
     * Check if a key exists and is not empty in the request data.
     *
     * @param string $key The key to check.
     * @return bool True if the key exists and is not empty, false otherwise.
     */
    public function filled($key)
    {
        return !empty($this->input($key));
    }

    /**
     * Determine if a key's value is equivalent to a boolean "true".
     *
     * @param string $key The key to check.
     * @return int 
     */
    public function integer($key, $default = null): int
    {
        return (int) $this->input($key, $default);
    }

    /**
     * Determine if a key's value is equivalent to a boolean "true".
     *
     * @param string $key The key to check.
     * @return bool True if the value represents a boolean "true", false otherwise.
     */
    public function boolean($key)
    {
        return in_array($this->input($key), ['on', 1, 'yes', true], true);
    }

    /**
     * Get a file from the request.
     *
     * @param string $key The key for the file input.
     * @return array|null The file data if it exists, null otherwise.
     */
    public function file($key)
    {
        return $this->data['files'][$key] ?? null;
    }

    /**
     * Check if a file exists in the request.
     *
     * @param string $key The key for the file input.
     * @return bool True if the file exists, false otherwise.
     */
    public function hasFile($key)
    {
        return isset($this->data['files'][$key]);
    }

    /**
     * Sanitize a value or array of values.
     *
     * @param mixed $value The value to sanitize.
     * @param bool $sanitize The value to sanitize.
     * @return mixed The sanitized value or array.
     */
    public function sanitize($value, $sanitize = true)
    {
        if (is_array($value)) {
            return array_map([$this, 'sanitize'], $value); // Recursive sanitization for arrays
        }
        
        $value = wp_unslash($value);
        if ($sanitize) {
            $value = sanitize_text_field($value);
        }
        return $value;
    }

    /**
     * Get $_GET data and sanitize a value or array of values.
     *
     * @param  mixed $key
     * @param  mixed $default
     */
    public static function getInput($key, $default = null)
    {
        return isset($_GET[$key]) ? sanitize_text_field(wp_unslash($_GET[$key])) : $default;
    }

    /**
     * Get $_POST data and sanitize a value or array of values.
     *
     * @param  mixed $key
     * @param  mixed $default
     */
    public static function postInput($key, $default = null)
    {
        $value = isset($_POST[$key]) ? wp_unslash($_POST[$key]) : $default;

        if (is_array($value)) {
            return array_map('sanitize_text_field', $value); // Recursively sanitize each item in the array
        }

        return sanitize_text_field($value);;
    }

}
