<?php
/**
 * Sanitizer class for input sanitization.
 *
 * @package BoostBot
 * @since   1.0.0
 */

// Prevent direct access
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

/**
 * Class BoostBot_Sanitizer
 *
 * Provides sanitization methods for user input.
 * Wraps WordPress sanitization functions with additional
 * BoostBot-specific sanitization.
 *
 * @since 1.0.0
 */
class BoostBot_Sanitizer {

    /**
     * Sanitize a text field.
     *
     * @param string $value The value to sanitize.
     * @return string The sanitized value.
     */
    public static function text( $value ) {
        return sanitize_text_field( $value );
    }

    /**
     * Sanitize a textarea field.
     *
     * @param string $value The value to sanitize.
     * @return string The sanitized value.
     */
    public static function textarea( $value ) {
        return sanitize_textarea_field( $value );
    }

    /**
     * Sanitize an email address.
     *
     * @param string $value The value to sanitize.
     * @return string The sanitized value.
     */
    public static function email( $value ) {
        return sanitize_email( $value );
    }

    /**
     * Sanitize a URL.
     *
     * @param string $value     The value to sanitize.
     * @param array  $protocols Optional. Allowed protocols. Default null (all).
     * @return string The sanitized value.
     */
    public static function url( $value, $protocols = null ) {
        return esc_url_raw( $value, $protocols );
    }

    /**
     * Sanitize an integer.
     *
     * @param mixed $value The value to sanitize.
     * @return int The sanitized value.
     */
    public static function int( $value ) {
        return intval( $value );
    }

    /**
     * Sanitize a positive integer.
     *
     * @param mixed $value The value to sanitize.
     * @return int The sanitized value (0 or positive).
     */
    public static function absint( $value ) {
        return absint( $value );
    }

    /**
     * Sanitize a float.
     *
     * @param mixed $value The value to sanitize.
     * @return float The sanitized value.
     */
    public static function float( $value ) {
        return floatval( $value );
    }

    /**
     * Sanitize a boolean.
     *
     * @param mixed $value The value to sanitize.
     * @return bool The sanitized value.
     */
    public static function bool( $value ) {
        return filter_var( $value, FILTER_VALIDATE_BOOLEAN );
    }

    /**
     * Sanitize an array of text values.
     *
     * @param array $values The values to sanitize.
     * @return array The sanitized values.
     */
    public static function text_array( $values ) {
        if ( ! is_array( $values ) ) {
            return array();
        }

        return array_map( 'sanitize_text_field', $values );
    }

    /**
     * Sanitize a key (lowercase alphanumeric with dashes and underscores).
     *
     * @param string $value The value to sanitize.
     * @return string The sanitized value.
     */
    public static function key( $value ) {
        return sanitize_key( $value );
    }

    /**
     * Sanitize a slug.
     *
     * @param string $value The value to sanitize.
     * @return string The sanitized value.
     */
    public static function slug( $value ) {
        return sanitize_title( $value );
    }

    /**
     * Sanitize a file name.
     *
     * @param string $value The value to sanitize.
     * @return string The sanitized value.
     */
    public static function filename( $value ) {
        return sanitize_file_name( $value );
    }

    /**
     * Sanitize HTML with limited allowed tags.
     *
     * @param string $value The value to sanitize.
     * @return string The sanitized value.
     */
    public static function html( $value ) {
        return wp_kses_post( $value );
    }

    /**
     * Sanitize a hex color code.
     *
     * @param string $value The value to sanitize.
     * @return string The sanitized value or default.
     */
    public static function hex_color( $value ) {
        // Remove any whitespace
        $value = trim( $value );

        // Check if it's a valid hex color (supports #RGB, #RRGGBB, or #RRGGBBAA with alpha)
        if ( preg_match( '/^#([A-Fa-f0-9]{8}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/', $value ) ) {
            return $value;
        }

        // If no hash, try adding it (supports 8, 6, or 3 digit hex)
        if ( preg_match( '/^([A-Fa-f0-9]{8}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/', $value ) ) {
            return '#' . $value;
        }

        return '';
    }

    /**
     * Sanitize a phone number.
     *
     * @param string $value The value to sanitize.
     * @return string The sanitized value.
     */
    public static function phone( $value ) {
        // Remove everything except digits, plus sign, and dashes
        $value = preg_replace( '/[^\d\+\-]/', '', $value );

        // Limit length
        if ( strlen( $value ) > 20 ) {
            $value = substr( $value, 0, 20 );
        }

        return $value;
    }

    /**
     * Sanitize JSON string.
     *
     * @param mixed $value The value to sanitize.
     * @return string The sanitized JSON string.
     */
    public static function json( $value ) {
        // If already string, validate and return
        if ( is_string( $value ) ) {
            $decoded = json_decode( $value );
            if ( json_last_error() === JSON_ERROR_NONE ) {
                return $value;
            }
            return '{}';
        }

        // If array or object, encode it
        if ( is_array( $value ) || is_object( $value ) ) {
            return wp_json_encode( $value );
        }

        return '{}';
    }

    /**
     * Sanitize an API key.
     *
     * @param string $value The value to sanitize.
     * @return string The sanitized value.
     */
    public static function api_key( $value ) {
        // Only allow alphanumeric, dashes, and underscores
        return preg_replace( '/[^a-zA-Z0-9\-_]/', '', $value );
    }

    /**
     * Sanitize a datetime string.
     *
     * @param string $value  The value to sanitize.
     * @param string $format The expected format. Default 'Y-m-d H:i:s'.
     * @return string The sanitized value or empty string.
     */
    public static function datetime( $value, $format = 'Y-m-d H:i:s' ) {
        $value = sanitize_text_field( $value );

        $d = DateTime::createFromFormat( $format, $value );
        if ( $d && $d->format( $format ) === $value ) {
            return $value;
        }

        // Try common formats
        $formats = array(
            'Y-m-d H:i:s',
            'Y-m-d H:i',
            'Y-m-d',
            'd/m/Y H:i:s',
            'd/m/Y',
        );

        foreach ( $formats as $try_format ) {
            $d = DateTime::createFromFormat( $try_format, $value );
            if ( $d ) {
                return $d->format( $format );
            }
        }

        return '';
    }

    /**
     * Sanitize an array recursively.
     *
     * @param array    $values   The values to sanitize.
     * @param callable $callback The sanitization callback. Default 'sanitize_text_field'.
     * @return array The sanitized values.
     */
    public static function recursive( $values, $callback = 'sanitize_text_field' ) {
        if ( ! is_array( $values ) ) {
            return call_user_func( $callback, $values );
        }

        $sanitized = array();
        foreach ( $values as $key => $value ) {
            $sanitized_key = sanitize_key( $key );

            if ( is_array( $value ) ) {
                $sanitized[ $sanitized_key ] = self::recursive( $value, $callback );
            } else {
                $sanitized[ $sanitized_key ] = call_user_func( $callback, $value );
            }
        }

        return $sanitized;
    }

    /**
     * Sanitize form data based on field types.
     *
     * @param array $data   The data to sanitize.
     * @param array $schema The schema defining field types.
     * @return array The sanitized data.
     *
     * @example
     * $schema = [
     *     'name'  => 'text',
     *     'email' => 'email',
     *     'age'   => 'int',
     *     'bio'   => 'textarea',
     * ];
     */
    public static function form_data( $data, $schema ) {
        $sanitized = array();

        foreach ( $schema as $field => $type ) {
            if ( ! isset( $data[ $field ] ) ) {
                continue;
            }

            $value = $data[ $field ];

            switch ( $type ) {
                case 'text':
                    $sanitized[ $field ] = self::text( $value );
                    break;
                case 'textarea':
                    $sanitized[ $field ] = self::textarea( $value );
                    break;
                case 'email':
                    $sanitized[ $field ] = self::email( $value );
                    break;
                case 'url':
                    $sanitized[ $field ] = self::url( $value );
                    break;
                case 'int':
                case 'integer':
                    $sanitized[ $field ] = self::int( $value );
                    break;
                case 'absint':
                    $sanitized[ $field ] = self::absint( $value );
                    break;
                case 'float':
                    $sanitized[ $field ] = self::float( $value );
                    break;
                case 'bool':
                case 'boolean':
                    $sanitized[ $field ] = self::bool( $value );
                    break;
                case 'html':
                    $sanitized[ $field ] = self::html( $value );
                    break;
                case 'json':
                    $sanitized[ $field ] = self::json( $value );
                    break;
                case 'hex_color':
                    $sanitized[ $field ] = self::hex_color( $value );
                    break;
                case 'phone':
                    $sanitized[ $field ] = self::phone( $value );
                    break;
                case 'key':
                    $sanitized[ $field ] = self::key( $value );
                    break;
                case 'slug':
                    $sanitized[ $field ] = self::slug( $value );
                    break;
                default:
                    $sanitized[ $field ] = self::text( $value );
            }
        }

        return $sanitized;
    }

    /**
     * Strip all HTML tags.
     *
     * @param string $value The value to sanitize.
     * @return string The sanitized value.
     */
    public static function strip_tags( $value ) {
        return wp_strip_all_tags( $value );
    }

    /**
     * Sanitize for output in JavaScript.
     *
     * @param string $value The value to sanitize.
     * @return string The sanitized value.
     */
    public static function js( $value ) {
        return esc_js( $value );
    }

    /**
     * Sanitize for output in HTML attribute.
     *
     * @param string $value The value to sanitize.
     * @return string The sanitized value.
     */
    public static function attr( $value ) {
        return esc_attr( $value );
    }
}










