<?php
/**
 * Optimized Data Renderer class file
 *
 * This file contains the optimized DataRenderer class which handles
 * multiple rendering strategies for dynamic content with performance
 * optimizations. It provides efficient caching, reduced memory usage,
 * and optimized algorithms for rendering dynamic data, AJAX content,
 * templates, shortcodes, widget areas, and navigation menus.
 *
 * The class implements static methods with comprehensive caching
 * mechanisms and uses modern PHP features like class constants and
 * optimized algorithms for better performance in high-traffic scenarios.
 *
 * @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/optimized-data-rendering
 */

namespace UltraguardPro\view;

defined( 'ABSPATH' ) || exit;

/**
 * Optimized Data Renderer
 *
 * Handles all data component rendering with performance optimizations
 * including comprehensive caching, efficient memory usage, and optimized
 * algorithms. Provides multiple rendering strategies with built-in error
 * handling, security validation, and extensibility through hooks.
 *
 * This class extends BaseRenderer and implements a highly optimized
 * architecture with static rendering methods, singleton pattern for
 * resource management, and intelligent caching to minimize redundant
 * operations. It's designed for high-performance environments with
 * frequent rendering operations.
 *
 * @package    UltraguardPro\view
 * @author     Ultraguard Pro Team
 * @version    1.0.0
 * @since      1.0.0
 * @see        \UltraguardPro\view\BaseRenderer
 * @see        \UltraguardPro\view\DataLoader
 */
class DataRenderer extends BaseRenderer {

    /**
     * Cache for rendered outputs
     *
     * Stores rendered HTML content keyed by cache keys to prevent
     * redundant rendering operations. Uses static array for
     * request-level caching.
     *
     * @var array<string, string>
     * @access private
     * @static
     */
    private static $rendered_cache = array();

    /**
     * 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;

    /**
     * Cache key salt for uniqueness
     *
     * Static salt value used to ensure cache key uniqueness across
     * different installations and environments.
     *
     * @var string
     * @access private
     * @static
     */
    private static $cache_salt = '';

    /**
     * Default scheme values for each render type
     *
     * Class constant defining default configuration values for each
     * rendering method. Using class constants for better performance
     * and memory efficiency.
     *
     * @var array<string, array<string, mixed>>
     * @access private
     * @const
     */
    private const DEFAULT_SCHEMES = array(
        'dynamic' => array(
            'source'          => array(),
            'template'        => '',
            'default_content' => '',
            'loading_text'    => 'Gathering data…',
        ),
        'ajax' => array(
            'ajax_action'     => '',
            'nonce'           => '',
            'loading_text'    => 'Gathering data…',
            'error_text'      => 'Failed to load content',
            'container_class' => 'ultraguard-ajax-content',
        ),
        'template' => array(
            'template_path'   => '',
            'template_data'   => array(),
            'default_content' => '',
            'safe_mode'       => true,
        ),
        'shortcode' => array(
            'shortcode'       => '',
            'attributes'      => array(),
            'content'         => '',
            'default_content' => '',
        ),
        'widget_area' => array(
            'sidebar_id'      => '',
            'default_content' => '',
            'wrapper_class'   => 'ultraguard-widget-area',
        ),
        'menu' => array(
            'menu_id'         => '',
            'menu_class'      => 'ultraguard-menu',
            'depth'           => 0,
            'container'       => false,
            'fallback_cb'     => false,
            'default_content' => '',
        ),
    );

    /**
     * Template render types and their corresponding methods
     *
     * Mapping of template type identifiers to internal render methods.
     * Used for efficient template type resolution without conditionals.
     *
     * @var array<string, string>
     * @access private
     * @const
     */
    private const TEMPLATE_TYPES = array(
        'list'    => 'render_list_template',
        'table'   => 'render_table_template',
        'cards'   => 'render_cards_template',
        'json'    => 'render_json_template',
        'raw'     => 'render_raw_template',
        'default' => 'render_default_template',
    );

    /**
     * Get singleton instance
     *
     * Returns the singleton instance of DataRenderer 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;
    }

    /**
     * Get cache key for scheme and context
     *
     * Generates a unique cache key based on scheme data, context, and
     * render type. Includes salt for uniqueness across environments.
     *
     * @param  array<string, mixed> $scheme   Scheme data
     * @param  array<string, mixed> $context  Context data
     * @param  string               $type     Render type identifier
     * @return string                        Unique cache key
     * @access private
     * @static
     */
    private static function get_cache_key( $scheme, $context, $type ) {
        if ( ! self::$cache_salt ) {
            self::$cache_salt = wp_hash( __CLASS__ );
        }

        return $type . '_' . md5( self::$cache_salt . wp_json_encode( array( $scheme, $context ) ) );
    }

    /**
     * Render dynamic content
     *
     * Renders dynamic content by loading data from specified source and
     * applying template processing. Includes intelligent caching,
     * optimized error handling, and support for callable templates.
     *
     * @param  array<string, mixed> $scheme   Dynamic content scheme configuration
     * @param  array<string, mixed> $context  Context data for rendering
     * @return string                         Rendered HTML content
     * @access public
     * @static
     *
     * @example
     * $html = DataRenderer::render_dynamic([
     *     'source' => ['type' => 'posts', 'args' => ['posts_per_page' => 5]],
     *     'template' => 'cards'
     * ], ['user_id' => get_current_user_id()]);
     */
    public static function render_dynamic( $scheme, $context ) {
        $cache_key = self::get_cache_key( $scheme, $context, 'dynamic' );

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

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );
        $scheme   = wp_parse_args( $scheme, self::DEFAULT_SCHEMES['dynamic'] );

        $source   = $scheme['source'];
        $template = $scheme['template'];

        $data = DataLoader::get_instance()->load( $source, $context );

        $data_is_empty = ( null === $data || ( is_array( $data ) && empty( $data ) ) );

        if ( $data_is_empty && ! empty( $scheme['default_content'] ) ) {
            $content = $scheme['default_content'];
        } elseif ( $template && is_callable( $template ) ) {
            try {
                $instance->dispatch_hook( 'ultraguard_before_template_callback', array( $template, $data, $context ) );
                $content = call_user_func( $template, $data, $context );
                $instance->dispatch_hook( 'ultraguard_after_template_callback', array( $template, $data, $context, $content ) );
            } catch ( \Exception $e ) {
                $content = $instance->handle_render_error(
                    /* translators: %s: string */
                    sprintf( __( 'Template callback error: %s', 'ultraguard-security-suite'), $e->getMessage() ),
                    $scheme
                );
            }
        } else {
            $content = $instance->render_data_template( $data, $template, $context );
        }

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

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

        return $output;
    }

    /**
     * Render AJAX content
     *
     * Renders AJAX-enabled content container with optimized markup,
     * automatic nonce generation, and efficient error handling.
     *
     * @param  array<string, mixed> $scheme   AJAX content scheme configuration
     * @param  array<string, mixed> $context  Context data for rendering
     * @return string                         Rendered HTML content
     * @access public
     * @static
     *
     * @example
     * $html = DataRenderer::render_ajax_content([
     *     'ajax_action' => 'load_user_profile',
     *     'loading_text' => 'Loading profile...'
     * ], []);
     */
    public static function render_ajax_content( $scheme, $context ) {
        $cache_key = self::get_cache_key( $scheme, $context, 'ajax' );

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

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );
        $scheme   = wp_parse_args( $scheme, self::DEFAULT_SCHEMES['ajax'] );

        if ( empty( $scheme['ajax_action'] ) ) {
            return $instance->handle_render_error(
                __( 'AJAX action is required', 'ultraguard-security-suite' ),
                $scheme
            );
        }

        if ( empty( $scheme['nonce'] ) ) {
            $scheme['nonce'] = wp_create_nonce( 'ultraguard_admin_nonce' );
        }

        $content = sprintf(
            '<div class="%s" data-ajax-action="%s" data-nonce="%s" data-error-text="%s">' .
            '<div class="ultraguard-ajax-loading">' .
            '<div class="ultraguard-loading-spinner"></div>' .
            '<p>%s</p>' .
            '</div>' .
            '<div class="ultraguard-ajax-error" style="display: none;">' .
            '<p>%s</p>' .
            '</div>' .
            '</div>',
            esc_attr( sanitize_html_class( $scheme['container_class'] ) ),
            esc_attr( sanitize_text_field( $scheme['ajax_action'] ) ),
            esc_attr( sanitize_text_field( $scheme['nonce'] ) ),
            esc_attr( sanitize_text_field( $scheme['error_text'] ) ),
            esc_html( $scheme['loading_text'] ),
            esc_html( $scheme['error_text'] )
        );

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

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

        return $output;
    }

    /**
     * Render template file
     *
     * Renders content from PHP template files with security validation,
     * optimized file checking, and safe data extraction.
     *
     * @param  array<string, mixed> $scheme   Template scheme configuration
     * @param  array<string, mixed> $context  Context data for rendering
     * @return string                         Rendered HTML content
     * @access public
     * @static
     *
     * @example
     * $html = DataRenderer::render_template([
     *     'template_path' => get_stylesheet_directory() . '/templates/profile.php',
     *     'template_data' => ['user' => wp_get_current_user()]
     * ], []);
     */
    public static function render_template( $scheme, $context ) {
        $cache_key = self::get_cache_key( $scheme, $context, 'template' );

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

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );
        $scheme   = wp_parse_args( $scheme, self::DEFAULT_SCHEMES['template'] );

        $template_path = $scheme['template_path'];
        $template_data = $scheme['template_data'];
        $safe_mode     = (bool) $scheme['safe_mode'];

        if ( empty( $template_path ) ) {
            return $instance->handle_render_error(
                __( 'Template path is required', 'ultraguard-security-suite'),
                $scheme
            );
        }

        $real_path = realpath( $template_path );
        if ( false === $real_path ) {
            return $instance->handle_render_error(
                __( 'Invalid template path', 'ultraguard-security-suite'),
                $scheme
            );
        }

        if ( ! is_readable( $real_path ) ) {
            return $instance->handle_render_error(
                /* translators: %s: string */
                sprintf( __( 'Template file not readable: %s', 'ultraguard-security-suite'), esc_html( $template_path ) ),
                $scheme
            );
        }

        $canonical_path = realpath( readlink( $real_path ) ?: $real_path );

        $allowed_paths = apply_filters( 'ultraguard_allowed_template_paths', array(
            get_template_directory(),
            get_stylesheet_directory(),
            WP_CONTENT_DIR,
        ) );

        $is_allowed = false;
        foreach ( $allowed_paths as $allowed_path ) {
            $allowed_real = realpath( $allowed_path );
            if ( false !== $allowed_real && 0 === strpos( $canonical_path, $allowed_real ) ) {
                $is_allowed = true;
                break;
            }
        }

        if ( ! $is_allowed ) {
            return $instance->handle_render_error(
                __( 'Template path is not allowed', 'ultraguard-security-suite'),
                $scheme
            );
        }

        try {
            $safe_data = array();
            foreach ( $template_data as $key => $value ) {
                if ( is_string( $key ) && preg_match( '/^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$/', $key ) ) {
                    $safe_data[ $key ] = $value;
                }
            }

            $instance->dispatch_hook( 'ultraguard_before_template_include', array( $template_path, $safe_data, $scheme ) );

            ob_start();
            if ( $safe_mode ) {
                extract( $safe_data, EXTR_SKIP );
                include $real_path;
            } else {
                extract( $template_data, EXTR_SKIP );
                include $real_path;
            }
            $content = ob_get_clean();

            $instance->dispatch_hook( 'ultraguard_after_template_include', array( $template_path, $safe_data, $scheme, $content ) );

        } catch ( \Exception $e ) {
            $content = $instance->handle_render_error(
                /* translators: %s: string */
                sprintf( __( 'Template rendering error: %s', 'ultraguard-security-suite'), $e->getMessage() ),
                $scheme
            );
        }

        if ( empty( trim( $content ) ) && ! empty( $scheme['default_content'] ) ) {
            $content = $scheme['default_content'];
        }

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

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

        return $output;
    }

    /**
     * Render shortcode
     *
     * Renders WordPress shortcode with optimized attribute handling,
     * JSON support for complex values, and efficient error management.
     *
     * @param  array<string, mixed> $scheme   Shortcode scheme configuration
     * @param  array<string, mixed> $context  Context data for rendering
     * @return string                         Rendered HTML content
     * @access public
     * @static
     *
     * @example
     * $html = DataRenderer::render_shortcode([
     *     'shortcode' => 'my_custom_gallery',
     *     'attributes' => ['ids' => '1,2,3', 'columns' => 3]
     * ], []);
     */
    public static function render_shortcode( $scheme, $context ) {
        $cache_key = self::get_cache_key( $scheme, $context, 'shortcode' );

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

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );
        $scheme   = wp_parse_args( $scheme, self::DEFAULT_SCHEMES['shortcode'] );

        $shortcode        = $scheme['shortcode'];
        $attributes       = $scheme['attributes'];
        $shortcode_content = $scheme['content'];

        if ( empty( $shortcode ) ) {
            return $instance->handle_render_error(
                __( 'Shortcode name is required', 'ultraguard-security-suite'),
                $scheme
            );
        }

        $shortcode_string = '[' . sanitize_text_field( $shortcode );

        if ( ! empty( $attributes ) && is_array( $attributes ) ) {
            foreach ( $attributes as $key => $value ) {
                if ( ! is_string( $key ) || '' === $key ) {
                    continue;
                }

                $safe_key = sanitize_key( $key );

                if ( is_array( $value ) || is_object( $value ) ) {
                    $json_value = wp_json_encode( $value );
                    if ( false !== $json_value ) {
                        $shortcode_string .= sprintf( ' %s="%s"', $safe_key, esc_attr( $json_value ) );
                    }
                } elseif ( is_bool( $value ) ) {
                    $shortcode_string .= sprintf( ' %s="%s"', $safe_key, $value ? 'true' : 'false' );
                } elseif ( is_numeric( $value ) ) {
                    $shortcode_string .= sprintf( ' %s="%s"', $safe_key, (string) $value );
                } elseif ( is_string( $value ) ) {
                    $shortcode_string .= sprintf( ' %s="%s"', $safe_key, esc_attr( $value ) );
                }
            }
        }

        $shortcode_string .= ']';

        if ( ! empty( $shortcode_content ) ) {
            $shortcode_string = substr( $shortcode_string, 0, -1 ) . sprintf( ']%s[/%s]', $shortcode_content, $shortcode );
        }

        $instance->dispatch_hook( 'ultraguard_before_shortcode_render', array( $shortcode_string, $scheme ) );
        $content = do_shortcode( $shortcode_string );
        $instance->dispatch_hook( 'ultraguard_after_shortcode_render', array( $shortcode_string, $scheme, $content ) );

        if ( empty( trim( $content ) ) && ! empty( $scheme['default_content'] ) ) {
            $content = $scheme['default_content'];
        }

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

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

        return $output;
    }

    /**
     * Render widget area
     *
     * Renders WordPress widget area (sidebar) with optimized active
     * checking and efficient fallback content handling.
     *
     * @param  array<string, mixed> $scheme   Widget area scheme configuration
     * @param  array<string, mixed> $context  Context data for rendering
     * @return string                         Rendered HTML content
     * @access public
     * @static
     *
     * @example
     * $html = DataRenderer::render_widget_area([
     *     'sidebar_id' => 'footer-widgets',
     *     'wrapper_class' => 'custom-footer-widgets'
     * ], []);
     */
    public static function render_widget_area( $scheme, $context ) {
        $cache_key = self::get_cache_key( $scheme, $context, 'widget_area' );

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

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );
        $scheme   = wp_parse_args( $scheme, self::DEFAULT_SCHEMES['widget_area'] );

        $sidebar_id = $scheme['sidebar_id'];

        if ( empty( $sidebar_id ) ) {
            return $instance->handle_render_error(
                __( 'Sidebar ID is required', 'ultraguard-security-suite'),
                $scheme
            );
        }

        if ( ! is_active_sidebar( $sidebar_id ) ) {
            if ( ! empty( $scheme['default_content'] ) ) {
                $content = $scheme['default_content'];
            } else {
                return $instance->handle_render_error(
                    /* translators: %s: string */
                    sprintf( __( 'Widget area not active: %s', 'ultraguard-security-suite'), esc_html( $sidebar_id ) ),
                    $scheme
                );
            }
        } else {
            ob_start();
            dynamic_sidebar( $sidebar_id );
            $content = ob_get_clean();
        }

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

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

        return $output;
    }

    /**
     * Render menu
     *
     * Renders WordPress navigation menu with optimized argument
     * handling, automatic sanitization, and efficient error management.
     *
     * @param  array<string, mixed> $scheme   Menu scheme configuration
     * @param  array<string, mixed> $context  Context data for rendering
     * @return string                         Rendered HTML content
     * @access public
     * @static
     *
     * @example
     * $html = DataRenderer::render_menu([
     *     'menu_id' => 'primary-navigation',
     *     'depth' => 2,
     *     'menu_class' => 'nav-primary'
     * ], []);
     */
    public static function render_menu( $scheme, $context ) {
        $cache_key = self::get_cache_key( $scheme, $context, 'menu' );

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

        $instance = self::get_instance();
        $scheme   = $instance->before_render( $scheme, $context );
        $scheme   = wp_parse_args( $scheme, self::DEFAULT_SCHEMES['menu'] );

        $menu_id    = $scheme['menu_id'];
        $menu_class = $scheme['menu_class'];
        $depth      = absint( $scheme['depth'] );

        if ( empty( $menu_id ) ) {
            return $instance->handle_render_error(
                __( 'Menu ID is required', 'ultraguard-security-suite'),
                $scheme
            );
        }

        $args = array(
            'menu'            => $menu_id,
            'container'       => $scheme['container'],
            'menu_class'      => sanitize_html_class( $menu_class ),
            'depth'           => $depth,
            'echo'            => false,
            'fallback_cb'     => $scheme['fallback_cb'],
        );

        $instance->dispatch_hook( 'ultraguard_before_menu_render', array( $menu_id, $args ) );
        $content = wp_nav_menu( $args );
        $instance->dispatch_hook( 'ultraguard_after_menu_render', array( $menu_id, $args, $content ) );

        if ( ! $content ) {
            if ( ! empty( $scheme['default_content'] ) ) {
                $content = $scheme['default_content'];
            } else {
                return $instance->handle_render_error(
                    /* translators: %s: string */
                    sprintf( __( 'Menu not found: %s', 'ultraguard-security-suite'), esc_html( $menu_id ) ),
                    $scheme
                );
            }
        }

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

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

        return $output;
    }

    /**
     * Dispatch hook with optimized parameters
     *
     * Efficiently dispatches WordPress action hooks only when there
     * are registered actions, minimizing unnecessary function calls.
     *
     * @param  string $hook_name Hook name to dispatch
     * @param  array<mixed> $args Hook arguments
     * @return void
     * @access private
     */
    private function dispatch_hook( $hook_name, $args = array() ) {
        if ( has_action( $hook_name ) ) {
            do_action_ref_array( $hook_name, $args );
        }
    }

    /**
     * Render data template
     *
     * Internal method to render data using specified template type.
     * Supports built-in templates and custom templates via filter hooks.
     * Uses efficient method lookup via constant mapping.
     *
     * @param  mixed                $data     Data to render
     * @param  string               $template Template type identifier
     * @param  array<string, mixed> $context  Context data for rendering
     * @return string                         Rendered content
     * @access protected
     *
     * @see self::TEMPLATE_TYPES
     */
    protected function render_data_template( $data, $template, $context ) {
        $template = $template ?: 'default';

        $custom_template = apply_filters( "ultraguard_data_template_{$template}", null, $data, $context );
        if ( null !== $custom_template ) {
            return $custom_template;
        }

        $method_name = self::TEMPLATE_TYPES[ $template ] ?? self::TEMPLATE_TYPES['default'];

        if ( method_exists( $this, $method_name ) ) {
            return $this->$method_name( $data, $context );
        }

        return $this->render_default_template( $data, $context );
    }

    /**
     * Render list template
     *
     * Renders data as an unordered list with optimized iteration
     * and automatic flattening of complex data items.
     *
     * @param  array<mixed>         $data    Data to render as list
     * @param  array<string, mixed> $context Context data for rendering
     * @return string                        List HTML
     * @access protected
     */
    protected function render_list_template( $data, $context ) {
        if ( ! is_array( $data ) || empty( $data ) ) {
            return $this->render_empty_data( $data, $context );
        }

        $items_html = '';
        $index = 0;
        foreach ( $data as $item ) {
            if ( is_array( $item ) || is_object( $item ) ) {
                $item = $this->flatten_data( $item );
            }
            $items_html .= sprintf(
                '<li class="ultraguard-list-item ultraguard-list-item-%d"><span class="ultraguard-list-item-text">%s</span></li>',
                $index++,
                esc_html( (string) $item )
            );
        }

        return sprintf( '<ul class="ultraguard-data-list">%s</ul>', $items_html );
    }

    /**
     * Render table template
     *
     * Renders data as HTML table with automatic header generation
     * from array keys and efficient row iteration.
     *
     * @param  array<mixed>         $data    Data to render as table
     * @param  array<string, mixed> $context Context data for rendering
     * @return string                        Table HTML
     * @access protected
     */
    protected function render_table_template( $data, $context ) {
        if ( ! is_array( $data ) || empty( $data ) ) {
            return $this->render_empty_data( $data, $context );
        }

        $first_row = reset( $data );
        $headers_html = '';

        if ( is_array( $first_row ) ) {
            foreach ( array_keys( $first_row ) as $header ) {
                $headers_html .= sprintf( '<th scope="col">%s</th>', esc_html( $header ) );
            }
        } else {
            $headers_html = '<th scope="col">' . esc_html__( 'Value', 'ultraguard-security-suite') . '</th>';
        }

        $rows_html = '';
        $index = 0;
        foreach ( $data as $row ) {
            $row_html = '';

            if ( is_array( $row ) ) {
                foreach ( $row as $cell ) {
                    $row_html .= sprintf( '<td>%s</td>', esc_html( (string) $cell ) );
                }
            } else {
                $row_html = sprintf( '<td>%s</td>', esc_html( (string) $row ) );
            }

            $rows_html .= sprintf(
                '<tr class="ultraguard-table-row ultraguard-table-row-%d">%s</tr>',
                $index++,
                $row_html
            );
        }

        return sprintf(
            '<table class="ultraguard-data-table">' .
            '<thead><tr>%s</tr></thead>' .
            '<tbody>%s</tbody>' .
            '</table>',
            $headers_html,
            $rows_html
        );
    }

    /**
     * Render cards template
     *
     * Renders data as card components with title, content, and optional
     * footer. Supports structured card data with automatic defaults.
     *
     * @param  array<array>         $data    Data to render as cards
     * @param  array<string, mixed> $context Context data for rendering
     * @return string                        Cards HTML
     * @access protected
     */
    protected function render_cards_template( $data, $context ) {
        if ( ! is_array( $data ) || empty( $data ) ) {
            return $this->render_empty_data( $data, $context );
        }

        $cards_html = '';
        $index = 0;
        foreach ( $data as $card_data ) {
            $card_data = wp_parse_args( $card_data, array(
                /* translators: %d: integer */
                'title'   => sprintf( __( 'Item %d', 'ultraguard-security-suite'), ++$index ),
                'content' => '',
                'footer'  => '',
                'class'   => 'ultraguard-data-card',
            ) );

            $cards_html .= sprintf(
                '<div class="%s">' .
                '<div class="ultraguard-data-card-body">' .
                '<h3 class="ultraguard-data-card-title">%s</h3>' .
                '<div class="ultraguard-data-card-content">%s</div>' .
                '</div>' .
                '%s' .
                '</div>',
                esc_attr( sanitize_html_class( $card_data['class'] ) ),
                esc_html( is_array( $card_data['title'] ) ? (string)( $card_data['title']['text'] ?? $card_data['title']['content'] ?? wp_json_encode( $card_data['title'] ) ) : (string)( $card_data['title'] ) ),
                wp_kses_post( is_array( $card_data['content'] ) ? esc_html( wp_json_encode( $card_data['content'] ) ) : (string)( $card_data['content'] ) ),
                $card_data['footer'] ? sprintf( '<div class="ultraguard-data-card-footer">%s</div>', wp_kses_post( is_array( $card_data['footer'] ) ? esc_html( wp_json_encode( $card_data['footer'] ) ) : (string)( $card_data['footer'] ) ) ) : ''
            );
        }

        return sprintf( '<div class="ultraguard-data-cards">%s</div>', $cards_html );
    }

    /**
     * Render JSON template
     *
     * Renders data as formatted JSON with pretty printing for
     * debugging and data inspection purposes.
     *
     * @param  mixed                $data    Data to render as JSON
     * @param  array<string, mixed> $context Context data for rendering
     * @return string                        JSON HTML
     * @access protected
     */
    protected function render_json_template( $data, $context ) {
        $json_string = wp_json_encode( $data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE );

        if ( false === $json_string ) {
            $json_string = __( 'Unable to encode data as JSON', 'ultraguard-security-suite');
        }

        return sprintf(
            '<pre class="ultraguard-data-json"><code>%s</code></pre>',
            esc_html( $json_string )
        );
    }

    /**
     * Render raw template
     *
     * Renders data with minimal processing, passing scalar values
     * through wp_kses_post() for safety.
     *
     * @param  mixed                $data    Data to render raw
     * @param  array<string, mixed> $context Context data for rendering
     * @return string                        Raw HTML
     * @access protected
     */
    protected function render_raw_template( $data, $context ) {
        if ( is_array( $data ) || is_object( $data ) ) {
            return $this->render_default_template( $data, $context );
        }

        return wp_kses_post( is_array( $data ) ? esc_html( wp_json_encode( $data ) ) : (string)( $data ) );
    }

    /**
     * Render default template
     *
     * Default rendering method for unhandled template types.
     * Displays complex data with print_r() formatting.
     *
     * @param  mixed                $data    Data to render
     * @param  array<string, mixed> $context Context data for rendering
     * @return string                        Default HTML
     * @access protected
     */
    protected function render_default_template( $data, $context ) {
        if ( is_array( $data ) || is_object( $data ) ) {
            return sprintf(
                '<pre class="ultraguard-data-default"><code>%s</code></pre>',
                esc_html( wp_json_encode( $data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_PARTIAL_OUTPUT_ON_ERROR ) ?: '[complex data]' )
            );
        }

        return sprintf( '<div class="ultraguard-data-scalar">%s</div>', esc_html( (string) $data ) );
    }

    /**
     * Render empty data state
     *
     * Renders user-friendly empty state message when no data
     * is available for rendering.
     *
     * @param  mixed                $data    Data that was empty
     * @param  array<string, mixed> $context Context data for rendering
     * @return string                        Empty state HTML
     * @access protected
     */
    protected function render_empty_data( $data, $context ) {
        // Show gathering overlay instead of a plain 'no data' message
        $msg = $context['empty_text'] ?? '';
        return '<div class="ultraguard-data-empty ultraguard-gathering-empty" '.
            'style="min-height:80px;display:flex;align-items:center;justify-content:center;'.
            'padding:20px;text-align:center;border:1px dashed #e2e8f0;border-radius:8px;background:rgba(0,0,0,.02);">'.
            '<div style="color:#94a3b8;">'.
            '<span class="dashicons dashicons-update ultraguard-spin-icon" '.
            'style="font-size:24px;width:24px;height:24px;display:block;margin:0 auto 8px;'.
            'animation:ultraguard-spin 1.5s linear infinite;"></span>'.
            '<p style="font-size:13px;font-weight:600;margin:0 0 4px;color:#64748b;">'.
            esc_html( $msg ?: __( 'Gathering data…', 'ultraguard-security-suite') ).'</p>'.
            '<p style="font-size:12px;margin:0;color:#94a3b8;">'.esc_html__( 'Data is being collected. Check back shortly.', 'ultraguard-security-suite').'</p>'.
            '</div></div>';
    }
    protected function flatten_data( $data ) {
        if ( is_scalar( $data ) ) {
            return (string) $data;
        }

        if ( is_array( $data ) || is_object( $data ) ) {
            $json = wp_json_encode( $data );
            return $json ?: '<code class="ultraguard-cell-json">' . esc_html__( '[complex data]', 'ultraguard-security-suite' ) . '</code>';
        }

        return __( '[Unknown Data Type]', 'ultraguard-security-suite');
    }

    /**
     * Clear cache
     *
     * Clears the internal rendered cache to free memory or reset
     * state for testing. Useful during plugin deactivation or
     * when cache invalidation is needed.
     *
     * @return void
     * @access public
     * @static
     *
     * @example
     * DataRenderer::clear_cache();
     */
    public static function clear_cache() {
        self::$rendered_cache = array();
    }
}
