<?php

namespace classes;

class ValueSanitiser
{
    /**
     * Sanitizes and trims a given string value.
     *
     * @param string $value The input string to be sanitized.
     * @return string The sanitized and trimmed string.
     */
    public static function string(string $value): string
    {
        $value = trim($value);

        return filter_var($value, FILTER_SANITIZE_STRING);
    }

    /**
     * Sanitizes the provided integer value by trimming whitespace
     * and removing all non-numeric characters.
     *
     * @param int $value The integer value to sanitize.
     * @return int The sanitized integer value.
     */
    public static function int(int $value): int
    {
        return filter_var($value, FILTER_SANITIZE_NUMBER_INT);
    }

    /**
     * Sanitizes the provided float value by trimming whitespace
     * and removing all invalid characters for a float number.
     *
     * @param float $value The float value to sanitize.
     * @return float The sanitized float value.
     */
    public static function float(float $value): float
    {
        return filter_var($value, FILTER_SANITIZE_NUMBER_FLOAT);
    }

    /**
     * Filters and validates a boolean value.
     *
     * @param bool $value The boolean value to be filtered and validated.
     * @return bool Returns the filtered and validated boolean value.
     */
    public static function bool(bool $value): bool
    {
        $value = trim($value);

        return filter_var($value, FILTER_VALIDATE_BOOLEAN);
    }

    /**
     * Filters and validates an email address.
     *
     * @param string $value The email address to be filtered and validated.
     * @return string Returns the validated email address, or an empty string if invalid.
     */
    public static function email(string $value): string
    {
        $value = trim($value);

        return filter_var($value, FILTER_VALIDATE_EMAIL);
    }

    /**
     * Validates and filters a URL.
     *
     * @param string $value The URL string to be validated and filtered.
     * @return string Returns the validated and filtered URL string.
     */
    public static function url(string $value): string
    {
        $value = trim($value);

        return filter_var($value, FILTER_VALIDATE_URL);
    }

    /**
     * Filters and validates an IP address string.
     *
     * @param string $value The IP address string to be filtered and validated.
     * @return string Returns the filtered and validated IP address string.
     */
    public static function ip(string $value): string
    {
        $value = trim($value);

        return filter_var($value, FILTER_VALIDATE_IP);
    }

    /**
     * Sanitizes a string by removing or encoding special characters to prevent potential security risks like XSS attacks.
     *
     * @param string $value The input string to sanitize.
     * @return string The sanitized string with special characters handled appropriately.
     */
    public static function fullSpecialChars(string $value): string
    {
        $value = trim($value);

        return filter_var($value, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
    }

    /**
     * Sanitizes an array by recursively processing its values based on their types to remove or encode potentially harmful content.
     *
     * @param array $array The input array to sanitize, which may include nested arrays.
     * @return array The sanitized array with all values processed according to their data types.
     */
    public static function array(array $array): array
    {
        $sanitisedArray = [];
        foreach ($array as $key => $value)
        {
            // Sanitises recursively if value is an array
            if (is_array($value))
            {
                $sanitisedArray[$key] = self::array($value);
                continue;
            }

            // Only trims strings
            $value = is_string($value) ? trim($value) : $value;

            // Determines filter type based on the type of the value
            switch (gettype($value)) {
                case 'integer':
                    $filterType = FILTER_SANITIZE_NUMBER_INT;
                    break;
                case 'double':
                    $filterType = FILTER_SANITIZE_NUMBER_FLOAT;
                    break;
                case 'boolean':
                    $filterType = FILTER_VALIDATE_BOOLEAN;
                    break;
                default:
                    $filterType = FILTER_SANITIZE_SPECIAL_CHARS;
                    break;
            }


            $filterFlags = 0;
            if ($filterType === FILTER_SANITIZE_NUMBER_INT)
            {
                $filterFlags = FILTER_FLAG_ALLOW_OCTAL;
            }
            else if ($filterType === FILTER_SANITIZE_NUMBER_FLOAT)
            {
                $filterFlags = FILTER_FLAG_ALLOW_FRACTION;
            }
            else if ($filterType === FILTER_VALIDATE_BOOLEAN)
            {
                $filterFlags = FILTER_NULL_ON_FAILURE;
            }
            else if ($filterType === FILTER_SANITIZE_SPECIAL_CHARS)
            {
                $filterFlags = FILTER_FLAG_ENCODE_LOW | FILTER_FLAG_ENCODE_HIGH;
            }

            $sanitisedArray[$key] = filter_var($value, $filterType, $filterFlags);;
        }

        return $sanitisedArray;
    }
}
