<?php
/**
 * Action Renderer - CORRECTED & ENHANCED VERSION
 *
 * This file contains the ActionRenderer class which provides optimized
 * rendering methods for various action UI components including buttons,
 * button groups, AJAX actions, bulk actions, and action bars. The class
 * implements performance optimizations with full backward compatibility
 * including static method caching, validation caching, and efficient
 * HTML generation.
 *
 * @package    UltraguardPro\view
 * @author     UltraGuard Pro Team <support@ultraguardpro.com>
 * @copyright  2024 UltraGuard Pro Security Solutions
 * @license    GPL-2.0+
 * @version    1.2.0
 * @link       https://ultraguardpro.com/docs/action-renderer
 */

namespace UltraguardPro\view;

defined( 'ABSPATH' ) || exit;

/**
 * Action Renderer - CORRECTED & ENHANCED VERSION
 *
 * Provides high-performance rendering methods for action-based UI components
 * with extensive caching and optimization techniques. This class extends
 * BaseRenderer to provide common rendering functionality while implementing
 * static caching patterns for maximum performance.
 *
 * The class features:
 * - Static instance caching (Singleton pattern)
 * - Cached validation arrays for fast lookups
 * - Default scheme caching with intelligent invalidation
 * - Optimized sanitization with result caching
 * - Efficient HTML attribute building
 * - Early exit strategies for empty data
 * - Minimal filter overhead with conditional execution
 * - Enhanced button size support (mini, small, medium, large, xlarge)
 * - Fixed button group rendering with proper flex display
 * - Improved connected button group styling
 *
 * @package    UltraguardPro\view
 * @author     UltraGuard Pro Team
 * @version    1.2.0
 * @since      1.0.0
 * @see        BaseRenderer
 * @see        \UltraguardPro\view\RenderEngine
 *
 * @example
 * // Render a button with mini size
 * $button_html = ActionRenderer::render_button([
 *     'text' => 'Click Me',
 *     'button_style' => 'primary',
 *     'size' => 'mini',
 *     'url' => 'https://example.com',
 *     'target' => '_blank'
 * ], []);
 *
 * // Render a connected button group
 * $group_html = ActionRenderer::render_button_group([
 *     'buttons' => [
 *         ['text' => 'Previous', 'button_style' => 'secondary'],
 *         ['text' => 'Next', 'button_style' => 'primary']
 *     ],
 *     'style' => 'connected',
 *     'alignment' => 'center',
 *     'size' => 'small'
 * ], []);
 *
 * // Render an AJAX action
 * $ajax_html = ActionRenderer::render_ajax_action([
 *     'ajax_action' => 'process_data',
 *     'text' => 'Process Now',
 *     'confirm_message' => 'Are you sure?',
 *     'ajax_data' => ['user_id' => 123, 'type' => 'premium']
 * ], []);
 */
class ActionRenderer extends BaseRenderer {

    /**
     * Static instance cache
     *
     * Stores the singleton instance of ActionRenderer to prevent
     * multiple instantiations and reduce memory usage.
     *
     * @var ActionRenderer|null
     * @access private
     * @static
     */
    private static $instance = null;

    /**
     * Cached validation arrays
     *
     * Predefined arrays for fast validation lookups to avoid
     * repeated array creation and improve performance.
     *
     * @var array<string, array<string>>
     * @access private
     * @static
     */
    private static $validation_cache = [
        'button_types' => [ 'button', 'submit', 'reset' ],
        'targets' => [ '_self', '_blank', '_parent', '_top' ],
        'methods' => [ 'GET', 'POST', 'PUT', 'DELETE' ],
        'alignments' => [ 'left', 'center', 'right', 'justify', 'between', 'around', 'stretch', 'space-between' ],
        'sizes' => [ 'mini', 'small', 'medium', 'large', 'xlarge' ],
        'group_styles' => [ 'default', 'connected', 'segmented', 'primary', 'secondary', 'success', 'error', 'danger', 'warning', 'info' ],
    ];

    /**
     * Default scheme cache
     *
     * Caches default scheme configurations for each rendering method
     * to avoid repeated wp_parse_args calls and array merging.
     *
     * @var array<string, array<string, mixed>>
     * @access private
     * @static
     */
    private static $default_schemes = [];

    /**
     * Get static instance
     *
     * Returns the singleton instance of ActionRenderer.
     * Implements lazy initialization to create the instance
     * only when needed.
     *
     * @return ActionRenderer  The singleton instance
     * @access private
     * @static
     */
    private static function get_instance() {
        if ( null === self::$instance ) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * Get cached default scheme
     *
     * Retrieves or creates a cached default scheme for a specific
     * rendering method. Uses MD5 hashing for cache key generation
     * to handle custom overrides.
     *
     * @param  string  $method  Method name (e.g., 'render_button')
     * @param  array<string, mixed>  $custom  Custom default overrides
     * @return array<string, mixed>           Cached default scheme
     * @access private
     * @static
     */
    private static function get_default_scheme( $method, $custom = [] ) {
        $cache_key = $method . '_' . md5( wp_json_encode( $custom ) );

        if ( ! isset( self::$default_schemes[ $cache_key ] ) ) {
            switch ( $method ) {
                case 'render_button':
                    self::$default_schemes[ $cache_key ] = wp_parse_args( $custom, [
                        'button_type'     => 'button',
                        'button_style'    => 'default',
                        'size'            => 'medium',
                        'text'            => '',
                        'class'           => '',
                        'id'              => '',
                        'name'            => '',
                        'value'           => '',
                        'disabled'        => false,
                        'url'             => '',
                        'target'          => '_self',
                        'icon'            => '',
                        'icon_position'   => 'left',
                        'icon_only'       => false,
                        'title'           => '',
                        'aria_label'      => '',
                        'ajax'            => [],
                        'data'            => [],
                        'ajax_data'       => [],
                        'modal'           => null,        // NEW: Inline modal definition
                        'modal_id'        => '',          // NEW: Reference to existing modal
                    ] );
                    break;

                case 'render_button_group':
                    self::$default_schemes[ $cache_key ] = wp_parse_args( $custom, [
                        'buttons'   => [],
                        'alignment' => 'left',
                        'class'     => '',
                        'id'        => '',
                        'style'     => 'default',
                        'size'      => 'medium',
                        'connected' => false, // Backward compatibility
                    ] );
                    break;

                case 'render_ajax_action':
                    self::$default_schemes[ $cache_key ] = wp_parse_args( $custom, [
                        'ajax_action'      => '',
                        'nonce'            => '',
                        'confirm_message'  => '',
                        'text'             => __( 'Process', 'ultraguard-security-suite' ),
                        'class'            => '',
                        'button_style'     => 'primary',
                        'button_type'      => 'button',
                        'size'             => 'medium',
                        'loading_text'     => __( 'Processing...', 'ultraguard-security-suite' ),
                        'method'           => 'POST',
                        'ajax_data'        => [],
                    ] );
                    break;

                case 'render_bulk_action':
                    self::$default_schemes[ $cache_key ] = wp_parse_args( $custom, [
                        'actions'    => [],
                        'class'      => '',
                        'id'         => '',
                        'name'       => 'bulk_action',
                        'button_text' => __( 'Apply', 'ultraguard-security-suite' ),
                        'button_size' => 'medium',
                        'empty_text' => __( 'Bulk Actions', 'ultraguard-security-suite' ),
                    ] );
                    break;

                case 'render_action_bar':
                    self::$default_schemes[ $cache_key ] = wp_parse_args( $custom, [
                        'actions'   => [],
                        'alignment' => 'right',
                        'class'     => '',
                        'id'        => '',
                        'spacing'   => 'normal',
                    ] );
                    break;

                case 'render_link_button':
                    self::$default_schemes[ $cache_key ] = wp_parse_args( $custom, [
                        'url'          => '',
                        'text'         => '',
                        'target'       => '_self',
                        'button_style' => 'default',
                        'size'         => 'medium',
                    ] );
                    break;

                case 'render_icon_button':
                    self::$default_schemes[ $cache_key ] = wp_parse_args( $custom, [
                        'icon'         => '',
                        'text'         => '',
                        'title'        => '',
                        'aria_label'   => '',
                        'button_style' => 'default',
                        'size'         => 'medium',
                        'icon_only'    => true,
                        'class'        => 'ultraguard-button-icon-only',
                    ] );
                    break;

                case 'render_submit':
                    self::$default_schemes[ $cache_key ] = wp_parse_args( $custom, [
                        'button_style' => 'primary',
                        'text'         => __( 'Submit', 'ultraguard-security-suite' ),
                        'size'         => 'medium',
                        'class'        => '',
                        'id'           => '',
                        'name'         => 'submit',
                        'value'        => '1',
                    ] );
                    break;

                case 'render_reset':
                    self::$default_schemes[ $cache_key ] = wp_parse_args( $custom, [
                        'button_style' => 'secondary',
                        'text'         => __( 'Reset', 'ultraguard-security-suite' ),
                        'size'         => 'medium',
                        'class'        => '',
                        'id'           => '',
                        'name'         => 'reset',
                        'value'        => '1',
                    ] );
                    break;

                default:
                    self::$default_schemes[ $cache_key ] = $custom;
            }
        }

        return self::$default_schemes[ $cache_key ];
    }

    /**
     * Fast sanitize key with cache
     *
     * Provides a cached version of sanitize_key() to avoid
     * repeated processing of the same key values.
     *
     * @param  string  $key  Key to sanitize
     * @return string        Sanitized key or empty string on failure
     * @access private
     * @static
     */
    private static function fast_sanitize_key( $key ) {
        static $cache = [];

        if ( ! is_string( $key ) ) {
            return '';
        }

        if ( isset( $cache[ $key ] ) ) {
            return $cache[ $key ];
        }

        $sanitized = sanitize_key( $key );
        $cache[ $key ] = $sanitized;

        return $sanitized;
    }

    /**
     * Fast sanitize HTML class with cache
     *
     * Provides a cached version of sanitize_html_class() to avoid
     * repeated processing of the same class values.
     *
     * @param  string  $class  Class name to sanitize
     * @return string          Sanitized class name or empty string on failure
     * @access private
     * @static
     */
    private static function fast_sanitize_html_class( $class ) {
        static $cache = [];

        if ( ! is_string( $class ) ) {
            return '';
        }

        if ( isset( $cache[ $class ] ) ) {
            return $cache[ $class ];
        }

        $sanitized = sanitize_html_class( $class );
        $cache[ $class ] = $sanitized;

        return $sanitized;
    }

    /**
     * Render button - CORRECTED & ENHANCED VERSION
     *
     * Renders a button element with comprehensive options for styling,
     * behavior, and accessibility. Supports regular buttons, link buttons,
     * and AJAX-enabled buttons with validation and security features.
     *
     * ENHANCEMENTS:
     * - Added 'mini' size support for very small buttons
     * - Added icon-only button support
     * - Improved size validation
     * - Better class handling for icon-only buttons
     *
     * @param  array<string, mixed>  $scheme   Button configuration scheme
     * @param  array<string, mixed>  $context  Rendering context data
     * @return string                          Rendered HTML button
     * @access public
     * @static
     *
     * @example
     * echo ActionRenderer::render_button([
     *     'text' => 'Save Changes',
     *     'button_style' => 'primary',
     *     'size' => 'mini',
     *     'icon' => 'dashicons-save',
     *     'ajax' => [
     *         'action' => 'save_settings',
     *         'confirm' => 'Are you sure?'
     *     ],
     *     'ajax_data' => ['user_id' => 123, 'type' => 'premium']
     * ], $context);
     */
    public static function render_button( $scheme, $context ) {
        $instance = self::get_instance();
        $scheme = $instance->before_render( $scheme, $context );

        // Use cached defaults
        $scheme = wp_parse_args( $scheme, self::get_default_scheme( 'render_button' ) );

        // Fast validation
        if ( ! in_array( $scheme['button_type'], self::$validation_cache['button_types'], true ) ) {
            $scheme['button_type'] = 'button';
        }

        // Validate size
        if ( ! in_array( $scheme['size'], self::$validation_cache['sizes'], true ) ) {
            $scheme['size'] = 'medium';
        }

        // Build classes array efficiently
        $classes = [
            'ultraguard-button',
            'button',
            'ultraguard-button-' . self::fast_sanitize_key( $scheme['button_style'] ),
            'ultraguard-button-' . self::fast_sanitize_key( $scheme['size'] ),
        ];

        // Add icon-only class if applicable
        if ( $scheme['icon_only'] && ! empty( $scheme['icon'] ) ) {
            $classes[] = 'ultraguard-button-icon-only';
        }

        if ( ! empty( $scheme['class'] ) ) {
            $custom_classes = explode( ' ', $scheme['class'] );
            foreach ( $custom_classes as $custom_class ) {
                $sanitized_class = self::fast_sanitize_html_class( $custom_class );
                if ( $sanitized_class ) {
                    $classes[] = $sanitized_class;
                }
            }
        }

        $attributes = [
            'type' => $scheme['button_type'],
        ];

        // Set ID and name with fast sanitization
        if ( ! empty( $scheme['id'] ) ) {
            $attributes['id'] = self::fast_sanitize_key( $scheme['id'] );
        }

        if ( ! empty( $scheme['name'] ) ) {
            $attributes['name'] = self::fast_sanitize_key( $scheme['name'] );
        }

        if ( ! empty( $scheme['value'] ) ) {
            $attributes['value'] = sanitize_text_field( is_array( $scheme['value'] ) ? (string)( $scheme['value']['value'] ?? $scheme['value']['content'] ?? '' ) : (string)$scheme['value'] );
        }

        if ( ! empty( $scheme['title'] ) ) {
            $attributes['title'] = sanitize_text_field( is_array( $scheme['title'] ) ? (string) ( $scheme['title']['text'] ?? $scheme['title']['content'] ?? '' ) : (string) $scheme['title'] );
        }

        if ( ! empty( $scheme['aria_label'] ) ) {
            $attributes['aria-label'] = sanitize_text_field( is_array( $scheme['aria_label'] ) ? (string) ( $scheme['aria_label']['text'] ?? $scheme['aria_label']['content'] ?? '' ) : (string) $scheme['aria_label'] );
        }

        if ( $scheme['disabled'] ) {
            $attributes['disabled'] = 'disabled';
            $classes[] = 'ultraguard-button-disabled';
        }

        // Determine tag and handle URL
        $tag = 'button';
        if ( ! empty( $scheme['url'] ) ) {
            unset( $attributes['type'] );
            $attributes['href'] = esc_url( $scheme['url'] );
            $tag = 'a';

            // Validate target
            if ( in_array( $scheme['target'], self::$validation_cache['targets'], true ) ) {
                $attributes['target'] = $scheme['target'];

                if ( '_blank' === $scheme['target'] ) {
                    $attributes['rel'] = 'noopener noreferrer';
                }
            }
        }

        // Handle AJAX with optimized nonce generation
        if ( ! empty( $scheme['ajax'] ) && is_array( $scheme['ajax'] ) && ! empty( $scheme['ajax']['action'] ) ) {
            $ajax_config = wp_parse_args( $scheme['ajax'], [
                'action' => '',
                'nonce'  => '',
                'confirm' => '',
                'method'  => 'POST',
                'data'    => [], // Backward compatible: data within ajax array
            ] );

            // Nonce: default to the shared admin nonce so it matches what the PHP
            // AjaxManager verifies (register_action defaults to 'ultraguard_admin_nonce').
            // Per-action nonces ('ultraguard_ajax_{action}') will never verify correctly.
            if ( empty( $ajax_config['nonce'] ) ) {
                $ajax_config['nonce'] = wp_create_nonce( 'ultraguard_admin_nonce' );
            }

            $classes[] = 'ultraguard-ajax-action';
            $attributes['data-ajax-action'] = self::fast_sanitize_key( $ajax_config['action'] );
            $attributes['data-nonce'] = sanitize_text_field( $ajax_config['nonce'] );

            // Validate method
            $method_upper = strtoupper( $ajax_config['method'] );
            if ( in_array( $method_upper, self::$validation_cache['methods'], true ) ) {
                $attributes['data-ajax-method'] = $method_upper;
            }

            if ( ! empty( $ajax_config['confirm'] ) ) {
                $attributes['data-confirm'] = sanitize_text_field( $ajax_config['confirm'] );
            }

            // Handle AJAX data - merge from both sources (backward compatible)
            $ajax_data = [];

            // 1. Get data from ajax['data'] (backward compatible)
            if ( ! empty( $ajax_config['data'] ) && is_array( $ajax_config['data'] ) ) {
                $ajax_data = array_merge( $ajax_data, $ajax_config['data'] );
            }

            // 2. Get data from top-level ajax_data (new parameter)
            if ( ! empty( $scheme['ajax_data'] ) && is_array( $scheme['ajax_data'] ) ) {
                $ajax_data = array_merge( $ajax_data, $scheme['ajax_data'] );
            }

            // Encode AJAX data if we have any
            if ( ! empty( $ajax_data ) ) {
                $json_value = wp_json_encode( $ajax_data );
                if ( false !== $json_value ) {
                    $attributes['data-ajax-data'] = $json_value;
                }
            }
        }
        // Handle inline modal definition
        if ( ! empty( $scheme['modal'] ) && is_array( $scheme['modal'] ) ) {
            $engine = RenderEngine::get_instance();

            // Collect inline modal and get generated ID
            $generated_modal_id = $engine->collect_inline_modal( $scheme['modal'], $context );

            // Add modal trigger data attribute
            $attributes['data-modal-trigger'] = $generated_modal_id;
            $classes[] = 'ultraguard-modal-trigger';
        }
        // Handle modal ID reference
        elseif ( ! empty( $scheme['modal_id'] ) ) {
            $attributes['data-modal-trigger'] = sanitize_key( $scheme['modal_id'] );
            $classes[] = 'ultraguard-modal-trigger';
        }

        if ( ! empty( $scheme['data']['modal-trigger'] ) ||
             ! empty( $scheme['data']['modal_trigger'] ) ||
             ! empty( $scheme['data']['modal-id'] ) ||
             ! empty( $scheme['data']['modal_id'] ) ) {

            $classes[] = 'ultraguard-modal-trigger';
        }

        // Handle data attributes efficiently (for non-AJAX data attributes)
        if ( ! empty( $scheme['data'] ) && is_array( $scheme['data'] ) ) {
            foreach ( $scheme['data'] as $data_key => $data_value ) {
                // Skip if this is ajax data attribute (already handled above)
                if ( 'ajax-data' === $data_key || 'ajax_data' === $data_key ) {
                    continue;
                }

                $safe_key = self::fast_sanitize_key( $data_key );
                $attr_key = 'data-' . $safe_key;

                if ( is_array( $data_value ) || is_object( $data_value ) ) {
                    $json_value = wp_json_encode( $data_value );
                    if ( false !== $json_value ) {
                        $attributes[ $attr_key ] = $json_value;
                    }
                } elseif ( is_bool( $data_value ) ) {
                    $attributes[ $attr_key ] = $data_value ? 'true' : 'false';
                } elseif ( is_numeric( $data_value ) ) {
                    $attributes[ $attr_key ] = $data_value;
                } else {
                    $attributes[ $attr_key ] = sanitize_text_field( $data_value );
                }
            }
        }

        // Finalize classes
        $attributes['class'] = implode( ' ', array_filter( $classes ) );

        // Apply filters only if there are filters hooked
        if ( has_filter( 'ultraguard_button_attributes' ) ) {
            $attributes = apply_filters( 'ultraguard_button_attributes', $attributes, $scheme, $context );
        }

        // Build icon and content
        $content = '';
        if ( ! $scheme['icon_only'] || empty( $scheme['icon'] ) ) {
            $content = is_array( $scheme['text'] ) ? esc_html( (string) ( $scheme['text']['text'] ?? $scheme['text']['content'] ?? '' ) ) : esc_html( (string) $scheme['text'] );
        }

        if ( ! empty( $scheme['icon'] ) ) {
            $icon_html = $instance->render_ui_icon( $scheme['icon'] );

            if ( $scheme['icon_only'] ) {
                $content = $icon_html;
                // Add aria-label for accessibility
                if ( ! empty( $scheme['text'] ) && empty( $attributes['aria-label'] ) ) {
                    $attributes['aria-label'] = is_array( $scheme['text'] ) ? sanitize_text_field( (string) ( $scheme['text']['text'] ?? '' ) ) : sanitize_text_field( (string) $scheme['text'] );
                } elseif ( ! empty( $attributes['title'] ) && empty( $attributes['aria-label'] ) ) {
                    $attributes['aria-label'] = $attributes['title'];
                }
            } else {
                if ( 'left' === $scheme['icon_position'] ) {
                    $content = $icon_html . ( $content ? ' ' . $content : '' );
                } else {
                    $content = ( $content ? $content . ' ' : '' ) . $icon_html;
                }
            }
        }

        if ( has_filter( 'ultraguard_button_content' ) ) {
            $content = apply_filters( 'ultraguard_button_content', $content, $scheme, $context );
        }

        // Build attributes string efficiently
        $attributes_string = self::build_attributes_string( $attributes );

        $output = sprintf( '<%s%s>%s</%s>', $tag, $attributes_string, $content, $tag );
        $output = $instance->after_render( $output, $scheme, $context );

        return $output;
    }

    /**
     * Build attributes string efficiently
     *
     * Converts an associative array of attributes into a properly
     * formatted HTML attributes string with escaping and boolean handling.
     *
     * @param  array<string, mixed>  $attributes  Attributes array
     * @return string                             HTML attributes string
     * @access private
     * @static
     */
    private static function build_attributes_string( $attributes ) {
        if ( empty( $attributes ) ) {
            return '';
        }

        $parts = [];
        foreach ( $attributes as $key => $value ) {
            if ( is_bool( $value ) ) {
                if ( $value ) {
                    $parts[] = esc_attr( $key );
                }
            } else {
                $parts[] = sprintf( '%s="%s"', esc_attr( $key ), esc_attr( $value ) );
            }
        }

        return $parts ? ' ' . implode( ' ', $parts ) : '';
    }

    /**
     * Render button group - CORRECTED & ENHANCED VERSION
     *
     * Renders a group of buttons with consistent styling and alignment.
     * Supports various alignment options and group styles including connected buttons.
     *
     * FIXES:
     * - Proper flex display handling
     * - Fixed connected button group rendering
     * - Improved size propagation to child buttons
     * - Better backward compatibility with 'connected' parameter
     * - Enhanced style validation
     *
     * @param  array<string, mixed>  $scheme   Button group configuration
     * @param  array<string, mixed>  $context  Rendering context data
     * @return string                          Rendered HTML button group
     * @access public
     * @static
     *
     * @example
     * echo ActionRenderer::render_button_group([
     *     'buttons' => [
     *         ['text' => 'Previous', 'button_style' => 'secondary'],
     *         ['text' => 'Next', 'button_style' => 'primary']
     *     ],
     *     'style' => 'connected',
     *     'alignment' => 'center',
     *     'size' => 'small'
     * ], $context);
     */
    public static function render_button_group( $scheme, $context ) {
        $instance = self::get_instance();
        $scheme = $instance->before_render( $scheme, $context );

        // Use cached defaults
        $scheme = wp_parse_args( $scheme, self::get_default_scheme( 'render_button_group' ) );

        // Fast validation
        if ( empty( $scheme['buttons'] ) || ! is_array( $scheme['buttons'] ) ) {
            return '';
        }

        // Backward compatibility: convert 'connected' boolean to style
        if ( ! empty( $scheme['connected'] ) && 'default' === $scheme['style'] ) {
            $scheme['style'] = 'connected';
        }

        // Validate alignment
        if ( ! in_array( $scheme['alignment'], self::$validation_cache['alignments'], true ) ) {
            $scheme['alignment'] = 'left';
        }

        // Validate style
        if ( ! in_array( $scheme['style'], self::$validation_cache['group_styles'], true ) ) {
            $scheme['style'] = 'default';
        }

        // Validate size
        if ( ! in_array( $scheme['size'], self::$validation_cache['sizes'], true ) ) {
            $scheme['size'] = 'medium';
        }

        $classes = [
            'ultraguard-button-group',
            'ultraguard-button-group-' . self::fast_sanitize_key( $scheme['alignment'] ),
            'ultraguard-button-group-' . self::fast_sanitize_key( $scheme['size'] ),
        ];

        if ( 'default' !== $scheme['style'] ) {
            $classes[] = 'ultraguard-button-group-' . self::fast_sanitize_key( $scheme['style'] );
        }

        if ( ! empty( $scheme['class'] ) ) {
            $custom_classes = explode( ' ', $scheme['class'] );
            foreach ( $custom_classes as $custom_class ) {
                $sanitized_class = self::fast_sanitize_html_class( $custom_class );
                if ( $sanitized_class ) {
                    $classes[] = $sanitized_class;
                }
            }
        }

        if ( has_filter( 'ultraguard_button_group_classes' ) ) {
            $classes = apply_filters( 'ultraguard_button_group_classes', $classes, $scheme, $context );
        }

        // Render buttons with early exit and size propagation
        $buttons_html = '';
        foreach ( $scheme['buttons'] as $button_scheme ) {
            if ( is_array( $button_scheme ) ) {
                // Propagate size to child buttons if not explicitly set
                if ( ! isset( $button_scheme['size'] ) && 'medium' !== $scheme['size'] ) {
                    $button_scheme['size'] = $scheme['size'];
                }

                $rendered_button = $instance->engine->render( $button_scheme, $context );
                if ( $rendered_button ) {
                    $buttons_html .= $rendered_button;
                }
            }
        }

        if ( empty( $buttons_html ) ) {
            return '';
        }

        $wrapper_attrs = [
            'class' => implode( ' ', array_filter( $classes ) ),
            'role'  => 'group',
        ];

        if ( ! empty( $scheme['id'] ) ) {
            $wrapper_attrs['id'] = self::fast_sanitize_key( $scheme['id'] );
        }

        $attributes_string = self::build_attributes_string( $wrapper_attrs );

        $content = sprintf( '<div%s>%s</div>', $attributes_string, $buttons_html );
        $output = $instance->after_render( $content, $scheme, $context );

        return $output;
    }

    /**
     * Render submit button - ENHANCED VERSION
     *
     * Renders a submit button with primary styling by default.
     * A convenience wrapper around render_button with submit-specific defaults.
     *
     * @param  array<string, mixed>  $scheme   Submit button configuration
     * @param  array<string, mixed>  $context  Rendering context data
     * @return string                          Rendered HTML submit button
     * @access public
     * @static
     *
     * @example
     * echo ActionRenderer::render_submit([
     *     'text' => 'Save All Changes',
     *     'name' => 'save_all',
     *     'size' => 'large',
     *     'class' => 'large-submit'
     * ], $context);
     */
    public static function render_submit( $scheme, $context ) {
        // Use cached defaults
        $scheme = wp_parse_args( $scheme, self::get_default_scheme( 'render_submit' ) );
        $scheme['button_type'] = 'submit';

        return self::render_button( $scheme, $context );
    }

    /**
     * Render reset button - ENHANCED VERSION
     *
     * Renders a reset button with secondary styling by default.
     * A convenience wrapper around render_button with reset-specific defaults.
     *
     * @param  array<string, mixed>  $scheme   Reset button configuration
     * @param  array<string, mixed>  $context  Rendering context data
     * @return string                          Rendered HTML reset button
     * @access public
     * @static
     *
     * @example
     * echo ActionRenderer::render_reset([
     *     'text' => 'Reset Form',
     *     'button_style' => 'danger',
     *     'size' => 'small'
     * ], $context);
     */
    public static function render_reset( $scheme, $context ) {
        // Use cached defaults
        $scheme = wp_parse_args( $scheme, self::get_default_scheme( 'render_reset' ) );
        $scheme['button_type'] = 'reset';

        return self::render_button( $scheme, $context );
    }

    /**
     * Render AJAX action - ENHANCED VERSION
     *
     * Renders a button configured for AJAX operations with automatic
     * nonce generation, confirmation dialogs, and loading states.
     *
     * @param  array<string, mixed>  $scheme   AJAX action configuration
     * @param  array<string, mixed>  $context  Rendering context data
     * @return string                          Rendered HTML AJAX button
     * @access public
     * @static
     *
     * @example
     * echo ActionRenderer::render_ajax_action([
     *     'ajax_action' => 'delete_item',
     *     'text' => 'Delete Item',
     *     'button_style' => 'danger',
     *     'size' => 'small',
     *     'confirm_message' => 'Permanently delete this item?',
     *     'loading_text' => 'Deleting...',
     *     'ajax_data' => [
     *         'item_id' => 456,
     *         'force_delete' => true
     *     ]
     * ], $context);
     */
    public static function render_ajax_action( $scheme, $context ) {
        $instance = self::get_instance();
        $scheme = $instance->before_render( $scheme, $context );

        // Use cached defaults
        $scheme = wp_parse_args( $scheme, self::get_default_scheme( 'render_ajax_action' ) );

        // Fast validation
        if ( empty( $scheme['ajax_action'] ) ) {
            return '';
        }

        // Nonce: use the shared admin nonce so PHP AjaxManager::verify_nonce() matches.
        // Per-action nonces ('ultraguard_ajax_{action}') are never verified server-side.
        if ( empty( $scheme['nonce'] ) ) {
            $scheme['nonce'] = wp_create_nonce( 'ultraguard_admin_nonce' );
        }

        // Build AJAX config efficiently
        $ajax_config = [
            'action' => $scheme['ajax_action'],
            'nonce'  => $scheme['nonce'],
            'method' => $scheme['method'],
        ];

        if ( ! empty( $scheme['confirm_message'] ) ) {
            $ajax_config['confirm'] = $scheme['confirm_message'];
        }

        // Handle backward compatibility: if old format has data in ajax array, preserve it
        if ( isset( $scheme['ajax'] ) && is_array( $scheme['ajax'] ) && isset( $scheme['ajax']['data'] ) ) {
            $ajax_config['data'] = $scheme['ajax']['data'];
        }

        $scheme['ajax'] = $ajax_config;

        // Add classes efficiently
        $scheme['class'] = $scheme['class']
            ? $scheme['class'] . ' ultraguard-ajax-action'
            : 'ultraguard-ajax-action';

        // Add loading text
        if ( ! empty( $scheme['loading_text'] ) ) {
            if ( ! isset( $scheme['data'] ) ) {
                $scheme['data'] = [];
            }
            $scheme['data']['loading-text'] = $scheme['loading_text'];
        }

        return self::render_button( $scheme, $context );
    }

    /**
     * Render bulk action - ENHANCED VERSION
     *
     * Renders a bulk action selector with associated apply button.
     * Commonly used in admin tables for performing actions on multiple items.
     *
     * @param  array<string, mixed>  $scheme   Bulk action configuration
     * @param  array<string, mixed>  $context  Rendering context data
     * @return string                          Rendered HTML bulk action selector
     * @access public
     * @static
     *
     * @example
     * echo ActionRenderer::render_bulk_action([
     *     'actions' => [
     *         'delete' => 'Delete Selected',
     *         'archive' => 'Archive Selected',
     *         'export' => 'Export Selected'
     *     ],
     *     'button_text' => 'Apply Action',
     *     'button_size' => 'small',
     *     'class' => 'custom-bulk-actions'
     * ], $context);
     */
    public static function render_bulk_action( $scheme, $context ) {
        $instance = self::get_instance();
        $scheme = $instance->before_render( $scheme, $context );

        // Use cached defaults
        $scheme = wp_parse_args( $scheme, self::get_default_scheme( 'render_bulk_action' ) );

        // Fast validation
        if ( empty( $scheme['actions'] ) || ! is_array( $scheme['actions'] ) ) {
            return '';
        }

        // Validate button size
        if ( ! in_array( $scheme['button_size'], self::$validation_cache['sizes'], true ) ) {
            $scheme['button_size'] = 'medium';
        }

        // Build options HTML efficiently
        $options = [ sprintf( '<option value="">%s</option>', esc_html( $scheme['empty_text'] ) ) ];

        // Apply filters only if needed
        $actions = $scheme['actions'];
        if ( has_filter( 'ultraguard_bulk_action_options' ) ) {
            $actions = apply_filters( 'ultraguard_bulk_action_options', $actions, $scheme, $context );
        }

        foreach ( $actions as $action_value => $action_label ) {
            $safe_value = self::fast_sanitize_key( $action_value );
            $safe_label = sanitize_text_field( $action_label );
            $options[] = sprintf( '<option value="%s">%s</option>', esc_attr( $safe_value ), esc_html( $safe_label ) );
        }

        // Build classes
        $classes = [ 'ultraguard-bulk-actions' ];
        if ( ! empty( $scheme['class'] ) ) {
            $custom_classes = explode( ' ', $scheme['class'] );
            foreach ( $custom_classes as $custom_class ) {
                $sanitized_class = self::fast_sanitize_html_class( $custom_class );
                if ( $sanitized_class ) {
                    $classes[] = $sanitized_class;
                }
            }
        }

        $select_id = ! empty( $scheme['id'] ) ? self::fast_sanitize_key( $scheme['id'] ) : '';
        $select_id_attr = $select_id ? sprintf( ' id="%s"', esc_attr( $select_id ) ) : '';

        $select_name = self::fast_sanitize_key( $scheme['name'] );

        // Build button classes with size
        $button_classes = 'button ultraguard-button ultraguard-button-secondary ultraguard-button-' .
                         self::fast_sanitize_key( $scheme['button_size'] ) . ' ultraguard-bulk-action-apply';

        $content = sprintf(
            '<div class="%s">' .
            '<select name="%s"%s class="ultraguard-bulk-action-select">%s</select>' .
            '<button type="button" class="%s">%s</button>' .
            '</div>',
            esc_attr( implode( ' ', $classes ) ),
            esc_attr( $select_name ),
            $select_id_attr,
            implode( '', $options ),
            esc_attr( $button_classes ),
            esc_html( $scheme['button_text'] )
        );

        $output = $instance->render_wrapper( $content, $scheme, $context );
        $output = $instance->after_render( $output, $scheme, $context );

        return $output;
    }

    /**
     * Render action bar - ENHANCED VERSION
     *
     * Renders a horizontal bar containing multiple action buttons
     * with configurable alignment and spacing.
     *
     * @param  array<string, mixed>  $scheme   Action bar configuration
     * @param  array<string, mixed>  $context  Rendering context data
     * @return string                          Rendered HTML action bar
     * @access public
     * @static
     *
     * @example
     * echo ActionRenderer::render_action_bar([
     *     'actions' => [
     *         ['type' => 'button', 'text' => 'Save', 'button_style' => 'primary', 'size' => 'small'],
     *         ['type' => 'button', 'text' => 'Cancel', 'button_style' => 'secondary', 'size' => 'small'],
     *         ['type' => 'link_button', 'text' => 'Help', 'url' => '/help', 'size' => 'small']
     *     ],
     *     'alignment' => 'right',
     *     'spacing' => 'large'
     * ], $context);
     */
    public static function render_action_bar( $scheme, $context ) {
        $instance = self::get_instance();
        $scheme = $instance->before_render( $scheme, $context );

        // Use cached defaults
        $scheme = wp_parse_args( $scheme, self::get_default_scheme( 'render_action_bar' ) );

        // Fast validation
        if ( empty( $scheme['actions'] ) || ! is_array( $scheme['actions'] ) ) {
            return '';
        }

        if ( ! in_array( $scheme['alignment'], self::$validation_cache['alignments'], true ) ) {
            $scheme['alignment'] = 'right';
        }

        // Render actions with early exit
        $actions_html = '';
        foreach ( $scheme['actions'] as $action_scheme ) {
            if ( is_array( $action_scheme ) && isset( $action_scheme['type'] ) ) {
                $rendered = $instance->engine->render( $action_scheme, $context );
                if ( $rendered ) {
                    $actions_html .= $rendered;
                }
            }
        }

        if ( empty( $actions_html ) ) {
            return '';
        }

        $classes = [
            'ultraguard-action-bar',
            'ultraguard-action-bar-' . self::fast_sanitize_key( $scheme['alignment'] ),
            'ultraguard-action-bar-spacing-' . self::fast_sanitize_key( $scheme['spacing'] ),
        ];

        if ( ! empty( $scheme['class'] ) ) {
            $custom_classes = explode( ' ', $scheme['class'] );
            foreach ( $custom_classes as $custom_class ) {
                $sanitized_class = self::fast_sanitize_html_class( $custom_class );
                if ( $sanitized_class ) {
                    $classes[] = $sanitized_class;
                }
            }
        }

        if ( has_filter( 'ultraguard_action_bar_classes' ) ) {
            $classes = apply_filters( 'ultraguard_action_bar_classes', $classes, $scheme, $context );
        }

        $wrapper_attrs = [
            'class'      => implode( ' ', array_filter( $classes ) ),
            'role'       => 'group',
            'aria-label' => __( 'Action buttons', 'ultraguard-security-suite' ),
        ];

        if ( ! empty( $scheme['id'] ) ) {
            $wrapper_attrs['id'] = self::fast_sanitize_key( $scheme['id'] );
        }

        $attributes_string = self::build_attributes_string( $wrapper_attrs );

        $content = sprintf( '<div%s>%s</div>', $attributes_string, $actions_html );
        $output = $instance->after_render( $content, $scheme, $context );

        return $output;
    }

    /**
     * Render link button - ENHANCED VERSION
     *
     * Renders a button styled as a hyperlink for navigation purposes.
     * A convenience wrapper around render_button with link-specific defaults.
     *
     * @param  array<string, mixed>  $scheme   Link button configuration
     * @param  array<string, mixed>  $context  Rendering context data
     * @return string                          Rendered HTML link button
     * @access public
     * @static
     *
     * @example
     * echo ActionRenderer::render_link_button([
     *     'url' => 'https://example.com/docs',
     *     'text' => 'View Documentation',
     *     'target' => '_blank',
     *     'button_style' => 'primary',
     *     'size' => 'small'
     * ], $context);
     */
    public static function render_link_button( $scheme, $context ) {
        // Use cached defaults
        $scheme = wp_parse_args( $scheme, self::get_default_scheme( 'render_link_button' ) );

        // Fast validation
        if ( empty( $scheme['url'] ) ) {
            return '';
        }

        return self::render_button( $scheme, $context );
    }

    /**
     * Render icon button - ENHANCED VERSION
     *
     * Renders a button consisting primarily of an icon with optional
     * text and tooltips. Designed for compact action spaces.
     *
     * @param  array<string, mixed>  $scheme   Icon button configuration
     * @param  array<string, mixed>  $context  Rendering context data
     * @return string                          Rendered HTML icon button
     * @access public
     * @static
     *
     * @example
     * echo ActionRenderer::render_icon_button([
     *     'icon' => 'dashicons-trash',
     *     'text' => 'Delete Item',
     *     'title' => 'Delete this item',
     *     'aria_label' => 'Delete selected item',
     *     'button_style' => 'danger',
     *     'size' => 'small',
     *     'ajax' => [
     *         'action' => 'delete_item'
     *     ],
     *     'ajax_data' => ['item_id' => 123, 'force' => true]
     * ], $context);
     */
    public static function render_icon_button( $scheme, $context ) {
        // Use cached defaults
        $scheme = wp_parse_args( $scheme, self::get_default_scheme( 'render_icon_button' ) );

        // Fast validation
        if ( empty( $scheme['icon'] ) ) {
            return '';
        }

        // Add accessibility attributes
        if ( empty( $scheme['text'] ) && ! empty( $scheme['aria_label'] ) ) {
            $scheme['aria_label'] = $scheme['aria_label'];
        }

        if ( ! empty( $scheme['title'] ) ) {
            $scheme['title'] = $scheme['title'];
        }

        return self::render_button( $scheme, $context );
    }

    /**
     * Clear static caches (for testing)
     *
     * Clears all static caches used by the class. Primarily intended
     * for unit testing and development purposes.
     *
     * @return void
     * @access public
     * @static
     */
    public static function clear_caches() {
        self::$instance = null;
        self::$default_schemes = [];
    }
}
