<?php
/**
 * Display Renderer class file
 *
 * This file contains the DisplayRenderer class which handles all display
 * component rendering within the UltraguardPro system. It provides methods
 * for rendering various UI components including messages, badges, dividers,
 * icons, images, videos, headings, paragraphs, security badges, step
 * indicators, toast notifications, and empty states.
 *
 * The class implements comprehensive caching, security validation, and
 * accessibility features to ensure safe and efficient rendering of
 * display components across the application.
 *
 * @package    UltraguardPro\view
 * @author     Ultraguard Pro Team <support@ultraguardpro.com>
 * @copyright  2024 Ultraguard Pro
 * @license    GPL-2.0-or-later
 * @version    1.0.0
 * @link       https://ultraguardpro.com/docs/display-rendering
 */

namespace UltraguardPro\view;

defined( 'ABSPATH' ) || exit;

/**
 * Display Renderer
 *
 * Handles all display component rendering including UI elements,
 * notifications, indicators, and visual components. Implements
 * comprehensive security measures, accessibility features, and
 * performance optimizations through caching.
 *
 * This class extends BaseRenderer and provides static methods for
 * rendering various display components. It includes extensive
 * configuration options, validation, and caching mechanisms to
 * ensure consistent and efficient rendering across the application.
 *
 * @package    UltraguardPro\view
 * @author     Ultraguard Pro Team
 * @version    1.0.0
 * @since      1.0.0
 * @see        \UltraguardPro\view\BaseRenderer
 * @see        \UltraguardPro\view\ConditionalRenderer
 */
class DisplayRenderer extends BaseRenderer {

    /**
     * Static cache for rendered content
     *
     * Stores rendered HTML output keyed by cache keys to prevent
     * redundant rendering operations for identical scheme/context
     * combinations. This cache is request-level only.
     *
     * @var array<string, string>
     * @access private
     * @static
     */
    private static $render_cache = array();

    /**
     * Default schemes for each render method
     *
     * Defines default configuration values for each display component
     * type to ensure consistent behavior and reduce required configuration.
     *
     * @var array<string, array<string, mixed>>
     * @access private
     * @static
     */
    private static $default_schemes = array(
        'html' => array(
            'content'          => '',
            'class'            => '',
            'id'               => '',
            'style'            => '',
            'wrapper_tag'      => 'div',
            'allow_unsafe_html' => false,
        ),
        'message' => array(
            'message_type'    => 'info',
            'dismissible'     => false,
            'icon'            => '',
            'content'         => '',
            'class'           => '',
            'id'              => '',
            'wrapper_class'   => '',
        ),
        'badge' => array(
            'badge_type'      => 'default',
            'content'         => '',
            'class'           => '',
            'id'              => '',
            'aria_label'      => '',
            'wrapper_tag'     => 'span',
        ),
        'divider' => array(
            'divider_type'    => 'solid',
            'color'           => '#ddd',
            'class'           => '',
            'id'              => '',
        ),
        'spacer' => array(
            'height'          => '20px',
            'class'           => '',
            'id'              => '',
        ),
        'icon' => array(
            'icon'            => '',
            'size'            => 'default',
            'color'           => '',
            'class'           => '',
            'id'              => '',
        ),
        'image' => array(
            'src'             => '',
            'alt'             => '',
            'width'           => '',
            'height'          => '',
            'class'           => 'ultraguard-image',
            'id'              => '',
            'loading'         => 'lazy',
            'srcset'          => '',
            'sizes'           => '',
            'decoding'        => 'async',
            'wrapper_tag'     => 'div',
        ),
        'video' => array(
            'src'             => '',
            'width'           => '100%',
            'height'          => '400px',
            'controls'        => true,
            'autoplay'        => false,
            'loop'            => false,
            'class'           => 'ultraguard-video',
            'id'              => '',
        ),
        'heading' => array(
            'level'           => 2,
            'content'         => '',
            'align'           => 'left',
            'class'           => '',
            'id'              => '',
        ),
        'paragraph' => array(
            'content'         => '',
            'align'           => 'left',
            'class'           => '',
            'id'              => '',
        ),
        'security_badge' => array(
            'level'           => 'secure',
            'size'            => 'medium',
            'style'           => 'shield',
            'text'            => '',
            'class'           => '',
            'id'              => '',
            'wrapper_class'   => '',
        ),
        'step_indicator' => array(
            'steps'           => array(),
            'current_step'    => 1,
            'style'           => 'horizontal',
            'class'           => '',
            'id'              => '',
            'wrapper_class'   => '',
            'aria_label'      => '',
        ),
        'toast_notification' => array(
            'message'         => '',
            'type'            => 'info',
            'duration'        => 5000,
            'position'        => 'top-right',
            'actions'         => array(),
            'class'           => '',
            'id'              => '',
            'wrapper_class'   => '',
        ),
        'empty_state' => array(
            'icon'            => 'dashicons-info',
            'message'         => '',
            'action_button'   => array(),
            'style'           => 'default',
            'class'           => '',
            'id'              => '',
            'wrapper_class'   => '',
        ),
         'loading' => array(
            'message'         => '',
            'size'            => 'medium',
            'type'            => 'spinner', // spinner, dots, progress, skeleton
            'show_text'       => true,
            'full_height'     => false,
            'class'           => '',
            'id'              => '',
            'wrapper_class'   => '',
            'center'          => true,
            'inline'          => false,
            'progress'        => 0, // 0-100 for progress type
            'icon'            => '', // Custom icon class
            'color'           => '', // Custom color
        ),
    );

    /**
     * Security badge configurations cache
     *
     * Caches security badge configurations to avoid repeated filter
     * execution and provide consistent badge styling.
     *
     * @var array<string, array>|null
     * @access private
     * @static
     */
    private static $security_badge_configs = null;

    /**
     * Valid dashicon classes cache
     *
     * Caches valid dashicon class names to optimize icon validation
     * and prevent invalid icon classes from being used.
     *
     * @var array<string>|null
     * @access private
     * @static
     */
    private static $valid_dashicons = null;

    /**
     * Toast notification icons cache
     *
     * Caches toast notification icon configurations for efficient
     * icon retrieval based on notification type.
     *
     * @var array<string, string>|null
     * @access private
     * @static
     */
    private static $toast_icons = null;

    /**
     * Singleton instance for internal use
     *
     * Singleton instance used by static methods to access instance
     * methods and non-static parent class functionality.
     *
     * @var self|null
     * @access private
     * @static
     */
    private static $instance = null;

    /**
     * Get singleton instance
     *
     * Returns the singleton instance of DisplayRenderer for internal use
     * by static rendering methods. Implements lazy initialization.
     *
     * @return self The singleton instance
     * @access private
     * @static
     */
    private static function get_instance() {
        if ( null === self::$instance ) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * Render HTML content
     *
     * Renders arbitrary HTML content with security sanitization and
     * wrapper support. Supports callable content and includes
     * comprehensive error handling.
     *
     * @param  array<string, mixed> $scheme   HTML scheme configuration
     * @param  array<string, mixed> $context  Context data for rendering
     * @return string                         Rendered HTML content
     * @access public
     * @static
     *
     * @example
     * $html = DisplayRenderer::render_html([
     *     'content' => '<p>Custom HTML content</p>',
     *     'wrapper_tag' => 'section',
     *     'class' => 'custom-section'
     * ], []);
     */
    public static function render_html( $scheme, $context ) {
        $cache_key = 'html_' . md5( wp_json_encode( array( $scheme, $context ) ) );

        if ( isset( self::$render_cache[ $cache_key ] ) ) {
            return self::$render_cache[ $cache_key ];
        }

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );

        // Merge with defaults
        $scheme = wp_parse_args( $scheme, self::$default_schemes['html'] );

        // Support both 'content' and 'html' keys for the HTML content
        $content = $scheme['content'];
        if ( empty( $content ) && ! empty( $scheme['html'] ) ) {
            $content = $scheme['html'];
        }

        // Allow callable content
        if ( is_callable( $content ) ) {
            try {
                if ( has_action( 'ultraguard_before_html_callback' ) ) {
                    do_action( 'ultraguard_before_html_callback', $content, $context );
                }

                $content = call_user_func( $content, $context );

                if ( has_action( 'ultraguard_after_html_callback' ) ) {
                    do_action( 'ultraguard_after_html_callback', $content, $context );
                }
            } catch ( \Exception $e ) {
                if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
                    \UltraguardPro\core\Logger::error(
                        sprintf(

                            /* translators: Placeholder values are inserted into this string. */
                            __( 'DisplayRenderer HTML callback error: %s', 'ultraguard-security-suite'),
                            $e->getMessage()
                        )
                    );
                }
                $content = $instance->handle_render_error(
                    /* translators: %s: string */
                    sprintf( __( 'HTML callback error: %s', 'ultraguard-security-suite'), $e->getMessage() ),
                    $scheme
                );
            }
        }

        // Sanitize content based on context
        $content = $instance->sanitize_html_content( $content, $scheme );

        // Use render_wrapper to get proper wrapper HTML
        $output = $instance->render_wrapper( $content, $scheme, $context );
        $output = $instance->after_render( $output, $scheme, $context );

        self::$render_cache[ $cache_key ] = $output;

        return $output;
    }

    /**
     * Sanitize HTML content based on scheme configuration
     *
     * Applies appropriate sanitization to HTML content based on
     * scheme configuration. Defaults to wp_kses_post for safety
     * but allows custom sanitization via filter.
     *
     * @param  string $content HTML content to sanitize
     * @param  array<string, mixed> $scheme Render scheme configuration
     * @return string                       Sanitized content
     * @access protected
     */
    protected function sanitize_html_content( $content, $scheme ) {
        // Default to wp_kses_post for safety
        if ( ! isset( $scheme['allow_unsafe_html'] ) || ! $scheme['allow_unsafe_html'] ) {
            return wp_kses_post( is_array( $content ) ? esc_html( wp_json_encode( $content ) ) : (string)( $content ) );
        }

        // Allow custom sanitization via filter
        return apply_filters( 'ultraguard_html_content_sanitize', $content, $scheme );
    }

    /**
     * Render message box
     *
     * Renders a styled message box with configurable type, icons,
     * and dismissible functionality. Supports info, success,
     * warning, and error message types.
     *
     * @param  array<string, mixed> $scheme   Message scheme configuration
     * @param  array<string, mixed> $context  Context data for rendering
     * @return string                         Rendered HTML content
     * @access public
     * @static
     *
     * @example
     * $html = DisplayRenderer::render_message([
     *     'content' => 'Operation completed successfully!',
     *     'message_type' => 'success',
     *     'dismissible' => true,
     *     'icon' => 'dashicons-yes-alt'
     * ], []);
     */
    public static function render_message( $scheme, $context ) {
        $cache_key = 'message_' . md5( wp_json_encode( array( $scheme, $context ) ) );

        if ( isset( self::$render_cache[ $cache_key ] ) ) {
            return self::$render_cache[ $cache_key ];
        }

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );

        // Merge with defaults
        $scheme = wp_parse_args( $scheme, self::$default_schemes['message'] );

        $type        = sanitize_html_class( $scheme['message_type'] );
        $dismissible = (bool) $scheme['dismissible'];

        $icon_html = '';
        if ( ! empty( $scheme['icon'] ) ) {
            $icon = sanitize_text_field( $scheme['icon'] );
            if ( $instance->is_valid_dashicon( $icon ) || $instance->is_fontawesome_icon( $icon ) ) {
                $icon_html = $instance->render_ui_icon( $icon );
            } elseif ( strpos( $icon, 'dashicons-' ) === 0 ) {
                $icon_html = $instance->render_ui_icon( 'dashicons-info' );
            }
        }

        $dismiss_html = '';
        if ( $dismissible ) {
            $dismiss_html = '<button type="button" class="ultraguard-message-dismiss" aria-label="' .
                esc_attr__( 'Dismiss', 'ultraguard-security-suite') . '">&times;</button>';
        }

        $content = sprintf(

            '<div class="ultraguard-message ultraguard-message-%s">' .
            '%s' .
            '<div class="ultraguard-message-content">%s</div>' .
            '%s' .
            '</div>',
            esc_attr( $type ),
            $icon_html,
            wp_kses_post( is_array( $scheme['content'] ) ? esc_html( wp_json_encode( $scheme['content'] ) ) : (string)( $scheme['content'] ) ),
            $dismiss_html
        );

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

        self::$render_cache[ $cache_key ] = $output;

        return $output;
    }

    /**
     * Render badge
     *
     * Renders a badge component with configurable type, content,
     * and accessibility attributes. Supports various badge styles
     * and semantic wrapper tags.
     *
     * @param  array<string, mixed> $scheme   Badge scheme configuration
     * @param  array<string, mixed> $context  Context data for rendering
     * @return string                         Rendered HTML content
     * @access public
     * @static
     *
     * @example
     * $html = DisplayRenderer::render_badge([
     *     'content' => 'New',
     *     'badge_type' => 'primary',
     *     'aria_label' => 'New item badge'
     * ], []);
     */
    public static function render_badge( $scheme, $context ) {
        $cache_key = 'badge_' . md5( wp_json_encode( array( $scheme, $context ) ) );

        if ( isset( self::$render_cache[ $cache_key ] ) ) {
            return self::$render_cache[ $cache_key ];
        }

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );

        // Merge with defaults
        $scheme = wp_parse_args( $scheme, self::$default_schemes['badge'] );

        $type       = sanitize_html_class( $scheme['badge_type'] );
        $content    = $scheme['content'];
        $aria_label = ! empty( $scheme['aria_label'] ) ? esc_attr( $scheme['aria_label'] ) : '';

        $attributes = array(
            'class' => 'ultraguard-badge ultraguard-badge-' . esc_attr( $type ),
        );

        if ( ! empty( $scheme['class'] ) ) {
            $attributes['class'] .= ' ' . sanitize_html_class( $scheme['class'] );
        }

        if ( ! empty( $scheme['id'] ) ) {
            $attributes['id'] = sanitize_html_class( $scheme['id'] );
        }

        if ( $aria_label ) {
            $attributes['aria-label'] = $aria_label;
        } else {
            $attributes['aria-label'] = esc_attr( wp_strip_all_tags( $content ) );
        }

        // Build attributes string
        $attributes_string = '';
        foreach ( $attributes as $key => $value ) {
            $attributes_string .= sprintf( ' %s="%s"', esc_attr( $key ), esc_attr( $value ) );
        }

        $output = sprintf(

            '<%s%s>%s</%s>',
            esc_attr( $scheme['wrapper_tag'] ),
            $attributes_string,
            esc_html( $content ),
            esc_attr( $scheme['wrapper_tag'] )
        );

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

        self::$render_cache[ $cache_key ] = $output;

        return $output;
    }

    /**
     * Render divider
     *
     * Renders a horizontal divider with configurable style and color.
     * Supports various divider types including solid, dashed, and dotted.
     *
     * @param  array<string, mixed> $scheme   Divider scheme configuration
     * @param  array<string, mixed> $context  Context data for rendering
     * @return string                         Rendered HTML content
     * @access public
     * @static
     *
     * @example
     * $html = DisplayRenderer::render_divider([
     *     'divider_type' => 'dashed',
     *     'color' => '#666'
     * ], []);
     */
    public static function render_divider( $scheme, $context ) {
        $cache_key = 'divider_' . md5( wp_json_encode( array( $scheme, $context ) ) );

        if ( isset( self::$render_cache[ $cache_key ] ) ) {
            return self::$render_cache[ $cache_key ];
        }

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );

        // Merge with defaults
        $scheme = wp_parse_args( $scheme, self::$default_schemes['divider'] );

        $type  = sanitize_html_class( $scheme['divider_type'] );
        $color = sanitize_hex_color( $scheme['color'] );

        $style = sprintf( 'border-color: %s;', $color );

        $output = sprintf(

            '<hr class="ultraguard-divider ultraguard-divider-%s" style="%s">',
            esc_attr( $type ),
            esc_attr( $style )
        );

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

        self::$render_cache[ $cache_key ] = $output;

        return $output;
    }

    /**
     * Render spacer
     *
     * Renders a vertical spacer element with configurable height.
     * Useful for creating consistent spacing between components.
     *
     * @param  array<string, mixed> $scheme   Spacer scheme configuration
     * @param  array<string, mixed> $context  Context data for rendering
     * @return string                         Rendered HTML content
     * @access public
     * @static
     *
     * @example
     * $html = DisplayRenderer::render_spacer([
     *     'height' => '40px',
     *     'class' => 'section-spacer'
     * ], []);
     */
    public static function render_spacer( $scheme, $context ) {
        $cache_key = 'spacer_' . md5( wp_json_encode( array( $scheme, $context ) ) );

        if ( isset( self::$render_cache[ $cache_key ] ) ) {
            return self::$render_cache[ $cache_key ];
        }

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );

        // Merge with defaults
        $scheme = wp_parse_args( $scheme, self::$default_schemes['spacer'] );

        $height = esc_attr( $scheme['height'] );

        $output = sprintf(

            '<div class="ultraguard-spacer" style="height: %s;"></div>',
            $height
        );

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

        self::$render_cache[ $cache_key ] = $output;

        return $output;
    }

    /**
     * Render icon
     *
     * Renders a WordPress dashicon with configurable size and color.
     * Includes validation to ensure only valid dashicon classes are used.
     *
     * @param  array<string, mixed> $scheme   Icon scheme configuration
     * @param  array<string, mixed> $context  Context data for rendering
     * @return string                         Rendered HTML content
     * @access public
     * @static
     *
     * @example
     * $html = DisplayRenderer::render_icon([
     *     'icon' => 'dashicons-yes',
     *     'size' => 'large',
     *     'color' => '#10b981'
     * ], []);
     */
    public static function render_icon( $scheme, $context ) {
        $cache_key = 'icon_' . md5( wp_json_encode( array( $scheme, $context ) ) );

        if ( isset( self::$render_cache[ $cache_key ] ) ) {
            return self::$render_cache[ $cache_key ];
        }

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );

        // Merge with defaults
        $scheme = wp_parse_args( $scheme, self::$default_schemes['icon'] );

        $icon  = sanitize_text_field( $scheme['icon'] );
        $size  = sanitize_html_class( $scheme['size'] );
        $color = sanitize_hex_color( $scheme['color'] );

        $style = '';
        if ( $color ) {
            $style = sprintf( 'color: %s;', $color );
        }

        $output = $instance->render_ui_icon(
            $icon,
            'ultraguard-icon ultraguard-icon-' . $size,
            $style ? array( 'style' => $style ) : array()
        );

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

        self::$render_cache[ $cache_key ] = $output;

        return $output;
    }

    /**
     * Render image
     *
     * Renders an image with responsive attributes, lazy loading,
     * and accessibility features. Supports modern image attributes
     * like srcset and sizes.
     *
     * @param  array<string, mixed> $scheme   Image scheme configuration
     * @param  array<string, mixed> $context  Context data for rendering
     * @return string                         Rendered HTML content
     * @access public
     * @static
     *
     * @example
     * $html = DisplayRenderer::render_image([
     *     'src' => 'https://example.com/image.jpg',
     *     'alt' => 'Descriptive alt text',
     *     'width' => 800,
     *     'height' => 600,
     *     'srcset' => 'small.jpg 400w, medium.jpg 800w, large.jpg 1200w',
     *     'loading' => 'lazy'
     * ], []);
     */
    public static function render_image( $scheme, $context ) {
        $cache_key = 'image_' . md5( wp_json_encode( array( $scheme, $context ) ) );

        if ( isset( self::$render_cache[ $cache_key ] ) ) {
            return self::$render_cache[ $cache_key ];
        }

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );

        // Merge with defaults
        $scheme = wp_parse_args( $scheme, self::$default_schemes['image'] );

        $src    = esc_url( $scheme['src'] );
        $alt    = esc_attr( $scheme['alt'] );
        $width  = esc_attr( $scheme['width'] );
        $height = esc_attr( $scheme['height'] );

        $attributes = array(
            'src'     => $src,
            'alt'     => $alt,
            'class'   => sanitize_html_class( $scheme['class'] ),
            'loading' => in_array( $scheme['loading'], array( 'lazy', 'eager' ), true ) ?
                        $scheme['loading'] : 'lazy',
            'decoding' => in_array( $scheme['decoding'], array( 'async', 'sync', 'auto' ), true ) ?
                         $scheme['decoding'] : 'async',
        );

        if ( $width ) {
            $attributes['width'] = $width;
        }

        if ( $height ) {
            $attributes['height'] = $height;
        }

        if ( ! empty( $scheme['srcset'] ) ) {
            $attributes['srcset'] = esc_attr( $scheme['srcset'] );
        }

        if ( ! empty( $scheme['sizes'] ) ) {
            $attributes['sizes'] = esc_attr( $scheme['sizes'] );
        }

        $attributes_string = '';
        foreach ( $attributes as $key => $value ) {
            $attributes_string .= sprintf( ' %s="%s"', esc_attr( $key ), esc_attr( $value ) );
        }

        $image_html = sprintf( '<img%s>', $attributes_string );

        // Wrap image if needed
        if ( $scheme['wrapper_tag'] !== 'none' ) {
            $wrapper_attrs = array(
                'class' => 'ultraguard-image-wrapper',
            );

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

            $wrapper_attrs_string = '';
            foreach ( $wrapper_attrs as $key => $value ) {
                $wrapper_attrs_string .= sprintf( ' %s="%s"', esc_attr( $key ), esc_attr( $value ) );
            }

            $image_html = sprintf(

                '<%s%s>%s</%s>',
                esc_attr( $scheme['wrapper_tag'] ),
                $wrapper_attrs_string,
                $image_html,
                esc_attr( $scheme['wrapper_tag'] )
            );
        }

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

        self::$render_cache[ $cache_key ] = $output;

        return $output;
    }
    /**
     * Render loading widget
     *
     * Renders a loading indicator with configurable type, size, and message.
     * Supports spinner, dots, progress bar, and skeleton loading types.
     *
     * @param  array<string, mixed> $scheme   Loading scheme configuration
     * @param  array<string, mixed> $context  Context data for rendering
     * @return string                         Rendered HTML content
     * @access public
     * @static
     *
     * @example
     * $html = DisplayRenderer::render_loading([
     *     'message' => 'Loading file details...',
     *     'type' => 'spinner',
     *     'size' => 'large',
     *     'full_height' => true
     * ], []);
     */
    public static function render_loading( $scheme, $context ) {
        $cache_key = 'loading_' . md5( wp_json_encode( array( $scheme, $context ) ) );

        if ( isset( self::$render_cache[ $cache_key ] ) ) {
            return self::$render_cache[ $cache_key ];
        }

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );

        // Merge with defaults
        $scheme = wp_parse_args( $scheme, self::$default_schemes['loading'] );

        $message      = $scheme['message'];
        $size         = sanitize_html_class( $scheme['size'] );
        $type         = sanitize_html_class( $scheme['type'] );
        $show_text    = (bool) $scheme['show_text'];
        $full_height  = (bool) $scheme['full_height'];
        $center       = (bool) $scheme['center'];
        $inline       = (bool) $scheme['inline'];
        $progress     = min( 100, max( 0, (int) $scheme['progress'] ) );
        $icon         = sanitize_text_field( $scheme['icon'] );
        $color        = sanitize_hex_color( $scheme['color'] );

        // Generate loading indicator based on type
        $indicator_html = '';
        $style = '';

        if ( $color ) {
            $style = sprintf( 'style="color: %s;"', esc_attr( $color ) );
        }

        switch ( $type ) {
            case 'spinner':
                if ( $icon ) {
                    $indicator_html = $instance->render_ui_icon(
                        $icon,
                        'ultraguard-loading-icon',
                        $color ? array( 'style' => sprintf( 'color: %s;', $color ) ) : array()
                    );
                } else {
                    $indicator_html = sprintf(

                        '<div class="ultraguard-spinner" %s></div>',
                        $style
                    );
                }
                break;

            case 'dots':
                $indicator_html = sprintf(

                    '<div class="ultraguard-dots-loading" %s>
                        <div class="ultraguard-dot"></div>
                        <div class="ultraguard-dot"></div>
                        <div class="ultraguard-dot"></div>
                    </div>',
                    $style
                );
                break;

            case 'progress':
                $indicator_html = sprintf(

                    '<div class="ultraguard-security-suitegress-loading" %s>
                        <div class="ultraguard-security-suitegress-bar" style="width: %d%%"></div>
                    </div>',
                    $style,
                    $progress
                );
                break;

            case 'skeleton':
                $indicator_html = sprintf(

                    '<div class="ultraguard-skeleton-loading" %s>
                        <div class="ultraguard-skeleton-line"></div>
                        <div class="ultraguard-skeleton-line" style="width: 80%%"></div>
                        <div class="ultraguard-skeleton-line" style="width: 60%%"></div>
                    </div>',
                    $style
                );
                break;

            default:
                $indicator_html = sprintf(

                    '<div class="ultraguard-spinner" %s></div>',
                    $style
                );
                break;
        }

        // Build classes
        $classes = array( 'ultraguard-loading', 'ultraguard-loading-' . $type );
        $classes[] = 'ultraguard-loading-' . $size;

        if ( $full_height ) {
            $classes[] = 'ultraguard-loading-full-height';
        }

        if ( $center && ! $inline ) {
            $classes[] = 'ultraguard-loading-center';
        }

        if ( $inline ) {
            $classes[] = 'ultraguard-loading-inline';
        }

        if ( ! empty( $scheme['class'] ) ) {
            $classes[] = sanitize_html_class( $scheme['class'] );
        }

        // Add text if enabled
        $text_html = '';
        if ( $show_text && ! empty( $message ) ) {
            $text_html = sprintf(

                '<div class="ultraguard-loading-text">%s</div>',
                esc_html( $message )
            );
        }

        // Determine layout based on type and inline setting
        $content = '';
        if ( $inline && $show_text && ! empty( $message ) ) {
            $content = sprintf(

                '<span class="ultraguard-loading-inline-wrapper">
                    %s
                    <span class="ultraguard-loading-text-inline">%s</span>
                </span>',
                $indicator_html,
                esc_html( $message )
            );
        } else {
            $content = $indicator_html . $text_html;
        }

        // Wrap content
        $attributes = array(
            'class' => implode( ' ', $classes ),
        );

        if ( ! empty( $scheme['id'] ) ) {
            $attributes['id'] = sanitize_html_class( $scheme['id'] );
        }

        if ( $full_height ) {
            $attributes['style'] = 'min-height: 200px;';
        }

        $attributes_string = '';
        foreach ( $attributes as $key => $value ) {
            $attributes_string .= sprintf( ' %s="%s"', esc_attr( $key ), esc_attr( $value ) );
        }

        $output = sprintf( '<div%s>%s</div>', $attributes_string, $content );

        // Apply wrapper if needed
        if ( ! empty( $scheme['wrapper_class'] ) || $full_height ) {
            $wrapper_classes = array( 'ultraguard-loading-wrapper' );

            if ( ! empty( $scheme['wrapper_class'] ) ) {
                $wrapper_classes[] = sanitize_html_class( $scheme['wrapper_class'] );
            }

            if ( $full_height ) {
                $wrapper_classes[] = 'ultraguard-loading-wrapper-full-height';
            }

            $output = sprintf(

                '<div class="%s">%s</div>',
                esc_attr( implode( ' ', $wrapper_classes ) ),
                $output
            );
        }

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

        self::$render_cache[ $cache_key ] = $output;

        return $output;
    }
    /**
     * Render video
     *
     * Renders an HTML5 video element with configurable controls,
     * autoplay, and loop settings. Includes responsive sizing support.
     *
     * @param  array<string, mixed> $scheme   Video scheme configuration
     * @param  array<string, mixed> $context  Context data for rendering
     * @return string                         Rendered HTML content
     * @access public
     * @static
     *
     * @example
     * $html = DisplayRenderer::render_video([
     *     'src' => 'https://example.com/video.mp4',
     *     'width' => '100%',
     *     'height' => 'auto',
     *     'controls' => true,
     *     'autoplay' => false,
     *     'loop' => false
     * ], []);
     */
    public static function render_video( $scheme, $context ) {
        $cache_key = 'video_' . md5( wp_json_encode( array( $scheme, $context ) ) );

        if ( isset( self::$render_cache[ $cache_key ] ) ) {
            return self::$render_cache[ $cache_key ];
        }

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );

        // Merge with defaults
        $scheme = wp_parse_args( $scheme, self::$default_schemes['video'] );

        $src      = esc_url( $scheme['src'] );
        $width    = esc_attr( $scheme['width'] );
        $height   = esc_attr( $scheme['height'] );
        $controls = (bool) $scheme['controls'];
        $autoplay = (bool) $scheme['autoplay'];
        $loop     = (bool) $scheme['loop'];

        $attributes = array(
            'src'   => $src,
            'width' => $width,
            'height' => $height,
            'class' => sanitize_html_class( $scheme['class'] ),
        );

        if ( $controls ) {
            $attributes['controls'] = 'controls';
        }

        if ( $autoplay ) {
            $attributes['autoplay'] = 'autoplay';
        }

        if ( $loop ) {
            $attributes['loop'] = 'loop';
        }

        $attributes_string = '';
        foreach ( $attributes as $key => $value ) {
            $attributes_string .= sprintf( ' %s="%s"', esc_attr( $key ), esc_attr( $value ) );
        }

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

        self::$render_cache[ $cache_key ] = $output;

        return $output;
    }

    /**
     * Render heading
     *
     * Renders a heading element (h1-h6) with configurable level,
     * alignment, and styling. Ensures proper heading hierarchy.
     *
     * @param  array<string, mixed> $scheme   Heading scheme configuration
     * @param  array<string, mixed> $context  Context data for rendering
     * @return string                         Rendered HTML content
     * @access public
     * @static
     *
     * @example
     * $html = DisplayRenderer::render_heading([
     *     'level' => 2,
     *     'content' => 'Section Title',
     *     'align' => 'center',
     *     'class' => 'section-title'
     * ], []);
     */
    public static function render_heading( $scheme, $context ) {
        $cache_key = 'heading_' . md5( wp_json_encode( array( $scheme, $context ) ) );

        if ( isset( self::$render_cache[ $cache_key ] ) ) {
            return self::$render_cache[ $cache_key ];
        }

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );

        // Merge with defaults
        $scheme = wp_parse_args( $scheme, self::$default_schemes['heading'] );

        $level   = absint( $scheme['level'] );
        $content = $scheme['content'];
        $align   = sanitize_html_class( $scheme['align'] );

        // Ensure level is between 1 and 6
        $level = max( 1, min( 6, $level ) );

        $classes = array( 'ultraguard-heading' );
        $classes[] = 'ultraguard-heading-align-' . $align;

        if ( ! empty( $scheme['class'] ) ) {
            $classes[] = sanitize_html_class( $scheme['class'] );
        }

        $output = sprintf(

            '<h%d class="%s">%s</h%d>',
            $level,
            esc_attr( implode( ' ', $classes ) ),
            esc_html( $content ),
            $level
        );

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

        self::$render_cache[ $cache_key ] = $output;

        return $output;
    }

    /**
     * Render paragraph
     *
     * Renders a paragraph element with configurable alignment and
     * styling. Supports safe HTML content through wp_kses_post.
     *
     * @param  array<string, mixed> $scheme   Paragraph scheme configuration
     * @param  array<string, mixed> $context  Context data for rendering
     * @return string                         Rendered HTML content
     * @access public
     * @static
     *
     * @example
     * $html = DisplayRenderer::render_paragraph([
     *     'content' => 'This is a paragraph with <strong>bold</strong> text.',
     *     'align' => 'justify',
     *     'class' => 'intro-text'
     * ], []);
     */
    public static function render_paragraph( $scheme, $context ) {
        $cache_key = 'paragraph_' . md5( wp_json_encode( array( $scheme, $context ) ) );

        if ( isset( self::$render_cache[ $cache_key ] ) ) {
            return self::$render_cache[ $cache_key ];
        }

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );

        // Merge with defaults
        $scheme = wp_parse_args( $scheme, self::$default_schemes['paragraph'] );

        $content = $scheme['content'];
        $align   = sanitize_html_class( $scheme['align'] );

        $classes = array( 'ultraguard-paragraph' );
        $classes[] = 'ultraguard-paragraph-align-' . $align;

        if ( ! empty( $scheme['class'] ) ) {
            $classes[] = sanitize_html_class( $scheme['class'] );
        }

        $output = sprintf(

            '<p class="%s">%s</p>',
            esc_attr( implode( ' ', $classes ) ),
            wp_kses_post( is_array( $content ) ? esc_html( wp_json_encode( $content ) ) : (string)( $content ) )
        );

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

        self::$render_cache[ $cache_key ] = $output;

        return $output;
    }

    /**
     * Render security badge
     *
     * Renders a security badge component indicating security status
     * levels (secure, warning, vulnerable, info). Supports multiple
     * styles and sizes with configurable text.
     *
     * @param  array<string, mixed> $scheme   Security badge scheme configuration
     * @param  array<string, mixed> $context  Context data for rendering
     * @return string                         Rendered HTML content
     * @access public
     * @static
     *
     * @example
     * $html = DisplayRenderer::render_security_badge([
     *     'level' => 'secure',
     *     'size' => 'large',
     *     'style' => 'shield',
     *     'text' => 'Site Secured'
     * ], []);
     */
    public static function render_security_badge( $scheme, $context ) {
        $cache_key = 'security_badge_' . md5( wp_json_encode( array( $scheme, $context ) ) );

        if ( isset( self::$render_cache[ $cache_key ] ) ) {
            return self::$render_cache[ $cache_key ];
        }

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );

        // Merge with defaults
        $scheme = wp_parse_args( $scheme, self::$default_schemes['security_badge'] );

        $level = sanitize_html_class( $scheme['level'] );
        $size  = sanitize_html_class( $scheme['size'] );
        $style = sanitize_html_class( $scheme['style'] );
        $text  = $scheme['text'];

        // Cache security badge configurations
        if ( null === self::$security_badge_configs ) {
            $default_configs = array(
                'secure' => array(
                    'color'       => '#10b981',
                    'icon'        => 'dashicons-shield-alt',
                    'default_text' => __( 'Secure', 'ultraguard-security-suite'),
                ),
                'warning' => array(
                    'color'       => '#d97706',
                    'icon'        => 'dashicons-warning',
                    'default_text' => __( 'Warning', 'ultraguard-security-suite'),
                ),
                'vulnerable' => array(
                    'color'       => '#dc2626',
                    'icon'        => 'dashicons-dismiss',
                    'default_text' => __( 'Vulnerable', 'ultraguard-security-suite'),
                ),
                'info' => array(
                    'color'       => '#2563eb',
                    'icon'        => 'dashicons-info',
                    'default_text' => __( 'Info', 'ultraguard-security-suite'),
                ),
            );

            self::$security_badge_configs = apply_filters( 'ultraguard_security_badge_configs', $default_configs );
        }

        $config = isset( self::$security_badge_configs[ $level ] ) ? self::$security_badge_configs[ $level ] : self::$security_badge_configs['info'];
        $display_text = ! empty( $text ) ? $text : $config['default_text'];

        $badge_html = '';
        if ( 'shield' === $style ) {
            $badge_html = sprintf(

                '<div class="ultraguard-security-badge ultraguard-badge-%s ultraguard-badge-%s ultraguard-badge-%s">' .
                '%s' .
                '<span class="ultraguard-badge-text">%s</span>' .
                '</div>',
                esc_attr( $style ),
                esc_attr( $level ),
                esc_attr( $size ),
                $instance->render_ui_icon( $config['icon'], 'ultraguard-badge-icon' ),
                esc_html( $display_text )
            );
        } elseif ( 'minimal' === $style ) {
            $badge_html = sprintf(

                '<div class="ultraguard-security-badge ultraguard-badge-%s ultraguard-badge-%s ultraguard-badge-%s">' .
                '<span class="ultraguard-badge-dot"></span>' .
                '<span class="ultraguard-badge-text">%s</span>' .
                '</div>',
                esc_attr( $style ),
                esc_attr( $level ),
                esc_attr( $size ),
                esc_html( $display_text )
            );
        } else {
            // Default badge style
            $badge_html = sprintf(

                '<div class="ultraguard-security-badge ultraguard-badge-%s ultraguard-badge-%s">' .
                '<span class="ultraguard-badge-text">%s</span>' .
                '</div>',
                esc_attr( $level ),
                esc_attr( $size ),
                esc_html( $display_text )
            );
        }

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

        self::$render_cache[ $cache_key ] = $output;

        return $output;
    }

    /**
     * Render step indicator
     *
     * Renders a step indicator component showing progress through
     * multiple steps. Supports horizontal and vertical layouts with
     * current step highlighting and ARIA accessibility.
     *
     * @param  array<string, mixed> $scheme   Step indicator scheme configuration
     * @param  array<string, mixed> $context  Context data for rendering
     * @return string                         Rendered HTML content
     * @access public
     * @static
     *
     * @example
     * $html = DisplayRenderer::render_step_indicator([
     *     'steps' => ['Setup', 'Configuration', 'Completion'],
     *     'current_step' => 2,
     *     'style' => 'horizontal',
     *     'aria_label' => 'Registration progress'
     * ], []);
     */
    public static function render_step_indicator( $scheme, $context ) {
        $cache_key = 'step_indicator_' . md5( wp_json_encode( array( $scheme, $context ) ) );

        if ( isset( self::$render_cache[ $cache_key ] ) ) {
            return self::$render_cache[ $cache_key ];
        }

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );

        // Merge with defaults
        $scheme = wp_parse_args( $scheme, self::$default_schemes['step_indicator'] );

        $steps        = $scheme['steps'];
        $current_step = absint( $scheme['current_step'] );
        $style        = sanitize_html_class( $scheme['style'] );
        $aria_label   = ! empty( $scheme['aria_label'] ) ? esc_attr( $scheme['aria_label'] ) : __( 'Progress steps', 'ultraguard-security-suite');

        if ( empty( $steps ) || ! is_array( $steps ) ) {
            self::$render_cache[ $cache_key ] = '';
            return '';
        }

        // Sanitize steps
        $sanitized_steps = array();
        foreach ( $steps as $index => $step ) {
            if ( is_string( $step ) ) {
                $sanitized_steps[] = sanitize_text_field( $step );
            } elseif ( is_array( $step ) ) {
                $step = wp_parse_args( $step, array(
                    'label'       => '',
                    'description' => '',
                ));
                $sanitized_steps[] = array(
                    'label'       => sanitize_text_field( is_array( $step['label'] ) ? (string)( $step['label']['text'] ?? $step['label']['content'] ?? '' ) : (string)$step['label'] ),
                    'description' => wp_kses_post( is_array( $step['description'] ) ? (string)( $step['description']['text'] ?? $step['description']['content'] ?? '' ) : (string)$step['description'] ),
                );
            } else {
                /* translators: %d: integer */
                $sanitized_steps[] = sprintf( __( 'Step %d', 'ultraguard-security-suite'), $index + 1 );
            }
        }

        $steps_html = '';
        $step_count = count( $sanitized_steps );

        foreach ( $sanitized_steps as $index => $step ) {
            $step_number = $index + 1;
            $is_current = $step_number === $current_step;
            $is_completed = $step_number < $current_step;
            $is_future = $step_number > $current_step;

            $step_class = 'ultraguard-step';
            if ( $is_current ) {
                $step_class .= ' ultraguard-step-current';
            } elseif ( $is_completed ) {
                $step_class .= ' ultraguard-step-completed';
            } elseif ( $is_future ) {
                $step_class .= ' ultraguard-step-future';
            }

            $step_icon = '';
            if ( $is_completed ) {
                $step_icon = $instance->render_ui_icon( 'dashicons-yes-alt', '', array( 'aria-hidden' => 'true' ) );
            } else {
                $step_icon = sprintf( '<span class="ultraguard-step-number">%d</span>', $step_number );
            }

            $step_label = is_array( $step ) ? $step['label'] : $step;
            $step_description = is_array( $step ) && ! empty( $step['description'] ) ?
                               sprintf( '<div class="ultraguard-step-description">%s</div>', esc_html( is_array( $step['description'] ) ? (string)( $step['description']['text'] ?? $step['description']['content'] ?? wp_json_encode( $step['description'] ) ) : (string)( $step['description'] ) ) ) : '';

            $steps_html .= sprintf(

                '<div class="%s" role="listitem" aria-current="%s">' .
                '<div class="ultraguard-step-marker">%s</div>' .
                '<div class="ultraguard-step-label">%s%s</div>' .
                '</div>',
                esc_attr( $step_class ),
                $is_current ? 'step' : 'false',
                $step_icon,
                esc_html( $step_label ),
                $step_description
            );

            // Add connector between steps (except for last step)
            if ( $step_number < $step_count ) {
                $connector_class = 'ultraguard-step-connector';
                if ( $is_completed ) {
                    $connector_class .= ' ultraguard-step-connector-completed';
                }
                $steps_html .= sprintf( '<div class="%s" aria-hidden="true"></div>', esc_attr( $connector_class ) );
            }
        }

        $content = sprintf(

            '<div class="ultraguard-step-indicator ultraguard-step-%s" role="list" aria-label="%s">%s</div>',
            esc_attr( $style ),
            $aria_label,
            $steps_html
        );

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

        self::$render_cache[ $cache_key ] = $output;

        return $output;
    }

    /**
     * Render toast notification
     *
     * Renders a toast notification component with configurable type,
     * duration, position, and actions. Supports success, error,
     * warning, and info notification types.
     *
     * @param  array<string, mixed> $scheme   Toast notification scheme configuration
     * @param  array<string, mixed> $context  Context data for rendering
     * @return string                         Rendered HTML content
     * @access public
     * @static
     *
     * @example
     * $html = DisplayRenderer::render_toast_notification([
     *     'message' => 'Settings saved successfully!',
     *     'type' => 'success',
     *     'duration' => 3000,
     *     'position' => 'top-right',
     *     'actions' => [
     *         ['type' => 'default', 'label' => 'Undo', 'action' => 'undo']
     *     ]
     * ], []);
     */
    public static function render_toast_notification( $scheme, $context ) {
        $cache_key = 'toast_' . md5( wp_json_encode( array( $scheme, $context ) ) );

        if ( isset( self::$render_cache[ $cache_key ] ) ) {
            return self::$render_cache[ $cache_key ];
        }

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );

        // Merge with defaults
        $scheme = wp_parse_args( $scheme, self::$default_schemes['toast_notification'] );

        $message  = $scheme['message'];
        $type     = sanitize_html_class( $scheme['type'] );
        $duration = absint( $scheme['duration'] );
        $position = sanitize_html_class( $scheme['position'] );
        $actions  = $scheme['actions'];

        if ( empty( $message ) ) {
            self::$render_cache[ $cache_key ] = '';
            return '';
        }

        $icon = self::get_toast_icon( $type );

        $actions_html = '';
        if ( ! empty( $actions ) && is_array( $actions ) ) {
            $actions_html .= '<div class="ultraguard-toast-actions">';
            foreach ( $actions as $index => $action ) {
                if ( ! is_array( $action ) ) {
                    continue;
                }

                $action = wp_parse_args( $action, array(
                    'type'   => 'default',
                    'action' => '',
                    'label'  => '',
                    'url'    => '',
                    'target' => '_self',
                    'nonce'  => '',
                ));

                $action_class = 'ultraguard-toast-action';
                $action_class .= ' ultraguard-toast-action-' . sanitize_html_class( $action['type'] );

                $action_attrs = array(
                    'class' => $action_class,
                    'data-action' => sanitize_key( $action['action'] ),
                );

                if ( ! empty( $action['nonce'] ) ) {
                    $action_attrs['data-nonce'] = sanitize_text_field( $action['nonce'] );
                }

                if ( ! empty( $action['url'] ) ) {
                    // It's a link button
                    $action_attrs['href'] = esc_url( $action['url'] );
                    $action_attrs['target'] = in_array( $action['target'], array( '_self', '_blank', '_parent', '_top' ), true ) ?
                                             $action['target'] : '_self';

                    $attrs_string = '';
                    foreach ( $action_attrs as $key => $value ) {
                        $attrs_string .= sprintf( ' %s="%s"', esc_attr( $key ), esc_attr( $value ) );
                    }

                    $actions_html .= sprintf(

                        '<a%s>%s</a>',
                        $attrs_string,
                        esc_html( is_array( $action['label'] ) ? (string)( $action['label']['text'] ?? $action['label']['content'] ?? wp_json_encode( $action['label'] ) ) : (string)( $action['label'] ) )
                    );
                } else {
                    // It's a regular button
                    $attrs_string = '';
                    foreach ( $action_attrs as $key => $value ) {
                        $attrs_string .= sprintf( ' %s="%s"', esc_attr( $key ), esc_attr( $value ) );
                    }

                    $actions_html .= sprintf(

                        '<button type="button"%s>%s</button>',
                        $attrs_string,
                        esc_html( is_array( $action['label'] ) ? (string)( $action['label']['text'] ?? $action['label']['content'] ?? wp_json_encode( $action['label'] ) ) : (string)( $action['label'] ) )
                    );
                }
            }
            $actions_html .= '</div>';
        }

        $content = sprintf(

            '<div class="ultraguard-toast ultraguard-toast-%s ultraguard-toast-%s" data-duration="%d">' .
            '<div class="ultraguard-toast-icon">%s</div>' .
            '<div class="ultraguard-toast-content">' .
            '<div class="ultraguard-toast-message">%s</div>' .
            '%s' .
            '</div>' .
            '<button type="button" class="ultraguard-toast-close" aria-label="%s">&times;</button>' .
            '</div>',
            esc_attr( $type ),
            esc_attr( $position ),
            $duration,
            $icon,
            esc_html( $message ),
            $actions_html,
            esc_attr__( 'Close notification', 'ultraguard-security-suite')
        );

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

        self::$render_cache[ $cache_key ] = $output;

        return $output;
    }

    /**
     * Render empty state
     *
     * Renders an empty state component for indicating no data or
     * content is available. Includes icon, message, and optional
     * action button with various styling options.
     *
     * @param  array<string, mixed> $scheme   Empty state scheme configuration
     * @param  array<string, mixed> $context  Context data for rendering
     * @return string                         Rendered HTML content
     * @access public
     * @static
     *
     * @example
     * $html = DisplayRenderer::render_empty_state([
     *     'icon' => 'dashicons-info',
     *     'message' => 'No items found',
     *     'action_button' => [
     *         'type' => 'primary',
     *         'label' => 'Create Item',
     *         'action' => 'create_item'
     *     ],
     *     'style' => 'minimal'
     * ], []);
     */
    public static function render_empty_state( $scheme, $context ) {
        $cache_key = 'empty_state_' . md5( wp_json_encode( array( $scheme, $context ) ) );

        if ( isset( self::$render_cache[ $cache_key ] ) ) {
            return self::$render_cache[ $cache_key ];
        }

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );

        // Merge with defaults
        $scheme = wp_parse_args( $scheme, self::$default_schemes['empty_state'] );

        $icon         = sanitize_text_field( $scheme['icon'] );
        $message      = ! empty( $scheme['message'] ) ? $scheme['message'] : __( 'No data available', 'ultraguard-security-suite');
        $action_button = $scheme['action_button'];
        $style        = sanitize_html_class( $scheme['style'] );

        $action_html = '';
        if ( ! empty( $action_button ) && is_array( $action_button ) ) {
            $action_html = $instance->engine->render( $action_button, $context );
        }

        $content = sprintf(

            '<div class="ultraguard-empty-state ultraguard-empty-%s">' .
            '%s' .
            '<div class="ultraguard-empty-message">%s</div>' .
            '%s' .
            '</div>',
            esc_attr( $style ),
            $instance->render_ui_icon( $icon, 'ultraguard-empty-icon' ),
            esc_html( $message ),
            $action_html
        );

        // Allow custom empty state content
        $content = apply_filters( 'ultraguard_empty_state_content', $content, $scheme, $context );

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

        self::$render_cache[ $cache_key ] = $output;

        return $output;
    }

    /**
     * Get toast notification icon (static version)
     *
     * Returns the appropriate icon HTML for a toast notification
     * based on the notification type. Caches icon configurations
     * for performance.
     *
     * @param  string $type Toast notification type
     * @return string       Icon HTML
     * @access protected
     * @static
     */
    protected static function get_toast_icon( $type ) {
        // Cache toast icons
        if ( null === self::$toast_icons ) {
            $default_icons = array(
                'success' => 'dashicons-yes-alt',
                'error'   => 'dashicons-dismiss',
                'warning' => 'dashicons-warning',
                'info'    => 'dashicons-info',
            );

            self::$toast_icons = apply_filters( 'ultraguard_toast_icons', $default_icons );
        }

        $icon_class = isset( self::$toast_icons[ $type ] ) ? self::$toast_icons[ $type ] : self::$toast_icons['info'];

        return self::get_instance()->render_ui_icon( $icon_class );
    }

    /**
     * Check if a string is a valid dashicon class
     *
     * Validates whether a given string is a valid WordPress dashicon
     * class name. Caches valid dashicon classes for performance.
     *
     * @param  string $icon_class Icon class to validate
     * @return bool              Whether it's a valid dashicon
     * @access protected
     */
    protected function is_valid_dashicon( $icon_class ) {
        if ( ! is_string( $icon_class ) ) {
            return false;
        }

        // Cache valid dashicons
        if ( null === self::$valid_dashicons ) {
            $default_dashicons = array(
                'dashicons-admin-appearance',
                'dashicons-admin-collapse',
                'dashicons-admin-comments',
                'dashicons-admin-customizer',
                'dashicons-admin-generic',
                'dashicons-admin-home',
                'dashicons-admin-links',
                'dashicons-admin-media',
                'dashicons-admin-multisite',
                'dashicons-admin-network',
                'dashicons-admin-page',
                'dashicons-admin-plugins',
                'dashicons-admin-post',
                'dashicons-admin-settings',
                'dashicons-admin-site',
                'dashicons-admin-tools',
                'dashicons-admin-users',
                'dashicons-album',
                'dashicons-align-center',
                'dashicons-align-left',
                'dashicons-align-none',
                'dashicons-align-right',
                'dashicons-archive',
                'dashicons-arrow-down',
                'dashicons-arrow-left',
                'dashicons-arrow-right',
                'dashicons-arrow-up',
                'dashicons-art',
                'dashicons-awards',
                'dashicons-backup',
                'dashicons-book',
                'dashicons-book-alt',
                'dashicons-building',
                'dashicons-businessman',
                'dashicons-calendar',
                'dashicons-calendar-alt',
                'dashicons-camera',
                'dashicons-carrot',
                'dashicons-cart',
                'dashicons-category',
                'dashicons-chart-area',
                'dashicons-chart-bar',
                'dashicons-chart-line',
                'dashicons-chart-pie',
                'dashicons-clipboard',
                'dashicons-clock',
                'dashicons-cloud',
                'dashicons-controls-back',
                'dashicons-controls-forward',
                'dashicons-controls-pause',
                'dashicons-controls-play',
                'dashicons-controls-repeat',
                'dashicons-controls-skipback',
                'dashicons-controls-skipforward',
                'dashicons-controls-volumeoff',
                'dashicons-controls-volumeon',
                'dashicons-dashboard',
                'dashicons-database',
                'dashicons-desktop',
                'dashicons-dismiss',
                'dashicons-download',
                'dashicons-edit',
                'dashicons-editor-aligncenter',
                'dashicons-editor-alignleft',
                'dashicons-editor-alignright',
                'dashicons-editor-bold',
                'dashicons-editor-break',
                'dashicons-editor-code',
                'dashicons-editor-contract',
                'dashicons-editor-customchar',
                'dashicons-editor-expand',
                'dashicons-editor-help',
                'dashicons-editor-indent',
                'dashicons-editor-insertmore',
                'dashicons-editor-italic',
                'dashicons-editor-justify',
                'dashicons-editor-kitchensink',
                'dashicons-editor-ol',
                'dashicons-editor-outdent',
                'dashicons-editor-paragraph',
                'dashicons-editor-paste-text',
                'dashicons-editor-paste-word',
                'dashicons-editor-quote',
                'dashicons-editor-removeformatting',
                'dashicons-editor-rtl',
                'dashicons-editor-spellcheck',
                'dashicons-editor-strikethrough',
                'dashicons-editor-table',
                'dashicons-editor-textcolor',
                'dashicons-editor-ul',
                'dashicons-editor-underline',
                'dashicons-editor-unlink',
                'dashicons-editor-video',
                'dashicons-email',
                'dashicons-email-alt',
                'dashicons-excerpt-view',
                'dashicons-external',
                'dashicons-facebook',
                'dashicons-feedback',
                'dashicons-filter',
                'dashicons-flag',
                'dashicons-format-aside',
                'dashicons-format-audio',
                'dashicons-format-chat',
                'dashicons-format-gallery',
                'dashicons-format-image',
                'dashicons-format-links',
                'dashicons-format-quote',
                'dashicons-format-status',
                'dashicons-format-video',
                'dashicons-forms',
                'dashicons-googleplus',
                'dashicons-grid-view',
                'dashicons-groups',
                'dashicons-hammer',
                'dashicons-heart',
                'dashicons-hidden',
                'dashicons-image-crop',
                'dashicons-image-filter',
                'dashicons-image-rotate',
                'dashicons-image-rotate-left',
                'dashicons-image-rotate-right',
                'dashicons-images-alt',
                'dashicons-images-alt2',
                'dashicons-index-card',
                'dashicons-info',
                'dashicons-laptop',
                'dashicons-layout',
                'dashicons-leftright',
                'dashicons-lightbulb',
                'dashicons-list-view',
                'dashicons-location',
                'dashicons-location-alt',
                'dashicons-lock',
                'dashicons-marker',
                'dashicons-media-archive',
                'dashicons-media-audio',
                'dashicons-media-code',
                'dashicons-media-default',
                'dashicons-media-document',
                'dashicons-media-interactive',
                'dashicons-media-spreadsheet',
                'dashicons-media-text',
                'dashicons-media-video',
                'dashicons-megaphone',
                'dashicons-menu',
                'dashicons-microphone',
                'dashicons-migrate',
                'dashicons-minus',
                'dashicons-money',
                'dashicons-nametag',
                'dashicons-networking',
                'dashicons-no',
                'dashicons-no-alt',
                'dashicons-palmtree',
                'dashicons-performance',
                'dashicons-phone',
                'dashicons-playlist-audio',
                'dashicons-playlist-video',
                'dashicons-plus',
                'dashicons-plus-alt',
                'dashicons-portfolio',
                'dashicons-post-status',
                'dashicons-pressthis',
                'dashicons-printer',
                'dashicons-privacy',
                'dashicons-randomize',
                'dashicons-redo',
                'dashicons-rest-api',
                'dashicons-rss',
                'dashicons-schedule',
                'dashicons-screenoptions',
                'dashicons-search',
                'dashicons-share',
                'dashicons-share-alt',
                'dashicons-share-alt2',
                'dashicons-shield',
                'dashicons-shield-alt',
                'dashicons-slides',
                'dashicons-smartphone',
                'dashicons-smiley',
                'dashicons-sort',
                'dashicons-sos',
                'dashicons-star-empty',
                'dashicons-star-filled',
                'dashicons-star-half',
                'dashicons-sticky',
                'dashicons-store',
                'dashicons-tablet',
                'dashicons-tag',
                'dashicons-tagcloud',
                'dashicons-testimonial',
                'dashicons-text',
                'dashicons-thumbs-down',
                'dashicons-thumbs-up',
                'dashicons-tickets',
                'dashicons-tickets-alt',
                'dashicons-translation',
                'dashicons-trash',
                'dashicons-twitter',
                'dashicons-undo',
                'dashicons-universal-access',
                'dashicons-universal-access-alt',
                'dashicons-unlock',
                'dashicons-update',
                'dashicons-upload',
                'dashicons-vault',
                'dashicons-video-alt',
                'dashicons-video-alt2',
                'dashicons-video-alt3',
                'dashicons-visibility',
                'dashicons-warning',
                'dashicons-welcome-add-page',
                'dashicons-welcome-comments',
                'dashicons-welcome-learn-more',
                'dashicons-welcome-view-site',
                'dashicons-welcome-widgets-menus',
                'dashicons-welcome-write-blog',
                'dashicons-wordpress',
                'dashicons-wordpress-alt',
                'dashicons-yes',
                'dashicons-yes-alt',
            );

            self::$valid_dashicons = apply_filters( 'ultraguard_valid_dashicons', $default_dashicons );
        }

        return in_array( $icon_class, self::$valid_dashicons, true );
    }

    /**
     * Clear static caches (useful for testing or memory management)
     *
     * Clears all internal static caches to free memory or reset state
     * for testing. Useful during plugin deactivation or batch processing.
     *
     * @return void
     * @access public
     * @static
     *
     * @example
     * DisplayRenderer::clear_caches();
     */
    public static function clear_caches() {
        self::$render_cache = array();
        self::$security_badge_configs = null;
        self::$valid_dashicons = null;
        self::$toast_icons = null;
        self::$instance = null;
    }

    /**
     * Render animated-counter display
     * Counts up to a target number with optional prefix/suffix.
     */
    public static function render_animated_counter( $scheme, $context ) {
        $cache_key = 'render_animated_counter_' . md5( wp_json_encode( array( $scheme, $context ) ) );
        if ( isset( self::$render_cache[ $cache_key ] ) ) {
            return self::$render_cache[ $cache_key ];
        }

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );

        $scheme = wp_parse_args( $scheme, [
            'value'    => 0,
            'prefix'   => '',
            'suffix'   => '',
            'duration' => 1500,
            'label'    => '',
            'id'       => 'ultraguard-counter-' . uniqid(),
            'class'    => '',
        ] );

        $id_attr    = $scheme['id']    ? ' id="' . esc_attr( $scheme['id'] )    . '"' : '';
        $class_attr = $scheme['class'] ? ' ' . esc_attr( $scheme['class'] )            : '';

        $label_html = $scheme['label']
            ? '<div class="ultraguard-counter-label">' . esc_html( $scheme['label'] ) . '</div>'
            : '';

        $output = sprintf(
            '<div%s class="ultraguard-animated-counter%s" data-target="%s" data-duration="%d">'
            . '<span class="ultraguard-counter-prefix">%s</span>'
            . '<span class="ultraguard-counter-value">%s</span>'
            . '<span class="ultraguard-counter-suffix">%s</span>'
            . '%s</div>'
            . '<script>document.addEventListener("DOMContentLoaded",function(){'
            . 'var el=document.querySelector("[data-target]");if(!el)return;'
            . 'var end=parseFloat(el.getAttribute("data-target"));'
            . 'var dur=parseInt(el.getAttribute("data-duration"),10)||1500;'
            . 'var val=el.querySelector(".ultraguard-counter-value");if(!val)return;'
            . 'var start=0,step=end/dur*16;'
            . 'var timer=setInterval(function(){start+=step;if(start>=end){val.textContent=end;clearInterval(timer);}else{val.textContent=Math.floor(start);}},16);'
            . '});</script>',
            $id_attr, $class_attr,
            esc_attr( $scheme['value'] ), absint( $scheme['duration'] ),
            esc_html( $scheme['prefix'] ),
            esc_html( $scheme['value'] ),
            esc_html( $scheme['suffix'] ),
            $label_html
        );
        $output = $instance->after_render( $output, $scheme, $context );
        self::$render_cache[ $cache_key ] = $output;
        return $output;
    }

    /**
     * Render comparison-slider display
     * Before/after slider for two HTML panels.
     */
    public static function render_comparison_slider( $scheme, $context ) {
        $cache_key = 'render_comparison_slider_' . md5( wp_json_encode( array( $scheme, $context ) ) );
        if ( isset( self::$render_cache[ $cache_key ] ) ) {
            return self::$render_cache[ $cache_key ];
        }

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );

        $scheme = wp_parse_args( $scheme, [
            'before_label' => __( 'Before', 'ultraguard-security-suite' ),
            'after_label'  => __( 'After', 'ultraguard-security-suite' ),
            'before'       => '',
            'after'        => '',
            'id'           => 'ultraguard-compare-' . uniqid(),
            'class'        => '',
        ] );

        $id_attr    = $scheme['id']    ? ' id="' . esc_attr( $scheme['id'] )    . '"' : '';
        $class_attr = $scheme['class'] ? ' ' . esc_attr( $scheme['class'] )            : '';

        $output = sprintf(
            '<div%s class="ultraguard-comparison-slider%s" style="display:grid;grid-template-columns:1fr 1fr;gap:16px;">'
            . '<div class="ultraguard-compare-before">'
            . '<div class="ultraguard-compare-label" style="font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:1px;color:#64748b;margin-bottom:8px;">%s</div>'
            . '<div class="ultraguard-compare-content" style="border:2px solid var(--ug-border,#e2e8f0);border-radius:var(--ug-radius-md,8px);padding:16px;">%s</div>'
            . '</div>'
            . '<div class="ultraguard-compare-after">'
            . '<div class="ultraguard-compare-label" style="font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:1px;color:#0ea5e9;margin-bottom:8px;">%s</div>'
            . '<div class="ultraguard-compare-content" style="border:2px solid var(--ug-primary,#0ea5e9);border-radius:var(--ug-radius-md,8px);padding:16px;">%s</div>'
            . '</div>'
            . '</div>',
            $id_attr, $class_attr,
            esc_html( $scheme['before_label'] ),
            wp_kses_post( $scheme['before'] ),
            esc_html( $scheme['after_label'] ),
            wp_kses_post( $scheme['after'] )
        );
        $output = $instance->after_render( $output, $scheme, $context );
        self::$render_cache[ $cache_key ] = $output;
        return $output;
    }

    /**
     * Render skeleton-loader display
     * CSS skeleton placeholder while content loads.
     */
    public static function render_skeleton_loader( $scheme, $context ) {
        $cache_key = 'render_skeleton_loader_' . md5( wp_json_encode( array( $scheme, $context ) ) );
        if ( isset( self::$render_cache[ $cache_key ] ) ) {
            return self::$render_cache[ $cache_key ];
        }

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );

        $scheme = wp_parse_args( $scheme, [
            'lines'  => 3,
            'avatar' => false,
            'card'   => false,
            'id'     => '',
            'class'  => '',
        ] );

        $id_attr    = $scheme['id']    ? ' id="' . esc_attr( $scheme['id'] )    . '"' : '';
        $class_attr = $scheme['class'] ? ' ' . esc_attr( $scheme['class'] )            : '';

        $avatar_html = $scheme['avatar']
            ? '<div class="ug-skeleton ug-skeleton-circle" style="width:40px;height:40px;border-radius:50%;margin-bottom:12px;"></div>'
            : '';

        $lines_html = '';
        for ( $i = 0; $i < absint( $scheme['lines'] ); $i++ ) {
            $width = ( $i === absint( $scheme['lines'] ) - 1 ) ? '60%' : '100%';
            $lines_html .= sprintf(

                '<div class="ug-skeleton ug-skeleton-text" style="height:14px;border-radius:4px;margin-bottom:8px;width:%s;"></div>',
                $width
            );
        }

        $wrapper_style = $scheme['card']
            ? 'background:#fff;border:1px solid var(--ug-border,#e2e8f0);border-radius:var(--ug-radius-md,8px);padding:20px;'
            : '';

        $output = sprintf(
            '<div%s class="ultraguard-skeleton-loader%s" style="%s">%s%s</div>',
            $id_attr, $class_attr, $wrapper_style, $avatar_html, $lines_html
        );
        $output = $instance->after_render( $output, $scheme, $context );
        self::$render_cache[ $cache_key ] = $output;
        return $output;
    }

    /**
     * Render collapsible display
     * Expandable/collapsible section with a toggle header.
     */
    public static function render_collapsible( $scheme, $context ) {
        $cache_key = 'render_collapsible_' . md5( wp_json_encode( array( $scheme, $context ) ) );
        if ( isset( self::$render_cache[ $cache_key ] ) ) {
            return self::$render_cache[ $cache_key ];
        }

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );

        $scheme = wp_parse_args( $scheme, [
            'title'     => '',
            'content'   => '',
            'open'      => false,
            'icon'      => 'dashicons-arrow-down-alt2',
            'id'        => 'ultraguard-collapsible-' . uniqid(),
            'class'     => '',
        ] );

        $id_attr       = $scheme['id'] ? ' id="' . esc_attr( $scheme['id'] )    . '"' : '';
        $class_attr    = $scheme['class'] ? ' ' . esc_attr( $scheme['class'] )        : '';
        $body_id       = esc_attr( $scheme['id'] ) . '-body';
        $open_attr     = $scheme['open'] ? ' open' : '';
        $open_style    = $scheme['open'] ? '' : 'display:none;';

        $onclick_js = esc_attr( 'var b=document.getElementById(\"' . $body_id . '\");b.style.display=b.style.display===\"none\"?\"\":\"none\";' );
        $output = sprintf(
            '<div%s class="ultraguard-collapsible%s">'
            . '<button type="button" class="ultraguard-collapsible-header" '
            . 'onclick="' . $onclick_js . '" '
            . 'style="width:100%%;text-align:left;background:var(--ug-bg-secondary,#f8fafc);border:1px solid var(--ug-border,#e2e8f0);border-radius:var(--ug-radius-md,8px);padding:12px 16px;cursor:pointer;display:flex;align-items:center;gap:8px;font-weight:600;">'
            . '%s%s'
            . '</button>'
            . '<div id="%s" class="ultraguard-collapsible-body" style="padding:16px;%s">%s</div>'
            . '</div>',
            $id_attr, $class_attr,
            $instance->render_ui_icon( $scheme['icon'] ),
            esc_html( $scheme['title'] ),
            $body_id, $open_style,
            wp_kses_post( $scheme['content'] )
        );
        $output = $instance->after_render( $output, $scheme, $context );
        self::$render_cache[ $cache_key ] = $output;
        return $output;
    }

    /**
     * Render tooltip display
     * Inline text with a hoverable tooltip.
     */
    public static function render_tooltip( $scheme, $context ) {
        $cache_key = 'render_tooltip_' . md5( wp_json_encode( array( $scheme, $context ) ) );
        if ( isset( self::$render_cache[ $cache_key ] ) ) {
            return self::$render_cache[ $cache_key ];
        }

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );

        $scheme = wp_parse_args( $scheme, [
            'text'     => '',
            'tip'      => '',
            'position' => 'top',
            'icon'     => 'dashicons-info',
            'id'       => '',
            'class'    => '',
        ] );

        $id_attr    = $scheme['id']    ? ' id="' . esc_attr( $scheme['id'] )    . '"' : '';
        $class_attr = $scheme['class'] ? ' ' . esc_attr( $scheme['class'] )            : '';

        $output = sprintf(
            '<span%s class="ultraguard-tooltip-wrapper%s" style="position:relative;display:inline-flex;align-items:center;gap:4px;cursor:help;" title="%s">'
            . '%s'
            . '%s'
            . '</span>',
            $id_attr, $class_attr,
            esc_attr( $scheme['tip'] ),
            esc_html( $scheme['text'] ),
            $instance->render_ui_icon( $scheme['icon'], '', array( 'style' => 'font-size:14px;width:14px;height:14px;color:#94a3b8;' ) )
        );
        $output = $instance->after_render( $output, $scheme, $context );
        self::$render_cache[ $cache_key ] = $output;
        return $output;
    }

    /**
     * Render breadcrumb display
     * Navigation breadcrumb trail from an array of items.
     */
    public static function render_breadcrumb( $scheme, $context ) {
        $cache_key = 'render_breadcrumb_' . md5( wp_json_encode( array( $scheme, $context ) ) );
        if ( isset( self::$render_cache[ $cache_key ] ) ) {
            return self::$render_cache[ $cache_key ];
        }

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );

        $scheme = wp_parse_args( $scheme, [
            'items'     => [],
            'separator' => '›',
            'id'        => '',
            'class'     => '',
        ] );

        $items = is_array( $scheme['items'] ) ? $scheme['items'] : [];
        $crumbs = '';
        $total  = count( $items );

        foreach ( $items as $i => $item ) {
            $item = is_array( $item ) ? $item : [ 'label' => $item ];
            $item = wp_parse_args( $item, [ 'label' => '', 'url' => '' ] );
            $is_last = ( $i === $total - 1 );

            if ( $is_last || empty( $item['url'] ) ) {
                $crumbs .= sprintf(

                    '<li class="ultraguard-breadcrumb-item%s" aria-current="%s">%s</li>',
                    $is_last ? ' ultraguard-breadcrumb-current' : '',
                    $is_last ? 'page' : 'false',
                    esc_html( $item['label'] )
                );
            } else {
                $crumbs .= sprintf(

                    '<li class="ultraguard-breadcrumb-item"><a href="%s" class="ultraguard-breadcrumb-link">%s</a></li>',
                    esc_url( $item['url'] ), esc_html( $item['label'] )
                );
            }

            if ( ! $is_last ) {
                $crumbs .= sprintf(

                    '<li class="ultraguard-breadcrumb-separator" aria-hidden="true">%s</li>',
                    esc_html( $scheme['separator'] )
                );
            }
        }

        $id_attr    = $scheme['id']    ? ' id="' . esc_attr( $scheme['id'] )    . '"' : '';
        $class_attr = $scheme['class'] ? ' ' . esc_attr( $scheme['class'] )            : '';

        $output = sprintf(
            '<nav%s class="ultraguard-breadcrumbs%s" aria-label="%s">'
            . '<ol class="ultraguard-breadcrumb-list" style="display:flex;list-style:none;padding:0;margin:0;gap:4px;flex-wrap:wrap;font-size:13px;align-items:center;">%s</ol>'
            . '</nav>',
            $id_attr, $class_attr,
            esc_attr__( 'Breadcrumb', 'ultraguard-security-suite' ),
            $crumbs
        );
        $output = $instance->after_render( $output, $scheme, $context );
        self::$render_cache[ $cache_key ] = $output;
        return $output;
    }

}
