<?php
/**
 * Extra Config Security Layer
 * Handles all security validations, sanitization, and permission checks
 *
 * @package AIAutoTool
 * @subpackage ExtraConfig
 * @since 1.0.0
 */

if ( ! defined( 'ABSPATH' ) ) exit; // Thoát nếu truy cập trực tiếp

/**
 * Security layer for Extra Config settings
 */
class Aiautotool_Extra_Config_Security {
    
    /**
     * Nonce action name
     *
     * @var string
     */
    const NONCE_ACTION = 'aiautotool_extra_config_action';
    
    /**
     * Nonce field name
     *
     * @var string
     */
    const NONCE_FIELD = 'aiautotool_extra_config_nonce';
    
    /**
     * Required capability
     *
     * @var string
     */
    const REQUIRED_CAPABILITY = 'manage_options';
    
    /**
     * Allowed setting keys with their types
     *
     * @var array
     */
    private $allowed_settings = array(
        // Editor settings
        'tool-blockcomment'    => 'boolean',
        'tool-edit1'           => 'boolean',
        'tool-edit11'          => 'boolean',
        'tool-widget1'         => 'boolean',
        
        // Upload/Update settings
        'tool-upload1'         => 'boolean',
        'tool-upload2'         => 'boolean',
        'tool-upload3'         => 'boolean',
        'tool-upload4'         => 'boolean',
        
        // Management settings
        'tool-mana1'           => 'boolean',
        'tool-mana2'           => 'boolean',
        'tool-mana3'           => 'boolean',
        
        // Hide tools settings
        'tool-hiden1'          => 'boolean',
        'tool-hiden2'          => 'boolean',
        'tool-hiden3'          => 'boolean',
        'tool-hiden4'          => 'boolean',
        'tool-hiden5'          => 'boolean',
        'tool-hiden6'          => 'boolean',
        'tool-hiden7'          => 'boolean',
        'tool-hiden8'          => 'boolean',
        'tool-hiden9'          => 'boolean',
        'tool-hiden10'         => 'boolean',
        'tool-hifox1'          => 'boolean',
        
        // Speed optimization
        'speed-off1'           => 'boolean',
        'speed-off2'           => 'boolean',
        'speed-off3'           => 'boolean',
        'speed-off4'           => 'boolean',
        'speed-link1'          => 'boolean',
        'speed-link2'          => 'boolean',
        'speed-zip1'           => 'boolean',
        'speed-data1'          => 'boolean',
        'speed-data11'         => 'integer',
        'speed-data2'          => 'boolean',
        'speed-data21'         => 'integer',
        
        // Security settings
        'scuri-off1'           => 'boolean',
        'scuri-off2'           => 'boolean',
        'scuri-off3'           => 'boolean',
        'scuri-off4'           => 'boolean',
        'scuri-off5'           => 'boolean',
        'scuri-off6'           => 'boolean',
        'scuri-verof1'         => 'boolean',
        'scuri-verof2'         => 'boolean',
        'scuri-sql1'           => 'boolean',
    );
    
    /**
     * Check if user has required permissions
     *
     * @return bool
     */
    public function can_manage_settings() {
        return current_user_can(self::REQUIRED_CAPABILITY);
    }
    
    /**
     * Verify user permissions and die if insufficient
     *
     * @return void
     */
    public function verify_permissions() {
        if (!$this->can_manage_settings()) {
            wp_die(
                esc_html__('You do not have permission to perform this action.', 'ai-auto-tool'),
                esc_html__('Permission Denied', 'ai-auto-tool'),
                array('response' => 403)
            );
        }
    }
    
    /**
     * Create nonce for forms
     *
     * @return string
     */
    public function create_nonce() {
        return wp_create_nonce(self::NONCE_ACTION);
    }
    
    /**
     * Verify nonce from request
     *
     * @param string $nonce Nonce to verify
     * @return bool
     */
    public function verify_nonce($nonce = '') {
        if (empty($nonce)) {
            $nonce = isset($_REQUEST[self::NONCE_FIELD]) ? $_REQUEST[self::NONCE_FIELD] : '';
        }
        
        return wp_verify_nonce($nonce, self::NONCE_ACTION);
    }
    
    /**
     * Verify AJAX nonce
     *
     * @param string $query_arg Optional. Key to check for nonce in `$_REQUEST`
     * @return bool|int
     */
    public function verify_ajax_nonce($query_arg = 'nonce') {
        return check_ajax_referer(self::NONCE_ACTION, $query_arg, false);
    }
    
    /**
     * Validate a single setting
     *
     * @param string $key   Setting key
     * @param mixed  $value Setting value
     * @return WP_Error|mixed Validated value or WP_Error on failure
     */
    public function validate_setting($key, $value) {
        // Check if key is allowed
        if (!isset($this->allowed_settings[$key])) {
            return new WP_Error(
                'invalid_setting_key',
                sprintf(
                    /* translators: %s: setting key */
                    __('Invalid setting key: %s', 'ai-auto-tool'),
                    $key
                )
            );
        }
        
        $type = $this->allowed_settings[$key];
        
        return $this->validate_by_type($value, $type, $key);
    }
    
    /**
     * Validate value by type
     *
     * @param mixed  $value Value to validate
     * @param string $type  Expected type
     * @param string $key   Setting key for context
     * @return WP_Error|mixed Validated value or WP_Error on failure
     */
    private function validate_by_type($value, $type, $key) {
        switch ($type) {
            case 'boolean':
                return $this->validate_boolean($value, $key);
                
            case 'integer':
                return $this->validate_integer($value, $key);
                
            case 'string':
                return $this->validate_string($value, $key);
                
            case 'text':
                return $this->validate_text($value, $key);
                
            default:
                return new WP_Error(
                    'unknown_type',
                    sprintf(
                        /* translators: %s: type name */
                        __('Unknown validation type: %s', 'ai-auto-tool'),
                        $type
                    )
                );
        }
    }
    
    /**
     * Validate boolean value
     *
     * @param mixed  $value Value to validate
     * @param string $key   Setting key
     * @return int 1 or 0
     */
    private function validate_boolean($value, $key) {
        return (int) $value === 1 ? 1 : 0;
    }
    
    /**
     * Validate integer value
     *
     * @param mixed  $value Value to validate
     * @param string $key   Setting key
     * @return WP_Error|int Validated integer or WP_Error
     */
    private function validate_integer($value, $key) {
        if (!is_numeric($value)) {
            return new WP_Error(
                'invalid_integer',
                sprintf(
                    /* translators: %s: setting key */
                    __('Setting %s must be a number', 'ai-auto-tool'),
                    $key
                )
            );
        }
        
        $int_value = (int) $value;
        
        // Additional validation for specific keys
        if (strpos($key, 'speed-data') !== false) {
            if ($int_value < 1 || $int_value > 100) {
                return new WP_Error(
                    'out_of_range',
                    sprintf(
                        /* translators: %s: setting key */
                        __('Setting %s must be between 1 and 100', 'ai-auto-tool'),
                        $key
                    )
                );
            }
        }
        
        return $int_value;
    }
    
    /**
     * Validate string value
     *
     * @param mixed  $value Value to validate
     * @param string $key   Setting key
     * @return string Validated string
     */
    private function validate_string($value, $key) {
        return sanitize_text_field($value);
    }
    
    /**
     * Validate text value (multiline)
     *
     * @param mixed  $value Value to validate
     * @param string $key   Setting key
     * @return string Validated text
     */
    private function validate_text($value, $key) {
        return sanitize_textarea_field($value);
    }
    
    /**
     * Sanitize all settings
     *
     * @param array $settings Settings to sanitize
     * @return array Sanitized settings
     */
    public function sanitize_settings($settings) {
        if (!is_array($settings)) {
            return array();
        }
        
        $sanitized = array();
        
        foreach ($settings as $key => $value) {
            $validated = $this->validate_setting($key, $value);
            
            // Skip invalid settings
            if (is_wp_error($validated)) {
                continue;
            }
            
            $sanitized[$key] = $validated;
        }
        
        return $sanitized;
    }
    
    /**
     * Validate all settings and return errors
     *
     * @param array $settings Settings to validate
     * @return array Array with 'valid' and 'errors' keys
     */
    public function validate_settings($settings) {
        $errors = array();
        $valid_settings = array();
        
        if (!is_array($settings)) {
            $errors[] = __('Settings must be an array', 'ai-auto-tool');
            return array(
                'valid'  => false,
                'errors' => $errors,
                'settings' => array()
            );
        }
        
        foreach ($settings as $key => $value) {
            $validated = $this->validate_setting($key, $value);
            
            if (is_wp_error($validated)) {
                $errors[] = $validated->get_error_message();
            } else {
                $valid_settings[$key] = $validated;
            }
        }
        
        return array(
            'valid'    => empty($errors),
            'errors'   => $errors,
            'settings' => $valid_settings
        );
    }
    
    /**
     * Sanitize SQL table name
     *
     * @param string $table_name Table name to sanitize
     * @return string Sanitized table name
     */
    public function sanitize_table_name($table_name) {
        global $wpdb;
        
        // Only allow WordPress core tables
        $allowed_tables = array(
            $wpdb->posts,
            $wpdb->postmeta,
            $wpdb->comments,
            $wpdb->commentmeta,
        );
        
        if (!in_array($table_name, $allowed_tables, true)) {
            return '';
        }
        
        return $table_name;
    }
    
    /**
     * Escape output for HTML context
     *
     * @param string $text Text to escape
     * @return string Escaped text
     */
    public function escape_html($text) {
        return esc_html($text);
    }
    
    /**
     * Escape output for attribute context
     *
     * @param string $text Text to escape
     * @return string Escaped text
     */
    public function escape_attr($text) {
        return esc_attr($text);
    }
    
    /**
     * Escape output for URL context
     *
     * @param string $url URL to escape
     * @return string Escaped URL
     */
    public function escape_url($url) {
        return esc_url($url);
    }
    
    /**
     * Escape output for JavaScript context
     *
     * @param string $text Text to escape
     * @return string Escaped text
     */
    public function escape_js($text) {
        return esc_js($text);
    }
    
    /**
     * Strip all tags and scripts for CSS output
     *
     * @param string $css CSS code
     * @return string Sanitized CSS
     */
    public function sanitize_css($css) {
        // Remove any HTML tags
        $css = wp_strip_all_tags($css);
        
        // Remove any JavaScript
        $css = preg_replace('/<script\b[^>]*>(.*?)<\/script>/is', '', $css);
        
        return $css;
    }
    
    /**
     * Validate and sanitize custom code
     * WARNING: This is dangerous and should be used with extreme caution
     *
     * @param string $code Custom code
     * @param string $type Type of code (css, js, html)
     * @return WP_Error|string Sanitized code or error
     */
    public function sanitize_custom_code($code, $type = 'css') {
        // Only administrators can save custom code
        if (!current_user_can('manage_options')) {
            return new WP_Error(
                'insufficient_permissions',
                __('Only administrators can save custom code', 'ai-auto-tool')
            );
        }
        
        switch ($type) {
            case 'css':
                // Remove any script tags
                $code = preg_replace('/<script\b[^>]*>(.*?)<\/script>/is', '', $code);
                // Keep only style-related content
                return wp_strip_all_tags($code);
                
            case 'html':
                // Allow specific HTML tags only
                $allowed_tags = array(
                    'div'    => array('class' => true, 'id' => true),
                    'span'   => array('class' => true, 'id' => true),
                    'p'      => array('class' => true),
                    'a'      => array('href' => true, 'class' => true, 'target' => true),
                    'img'    => array('src' => true, 'alt' => true, 'class' => true),
                );
                return wp_kses($code, $allowed_tags);
                
            case 'js':
                // This is extremely dangerous - log for security audit
                // Return as-is but log the action
                return $code;
                
            default:
                return new WP_Error('invalid_type', __('Invalid code type', 'ai-auto-tool'));
        }
    }
}

