<?php

namespace WPUF\UserDirectory;

/**
 * Block registration for User Directory
 *
 * @since   4.2.0
 * @package WPUF_Pro
 */
class Blocks {
    /**
     * List of block slugs to register (add more as needed)
     * Each block should have a block.json in its directory
     * Example: 'user-directory' => path/to/block.json
     *
     * @var array
     */
    protected $blocks;

    protected $current_pagination_param;

    /**
     * Constructor
     *
     * @since 4.2.0
     */
    public function __construct() {
        // Initialize blocks from centralized configuration
        $this->blocks = BlockConfig::get_block_paths();

        // Disable PHP registration to avoid double registration with JavaScript
        add_action( 'init', [ $this, 'register_blocks' ] );
        add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue_editor_assets' ] );
        add_filter( 'block_categories_all', [ $this, 'register_block_category' ], 12 );
        add_filter( 'single_post_title', [ $this, 'remove_single_profile_page_title' ], 10, 2 );
    }

    /**
     * Remove title from profile page
     *
     * @param mixed $title
     * @param mixed $post
     */
    public function remove_single_profile_page_title($title, $post) {
        if ( empty( $_GET['user'] ) ) {
            return $title;
        }

        //  if $post contains `wpuf-ud/profile` block, return empty title
        if ( strpos( $post->post_content, 'wpuf-ud/profile' ) !== false ) {
            return '';
        }

        return $title;
    }

    /**
     * Register blocks
     *
     * @since 4.2.0
     */
    public function register_blocks() {
        // Register all blocks from the $blocks property
        foreach ( $this->blocks as $block_slug => $block_json_path ) {
            $args = [];
            // Check if block.json file exists
            if ( ! file_exists( $block_json_path ) ) {
                continue;
            }
            // Add render callback for directory block
            if ( $block_slug === BlockConfig::BLOCKS['DIRECTORY'] ) {
                $args['render_callback'] = [ $this, 'render_user_directory_block' ];
            }
            // Add render callback for profile block
            if ( $block_slug === BlockConfig::BLOCKS['PROFILE'] ) {
                $args['render_callback'] = [ $this, 'render_user_profile_standalone_block' ];
            }
            // Add render callbacks for individual blocks

            if ( in_array(
                $block_slug, [
                BlockConfig::BLOCKS['AVATAR'],
                BlockConfig::BLOCKS['NAME'],
                BlockConfig::BLOCKS['BIO'],
                BlockConfig::BLOCKS['CONTACT'],
                BlockConfig::BLOCKS['CUSTOM_FIELD'],
                BlockConfig::BLOCKS['FILES'],
                BlockConfig::BLOCKS['POSTS'],
                BlockConfig::BLOCKS['COMMENTS'],
                BlockConfig::BLOCKS['TABS'],
                BlockConfig::BLOCKS['BUTTON'],
                BlockConfig::BLOCKS['SOCIAL'],
                BlockConfig::BLOCKS['MESSAGE_BUTTON'],
            ]
            ) ) {
                $args['render_callback'] = [ $this, 'render_user_block' ];
            }
            		// Add render callback for directory-item block
		if ( $block_slug === BlockConfig::BLOCKS['DIRECTORY_ITEM'] ) {
                $args['render_callback'] = [ $this, 'render_user_template_block' ];
            }
            register_block_type( $block_json_path, $args );
        }
    }

    /**
     * Enqueue editor assets
     *
     * @since 4.2.0
     */
    public function enqueue_editor_assets() {
        $asset_file = include WPUF_UD_ROOT . '/assets/js/block-user-directory.asset.php';
        wp_enqueue_script(
            'wpuf-user-directory-block',
            WPUF_UD_ROOT_URI . '/assets/js/block-user-directory.js',
            $asset_file['dependencies'],
            $asset_file['version']
        );
        wp_enqueue_style(
            'wpuf-user-directory-block-editor',
            WPUF_UD_ROOT_URI . '/assets/css/block-user-directory.css',
            [],
            $asset_file['version']
        );

        // Enqueue WordPress block editor styles to ensure CSS custom properties are available
        wp_enqueue_style( 'wp-block-library' );

        		        // Localize script with user roles and other data
		wp_localize_script(
			'wpuf-user-directory-block', 'wpufUserDirectory',
            [
                'userRoles'                       => $this->get_user_roles(),
                'users'                           => $this->get_users_for_editor(),
                'orderByOptions'                  => $this->get_order_by_options(),
                'searchableFields'                => $this->get_searchable_fields(),
                'metaKeys'                        => $this->get_meta_keys(),
                'postTypes'                       => $this->get_post_types(),
                'current_user_id'                 => get_current_user_id(),
                'current_user_can_manage_options' => current_user_can( 'manage_options' ),
                'rest_nonce'                      => wp_create_nonce( 'wp_rest' ),
                'rest_url'                        => rest_url(),
                'asset_url'                       => WPUF_UD_ASSET_URI,
            ]
		);

        // Add WPUF User Activity detection for User Tabs block
        wp_add_inline_script(
            'wpuf-user-directory-block',
            'window.wpufUserActivityExists = ' . (class_exists('WPUF_User_Activity') ? 'true' : 'false') . ';',
            'before'
        );
    }

    /**
     * Register block category
     *
     * @since 4.2.0
     *
     * @param array    $categories Block categories.
     * @param \WP_Post $post       Post object.
     *
     * @return array
     */
    public function register_block_category( $categories ) {
        array_unshift(
            $categories,
            [
                'slug'  => 'wpuf-ud',
                'title' => __( 'WPUF - User Directory', 'wpuf-pro' ),
            ]
        );

        return $categories;
    }

    /**
     * Get user roles for the block
     *
     * @since 4.2.0
     * @return array
     */
    private function get_user_roles() {
        $roles        = wp_roles()->get_names();
        $role_options = [];
        foreach ( $roles as $role => $name ) {
            $role_options[] = [
                'label' => $name,
                'value' => $role,
            ];
        }

        return $role_options;
    }

    /**
     * Get order by options for the block
     *
     * @since 4.2.0
     * @return array
     */
    private function get_order_by_options() {
        // Core user fields
        $core_fields = [
            [ 'label' => __( 'ID', 'wpuf-pro' ), 'value' => 'id' ],
            [ 'label' => __( 'Username', 'wpuf-pro' ), 'value' => 'user_login' ],
            [ 'label' => __( 'Display Name', 'wpuf-pro' ), 'value' => 'display_name' ],
            [ 'label' => __( 'Email', 'wpuf-pro' ), 'value' => 'user_email' ],
            [ 'label' => __( 'Registration Date', 'wpuf-pro' ), 'value' => 'user_registered' ],
        ];

        // Get usermeta keys using existing function
        $meta_fields_data = wpuf_get_user_meta_fields();

        // Convert to options format
        $meta_fields = [];
        if ( is_array( $meta_fields_data ) ) {
            foreach ( $meta_fields_data as $meta_key => $label ) {
                $meta_fields[] = [
                    'label' => $label,
                    'value' => $meta_key,
                ];
            }
        }

        // Combine core fields and usermeta fields
        return array_merge( $core_fields, $meta_fields );
    }

    /**
     * Convert field name to human-readable label
     *
     * @since 4.2.0
     * @param string $field_name The field name to convert
     * @return string Human-readable label
     */
    private function get_human_readable_field_label( $field_name ) {
        // Convert field name to human-readable format
        $label = $field_name;

        // Remove common prefixes
        $label = str_replace( ['user_', 'meta_'], '', $label );

        // Convert underscores to spaces
        $label = str_replace( '_', ' ', $label );

        // Capitalize words
        $label = ucwords( $label );

        // Apply general filter hook for custom label modification
        $label = apply_filters( 'wpuf_user_directory_field_label', $label, $field_name );

        return $label;
    }

    	/**
	 * Get searchable fields for the block
	 *
	 * @since 4.2.0
	 * @return array
	 */
	private function get_searchable_fields() {
		// Core user fields
		$core_fields = [
			[ 'label' => __( 'Username', 'wpuf-pro' ), 'value' => 'user_login' ],
			[ 'label' => __( 'Display Name', 'wpuf-pro' ), 'value' => 'display_name' ],
			[ 'label' => __( 'Email', 'wpuf-pro' ), 'value' => 'user_email' ],
		];

		// Get usermeta keys using existing function
		$meta_fields_data = wpuf_get_user_meta_fields();

		// Convert to options format
		$meta_fields = [];
		if ( is_array( $meta_fields_data ) ) {
			foreach ( $meta_fields_data as $meta_key => $label ) {
				$meta_fields[] = [
					'label' => $label,
					'value' => $meta_key,
				];
			}
		}

		// Combine core fields and usermeta fields
		return array_merge( $core_fields, $meta_fields );
	}

	/**
	 * Get meta keys for the block
	 *
	 * @since 4.2.0
	 * @return array
	 */
	private function get_meta_keys() {
		// Get usermeta keys using existing function
		$meta_fields_data = wpuf_get_user_meta_fields();

		// Return just the keys for backward compatibility
		return is_array( $meta_fields_data ) ? array_keys( $meta_fields_data ) : [];
	}

	/**
	 * Get users for the editor (for exclude users dropdown)
	 *
	 * @since 4.2.0
	 * @return array
	 */
	private function get_users_for_editor() {
		$users = get_users([
			'number' => 100, // Limit to 100 users for performance
			'orderby' => 'display_name',
			'order' => 'ASC',
		]);

		$user_options = [];
		foreach ( $users as $user ) {
			$user_options[] = [
				'ID' => $user->ID,
				'display_name' => $user->display_name ?: $user->user_login,
				'user_login' => $user->user_login,
			];
		}

		return $user_options;
	}

	/**
	 * Get available post types for the block
	 *
	 * @since 4.2.0
	 * @return array
	 */
	private function get_post_types() {
		$post_types = get_post_types([
			'public' => true,
			'show_ui' => true,
		], 'objects');

		$post_type_options = [];
		foreach ( $post_types as $post_type => $post_type_object ) {
			$post_type_options[] = [
				'label' => $post_type_object->labels->name,
				'value' => $post_type,
			];
		}

		return $post_type_options;
	}

	/**
	 * Get dynamic post type label for display
	 *
	 * @since 4.2.0
	 *
	 * @param string $post_type_value The post type value (e.g., 'post', 'product', 'book').
	 *
	 * @return string The formatted post type label (e.g., 'Post Title', 'Product Title', 'Book Title').
	 */
	private function get_post_type_label( $post_type_value ) {
		$post_types = $this->get_post_types();

		foreach ( $post_types as $post_type ) {
			if ( $post_type['value'] === $post_type_value ) {
				// Combine the post type label with "Title" suffix
				// This handles cases like "Post" -> "Post Title", "Product" -> "Product Title", "Book" -> "Book Title"
				return sprintf( '%s %s', $post_type['label'], __( 'Title', 'wpuf-pro' ) );
			}
		}

		// Fallback to generic "Post Title" if post type not found
		return __( 'Post Title', 'wpuf-pro' );
	}

    /**
     * Render user directory block
     *
     * @since 4.2.0
     *
     * @param array     $attributes Block attributes.
     * @param string    $content    Block content.
     * @param \WP_Block $block      Block object.
     *
     * @return string
     */
    public function render_user_directory_block( $attributes, $content, $block ) {
        // Enqueue frontend CSS only when block is rendered
        wp_enqueue_style(
            'wpuf-block-user-directory',
            WPUF_UD_ROOT_URI . '/assets/css/block-user-directory.css',
            [],
            WPUF_UD_VERSION
        );

        // Enqueue WordPress block editor styles to ensure CSS custom properties are available
        wp_enqueue_style( 'wp-block-library' );

        // Enqueue WordPress core layout styles for flexbox/grid support
        wp_enqueue_style( 'wp-block-library-theme' );

        // Enqueue frontend search/pagination JavaScript
        wp_enqueue_script(
            'wpuf-ud-search',
            WPUF_UD_ROOT_URI . '/assets/js/ud-search.js',
            [],
            WPUF_UD_VERSION,
            true
        );

        // Default attributes
        $defaults = [
            'roles'              => 'all',
            'max_item_per_page'  => 10,
            'orderby'            => 'id',
            'order'              => 'desc',
            'directory_layout'   => 'roundGrids',
            'enable_search'      => true,
            'search_placeholder' => __( 'Search Users', 'wpuf-pro' ),
            'searchable_fields'  => ['user_login', 'user_email', 'display_name'],
            'tagName'            => 'div',
        ];
        $attributes = wp_parse_args( $attributes, $defaults );

        // Get page context for better coordination with profile block
        $page_context = $this->get_page_context();

        // Check for conditional rendering - if profile parameters exist, hide directory and let user-profile block handle it
        $profile_user = $this->get_profile_user_from_query( $attributes );

        if ( $profile_user && $this->has_user_profile_block_on_page() ) {
            // Return empty string to hide directory when profile parameters exist and user-profile block is present
            // This allows the profile block to be the primary content when a specific user is selected

            // Add debug information in development mode
            if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
                $debug_info = sprintf(
                    '<!-- Directory Block Hidden: Profile parameters found. Profile Block: %s -->',
                    $page_context['has_profile_block'] ? 'Yes' : 'No'
                );
                return $debug_info;
            }

            return '<!-- Directory hidden -->';
        }

        // Get current page for pagination
        $current_page = $this->get_current_page();
        $per_page = ! empty( $attributes['max_item_per_page'] ) ? intval( $attributes['max_item_per_page'] ) : 10;
        $offset = ( $current_page - 1 ) * $per_page;

        // Get users based on query parameters
        $filters = [];
        // Map query parameters to wpuf_ud_get_users args
        if ( ! empty( $attributes['roles'] ) && $attributes['roles'] !== 'all' ) {
            $filters['roles'] = is_array( $attributes['roles'] )
                ? $attributes['roles']
                : explode( ',', $attributes['roles'] );
        }

        		// Handle exclude roles
		if ( ! empty( $attributes['exclude_roles'] ) ) {
			$filters['exclude_roles'] = is_array( $attributes['exclude_roles'] )
				? $attributes['exclude_roles']
				: explode( ',', $attributes['exclude_roles'] );
		}

		// Handle exclude users
		if ( ! empty( $attributes['exclude_users'] ) ) {
			$filters['exclude_users'] = is_array( $attributes['exclude_users'] )
				? $attributes['exclude_users']
				: explode( ',', $attributes['exclude_users'] );
		}

        $filters['per_page'] = $per_page;
        $filters['offset'] = $offset;

        // Check URL parameters first, then fall back to attributes
        $orderby_from_url = isset( $_GET['orderby'] ) ? sanitize_key( $_GET['orderby'] ) : '';
        $order_from_url = isset( $_GET['order'] ) ? sanitize_key( $_GET['order'] ) : '';
        $search_from_url = isset( $_GET['search'] ) ? sanitize_text_field( $_GET['search'] ) : '';

        if ( ! empty( $orderby_from_url ) ) {
            $filters['orderby'] = $orderby_from_url;
        } elseif ( ! empty( $attributes['orderby'] ) ) {
            // Handle comma-separated values by taking only the first field
            $orderby_value = $attributes['orderby'];
            if ( strpos( $orderby_value, ',' ) !== false ) {
                $orderby_parts = explode( ',', $orderby_value );
                $orderby_value = trim( $orderby_parts[0] ); // Take only the first field
            }

            $filters['orderby'] = sanitize_key( $orderby_value );
        }

        if ( ! empty( $order_from_url ) ) {
            $filters['order'] = strtoupper( $order_from_url ) === 'ASC' ? 'ASC' : 'DESC';
        } elseif ( ! empty( $attributes['order'] ) ) {
            $filters['order'] = strtoupper( $attributes['order'] ) === 'ASC' ? 'ASC' : 'DESC';
        }

        if ( ! empty( $search_from_url ) ) {
            $filters['search'] = $search_from_url;
        } elseif ( ! empty( $attributes['search'] ) ) {
            $filters['search'] = sanitize_text_field( $attributes['search'] );
        }



        // Get users using the existing function
        $result = function_exists( 'wpuf_ud_get_users' ) ? wpuf_ud_get_users( $filters ) : [
            'users' => [],
            'total' => 0,
        ];

        $users = $result['users'];
        $total = $result['total'];

        // If no users found, return empty content
        if ( empty( $users ) ) {
            $no_users_message = ! empty( $attributes['search'] )
                ? __( 'No users found matching your search criteria.', 'wpuf-pro' )
                : __( 'No users found.', 'wpuf-pro' );

            return '<div class="wpuf-user-directory-no-users wpuf-text-center wpuf-py-8 wpuf-px-4">
                <div class="wpuf-text-gray-500 wpuf-text-lg wpuf-mb-2">' . esc_html( $no_users_message ) . '</div>
            </div>';
        }

        // Generate unique block ID for search/pagination JavaScript
        $block_id = 'wpuf-directory-' . uniqid();
        $page_id = get_the_ID();

        // Determine layout early so we can use it in wrapper attributes
        $layout = $attributes['directory_layout'] ?? 'roundGrids';

        // Get the block wrapper attributes with styling (like Query Loop)
        $wrapper_attributes = wpuf_get_block_wrapper_attributes(
            $attributes, 'user-directory', [
                'class'                 => 'wpuf-user-directory wpuf-user-listing',
                'data-block-id'         => $block_id,
                'data-page-id'          => $page_id,
                'data-roles'            => $attributes['roles'] ?? 'all',
                'data-exclude-roles'    => $attributes['exclude_roles'] ?? '',
                'data-exclude-users'    => $attributes['exclude_users'] ?? '',
                'data-layout'           => $layout, // Add the layout attribute to the wrapper
                'data-max-item-per-page' => $per_page, // Add max items per page for AJAX requests
                'data-users-per-row'    => $attributes['usersPerRow'] ?? 3, // Add users per row for AJAX requests
                'data-avatar-size'      => $attributes['avatar_size'] ?? 'medium', // Add avatar size for AJAX requests
                'data-show-avatar'      => $attributes['show_avatar'] ?? true, // Add show avatar for table layout
                'data-avatar-shape'     => $attributes['avatar_shape'] ?? 'circle', // Add avatar shape for table layout
                'data-avatar-fallback-type' => $attributes['avatar_fallback_type'] ?? 'initial', // Add avatar fallback type for table layout
        ]
        );
        // Start building the HTML output
        $html = '<' . $attributes['tagName'] . ' ' . $wrapper_attributes . '>';

        // add sorting and searching container
        $html .= '<div class="wpuf-user-directory-header wpuf-flex wpuf-justify-between wpuf-items-center wpuf-mb-6">';

        // Add search field if enabled
        if ( $attributes['enable_search'] ) {
            $html .= $this->render_search_field( $attributes, 'block' );
        }

        // Add sorting controls if enabled
        $html .= $this->render_sorting_controls( $attributes, 'block' );

        $html .= '</div>';

        // Add wrapper for user list that JavaScript can target
        $html .= '<div class="wpuf-user-list-container">';

        // Handle different layouts (layout already determined above)

        if ( $layout === 'table' ) {
            // Render table layout with proper structure for JavaScript updates
            $html .= '<div class="wpuf-table-layout-container">';
            $html .= '<div class="wpuf-table-wrapper wpuf-ud-list wpuf-ud-list-table" data-table-wrapper="true">';
            $html .= $this->render_table_layout( $users, $attributes, 'block' );
            $html .= '</div>';
            $html .= '</div>';
        } else {
            // Render grid layout (existing logic)
            $usersPerRow  = $attributes['usersPerRow'] ?? 3;
            $grid_classes = 'wp-block-post-template is-layout-grid columns-' . $usersPerRow . ' wpuf-ud-list wpuf-ud-list-' . $layout . ' wpuf-flow-root';
            $html .= '<ul class="' . esc_attr( $grid_classes ) . '" role="list">';

            // Find the user directory item block (like Query Loop finds post-template)
            $template_block = null;

            if ( ! empty( $block->parsed_block['innerBlocks'] ) ) {
                foreach ( $block->parsed_block['innerBlocks'] as $inner_block ) {
                    if ( isset( $inner_block['blockName'] ) && $inner_block['blockName'] === 'wpuf-ud/directory-item' ) {
                        $template_block = $inner_block;
                        break;
                    }
                }
            }

            // Render each user with the template block using extracted method
            $html .= $this->render_user_list_items( $users, $template_block, $attributes, 'block' );
            $html .= '</ul>';
        }

        $html .= '</div>'; // Close user list container

        // Add pagination if needed
        $total_pages = $per_page > 0 ? (int) ceil( $total / $per_page ) : 1;
        if ( $total > $per_page && $total_pages > 1 ) {
            $html .= $this->render_block_pagination( $current_page, $total_pages, $total, $per_page, $block_id, $page_id );
        }
        $html .= '</' . $attributes['tagName'] . '>';

        return $html;
    }

    /**
     * Render table layout for user directory
     *
     * @since 4.2.0
     *
     * @param array $users Array of WP_User objects to render.
     * @param array $attributes Block attributes.
     * @param string $context Rendering context ('block' or 'ajax').
     *
     * @return string HTML content for table layout.
     */
        public function render_table_layout( $users, $attributes, $context = 'block' ) {
        $html = '';

        // Get table settings
        $show_avatar = isset( $attributes['show_avatar'] ) ? $attributes['show_avatar'] : true;
        $avatar_size = isset( $attributes['avatar_size'] ) ? $attributes['avatar_size'] : 'medium';
        $avatar_shape = isset( $attributes['avatar_shape'] ) ? $attributes['avatar_shape'] : 'circle';
        $avatar_fallback_type = isset( $attributes['avatar_fallback_type'] ) ? $attributes['avatar_fallback_type'] : 'gravatar';
        $table_columns = isset( $attributes['table_columns'] ) ? $attributes['table_columns'] : ['username', 'email', 'display_name'];

        // Ensure table_columns is an array
        if ( ! is_array( $table_columns ) ) {
            $table_columns = ['username', 'email', 'display_name'];
        }



        // Start table with proper data attributes for JavaScript updates
        $html .= '<div class="wpuf-table-container wpuf-overflow-x-auto" data-table-layout="true">';
        $html .= '<table class="wpuf-user-table wpuf-w-full wpuf-border-collapse wpuf-border wpuf-border-gray-300" data-table-users="' . count( $users ) . '">';

        // Table header
        $html .= '<thead>';
        $html .= '<tr class="wpuf-bg-gray-50">';

        // Avatar column header (if enabled)
        if ( $show_avatar ) {
            /**
             * Filter the avatar column header text in the user directory table.
             *
             * @since 4.2.0
             *
             * @param string $avatar_label The avatar column header text.
             * @param array  $attributes   Block attributes.
             */
            $avatar_label = apply_filters( 'wpuf_ud_table_avatar_header', __( 'Avatar', 'wpuf-pro' ), $attributes );
            $html .= '<th class="wpuf-px-4 wpuf-py-3 wpuf-text-left wpuf-text-xs wpuf-font-medium wpuf-text-gray-500 wpuf-uppercase wpuf-tracking-wider wpuf-border-b wpuf-border-gray-300">';
            $html .= esc_html( $avatar_label );
            $html .= '</th>';
        }

        // Dynamic column headers
        foreach ( $table_columns as $column ) {
            $column_label = $this->get_column_label( $column );
            /**
             * Filter individual column header text in the user directory table.
             *
             * @since 4.2.0
             *
             * @param string $column_label The column header text.
             * @param string $column       The column key/identifier.
             * @param array  $attributes   Block attributes.
             */
            $column_label = apply_filters( 'wpuf_ud_table_column_header', $column_label, $column, $attributes );
            $html .= '<th class="wpuf-px-4 wpuf-py-3 wpuf-text-left wpuf-text-xs wpuf-font-medium wpuf-text-gray-500 wpuf-uppercase wpuf-tracking-wider wpuf-border-b wpuf-border-gray-300">';
            $html .= esc_html( $column_label );
            $html .= '</th>';
        }

        // View Profile column header
        /**
         * Filter the actions column header text in the user directory table.
         *
         * @since 4.2.0
         *
         * @param string $actions_label The actions column header text.
         * @param array  $attributes    Block attributes.
         */
        $actions_label = apply_filters( 'wpuf_ud_table_actions_header', '', $attributes );
        $html .= '<th class="wpuf-px-4 wpuf-py-3 wpuf-text-left wpuf-text-xs wpuf-font-medium wpuf-text-gray-500 wpuf-uppercase wpuf-tracking-wider wpuf-border-b wpuf-border-gray-300">';
        $html .= esc_html( $actions_label );
        $html .= '</th>';

        $html .= '</tr>';
        $html .= '</thead>';

        // Table body with proper classes for JavaScript updates (matches existing ud-search.js expectations)
        $html .= '<tbody class="wpuf-bg-white wpuf-divide-y wpuf-divide-gray-300 wpuf-ud-tbody">';

        foreach ( $users as $user ) {
            $html .= '<tr class="wpuf-hover:wpuf-bg-gray-50">';

            // Avatar column (if enabled)
            if ( $show_avatar ) {
                $html .= '<td class="wpuf-px-4 wpuf-py-3 wpuf-whitespace-nowrap wpuf-border-b wpuf-border-gray-300">';
                $html .= $this->render_user_avatar( $user, $avatar_size, $avatar_shape, $avatar_fallback_type );
                $html .= '</td>';
            }

            // Dynamic columns
            foreach ( $table_columns as $column ) {
                $html .= '<td class="wpuf-px-4 wpuf-py-3 wpuf-whitespace-nowrap wpuf-border-b wpuf-border-gray-300">';
                $html .= $this->render_table_cell( $user, $column );
                $html .= '</td>';
            }

            // View Profile button column
            $html .= '<td class="wpuf-px-4 wpuf-py-3 wpuf-whitespace-nowrap wpuf-border-b wpuf-border-gray-300">';
            $html .= $this->render_profile_button( $user, $attributes );
            $html .= '</td>';

            $html .= '</tr>';
        }

        $html .= '</tbody>';
        $html .= '</table>';
        $html .= '</div>';

        return $html;
    }



    /**
     * Get the total number of columns for the table (including avatar and actions)
     *
     * @since 4.2.0
     *
     * @param array $attributes Block attributes.
     *
     * @return int Total column count.
     */
    private function get_table_column_count( $attributes ) {
        $show_avatar = isset( $attributes['show_avatar'] ) ? $attributes['show_avatar'] : true;
        $table_columns = isset( $attributes['table_columns'] ) ? $attributes['table_columns'] : ['username', 'email', 'display_name'];

        // Ensure table_columns is an array
        if ( ! is_array( $table_columns ) ) {
            $table_columns = ['username', 'email', 'display_name'];
        }

        // Get additional columns (same logic as render_search_results_table_rows)
        $additional_columns = [];

        // Add social fields if present
        $social_fields = isset( $attributes['social_fields'] ) ? $attributes['social_fields'] : [];
        if ( ! empty( $social_fields ) ) {
            $additional_columns = array_merge( $additional_columns, $social_fields );
        }

        // Add meta field columns if present
        $meta_field_columns = isset( $attributes['meta_field_columns'] ) ? $attributes['meta_field_columns'] : [];
        if ( ! empty( $meta_field_columns ) ) {
            $additional_columns = array_merge( $additional_columns, array_keys( $meta_field_columns ) );
        }

        // Add any other custom columns that might be defined
        $custom_columns = isset( $attributes['custom_columns'] ) ? $attributes['custom_columns'] : [];
        if ( ! empty( $custom_columns ) ) {
            $additional_columns = array_merge( $additional_columns, $custom_columns );
        }

        // Merge all columns and remove duplicates
        $all_columns = array_unique( array_merge( $table_columns, $additional_columns ) );
        $count = count( $all_columns );

        // Add avatar column if enabled
        if ( $show_avatar ) {
            $count++;
        }

        // Add actions column
        $count++;

        return $count;
    }

    /**
     * Get column label for table headers
     *
     * @since 4.2.0
     *
     * @param string $column Column key.
     *
     * @return string Column label.
     */
    private function get_column_label( $column ) {
        $labels = [
            'username' => __( 'Username', 'wpuf-pro' ),
            'first_name' => __( 'First Name', 'wpuf-pro' ),
            'last_name' => __( 'Last Name', 'wpuf-pro' ),
            'nickname' => __( 'Nickname', 'wpuf-pro' ),
            'display_name' => __( 'Display Name', 'wpuf-pro' ),
            'email' => __( 'Email', 'wpuf-pro' ),
            'website' => __( 'Website', 'wpuf-pro' ),
            'bio' => __( 'Bio', 'wpuf-pro' ),
            'registered_date' => __( 'Registration Date', 'wpuf-pro' ),
            'posts_count' => __( 'Posts Count', 'wpuf-pro' ),
            'comments_count' => __( 'Comments Count', 'wpuf-pro' )
        ];

        // If we have a predefined label, use it
        if ( isset( $labels[ $column ] ) ) {
            $label = $labels[ $column ];
        } else {
            // Handle custom meta fields and any other columns
            // Convert underscores to spaces and capitalize first letter of each word
            $label = ucwords( str_replace( '_', ' ', $column ) );
        }

        /**
         * Filter the base column label text in the user directory table.
         *
         * @since 4.2.0
         *
         * @param string $label  The column label text.
         * @param string $column The column key/identifier.
         */
        return apply_filters( 'wpuf_ud_table_column_label', $label, $column );
    }

    /**
     * Render table cell content
     *
     * @since 4.2.0
     *
     * @param \WP_User $user User object.
     * @param string $column Column key.
     *
     * @return string Cell content.
     */
    private function render_table_cell( $user, $column ) {
        switch ( $column ) {
            case 'username':
                return '<span class="wpuf-text-sm wpuf-font-medium wpuf-text-gray-900">' . esc_html( $user->user_login ) . '</span>';

            case 'first_name':
                return '<span class="wpuf-text-sm wpuf-text-gray-900">' . esc_html( get_user_meta( $user->ID, 'first_name', true ) ) . '</span>';

            case 'last_name':
                return '<span class="wpuf-text-sm wpuf-text-gray-900">' . esc_html( get_user_meta( $user->ID, 'last_name', true ) ) . '</span>';

            case 'nickname':
                return '<span class="wpuf-text-sm wpuf-text-gray-900">' . esc_html( get_user_meta( $user->ID, 'nickname', true ) ) . '</span>';

            case 'display_name':
                return '<span class="wpuf-text-sm wpuf-font-medium wpuf-text-gray-900">' . esc_html( $user->display_name ) . '</span>';

            case 'email':
                return '<span class="wpuf-text-sm wpuf-text-gray-900">' . esc_html( $user->user_email ) . '</span>';

            case 'website':
                $website = $user->user_url;
                if ( $website ) {
                    return '<a href="' . esc_url( $website ) . '" class="wpuf-text-sm wpuf-text-blue-600 hover:wpuf-text-blue-800" target="_blank" rel="noopener noreferrer">' . esc_html( $website ) . '</a>';
                }
                return '<span class="wpuf-text-sm wpuf-text-gray-400">-</span>';

            default:
                $meta_value = get_user_meta( $user->ID, $column, true );
                if ( $meta_value ) {
                    return '<span class="wpuf-text-sm wpuf-text-gray-900">' . esc_html( $meta_value ) . '</span>';
                }

                return '<span class="wpuf-text-sm wpuf-text-gray-400">-</span>';
        }
    }

    /**
     * Render user avatar for table
     *
     * @since 4.2.0
     *
     * @param \WP_User $user User object.
     * @param string $size Avatar size.
     * @param string $shape Avatar shape.
     * @param string $fallback_type Fallback type.
     *
     * @return string Avatar HTML.
     */
    private function render_user_avatar( $user, $size = 'medium', $shape = 'circle', $fallback_type = 'gravatar' ) {
        $size_classes = [
            'small' => 'wpuf-w-8 wpuf-h-8',      // 32px
            'medium' => 'wpuf-w-24 wpuf-h-24',   // 96px
            'large' => 'wpuf-w-36 wpuf-h-36',    // 150px
            'xlarge' => 'wpuf-w-72 wpuf-h-72',   // 300px
        ];

        $shape_classes = [
            'circle' => 'wpuf-rounded-full',
            'squared' => 'wpuf-rounded-none',
            'rounded' => 'wpuf-rounded-lg',
        ];

        $size_class = isset( $size_classes[ $size ] ) ? $size_classes[ $size ] : $size_classes['medium'];
        $shape_class = isset( $shape_classes[ $shape ] ) ? $shape_classes[ $shape ] : $shape_classes['circle'];

        // Use the proper avatar handling infrastructure that checks wpuf_profile_photo first
        $display_size = wpuf_ud_get_avatar_display_size( $size, 150 ); // Default custom size
        $avatar_data = wpuf_ud_get_block_avatar_data( $user, $display_size, $fallback_type );
        $avatar_url = $avatar_data['url'];
        $avatar_alt = $avatar_data['alt'];

        if ( $avatar_url ) {
            return '<img src="' . esc_url( $avatar_url ) . '" alt="' . esc_attr( $avatar_alt ) . '" class="' . esc_attr( $size_class . ' ' . $shape_class ) . ' wpuf-object-cover">';
        } else {
            // Fallback to initials
            $initials = wpuf_ud_get_user_initials( $user );
            $bg_color = 'wpuf-bg-gray-300';

            return '<div class="' . esc_attr( $size_class . ' ' . $shape_class . ' ' . $bg_color ) . ' wpuf-flex wpuf-items-center wpuf-justify-center wpuf-text-sm wpuf-font-medium wpuf-text-gray-700">' . esc_html( $initials ) . '</div>';
        }
    }

    /**
     * Render profile button for table
     *
     * @since 4.2.0
     *
     * @param \WP_User $user User object.
     * @param array $attributes Block attributes.
     *
     * @return string Profile button HTML.
     */
    private function render_profile_button( $user, $attributes ) {
        $current_url = home_url($_SERVER['REQUEST_URI']);

        global $wp;
        $current_wp_url = home_url(add_query_arg(array(), $wp->request));

        // Use pretty URL generation for consistency
        // Pass base_url directly to the method instead of using $_GET
        $base_url = $attributes['base_url'] ?? null;

        // Generate pretty profile URL
        $profile_url = $this->generate_pretty_profile_url( $user, $base_url );

        return '<a href="' . esc_url( $profile_url ) . '" class="wpuf-inline-flex wpuf-items-center wpuf-px-3 wpuf-py-1.5 wpuf-border wpuf-border-transparent wpuf-text-xs wpuf-font-medium wpuf-rounded-md wpuf-text-white wpuf-bg-emerald-600 hover:wpuf-bg-emerald-700 focus:wpuf-outline-none focus:wpuf-ring-2 focus:wpuf-ring-offset-2 focus:wpuf-ring-emerald-500 wpuf-no-underline">' . esc_html__( 'View Profile', 'wpuf-pro' ) . '</a>';
    }

    /**
     * Render user list items (extracted from user directory block)
     *
     * This method renders the individual user list items (<li> elements) for both
     * block and API contexts, ensuring visual consistency.
     *
     * @since 4.2.0
     *
     * @param array $users Array of WP_User objects to render.
     * @param array|null $template_block Template block data structure.
     * @param array $attributes Block attributes.
     * @param string $context Rendering context ('block' or 'ajax').
     *
     * @return string HTML content for user list items (without wrapper).
     */
    public function render_user_list_items( $users, $template_block, $attributes, $context = 'block' ) {
        $html = '';

        // Render each user with the template block (like Query Loop's post-template)
        foreach ( $users as $user ) {
            $html .= '<div class="wpuf-user-card">';
            if ( $template_block ) {
                // Get user context
                $user_context = [
                    'wpuf-ud/userId'           => $user->ID,
                    'wpuf-ud/userObject'       => $user,
                    'wpuf-ud/isDirectoryMode'  => true,
                    'wpuf-ud/attributes'       => $attributes,
                    'wpuf-ud/directorySettings' => [
                        'use_pretty_urls' => true,
                        'base_url'        => $attributes['base_url'] ?? '',
                    ],
                ];
                // Render the template block with user context using Query Loop style approach
                $block_content = $this->render_template_block_with_context( $template_block, $user_context );

                $html          .= $block_content;
            } else {
                // Fallback: render a simple user display if no template found
                $html .= '<div class="wpuf-user-fallback">';
                $html .= '<h3>' . esc_html( $user->display_name ) . '</h3>';
                $html .= '<p>' . esc_html( $user->user_email ) . '</p>';
                $html .= '</div>';
            }
            $html .= '</div>';
        }

        return $html;
    }

    /**
     * Render user template block
     *
     * @since 4.2.0
     *
     * @param array     $attributes Block attributes.
     * @param string    $content    Block content.
     * @param \WP_Block $block      Block object.
     *
     * @return string
     */
    public function render_user_template_block( $attributes, $content, $block ) {
        // Get the user context from the block context
        $user_context = $block->context ?? [];
        // If no user context, return empty content
        if ( empty( $user_context['wpuf-ud/userObject'] ) ) {
            return '';
        }
        // For template blocks, we render the inner content with the user context
        // The context is already being passed via render_block_context filter
        return $this->render_inner_blocks_with_context( $block, $user_context );
    }

    /**
     * Render user block
     *
     * @since 4.2.0
     *
     * @param array     $attributes Block attributes.
     * @param string    $content    Block content.
     * @param \WP_Block $block      Block object.
     *
     * @return string
     */
    public function render_user_block( $attributes, $content, $block ) {
        // Check if we're in the editor - if so, return null to let JavaScript handle it
        if ( is_admin() && ! wp_doing_ajax() ) {
            return null;
        }

        // Get user object from context (this is how Query Loop passes data)
        $user    = null;
        $user_id = 0;
        // Try to get user from context first (Query Loop style)
        if ( ! empty( $block->context['wpuf-ud/userObject'] ) ) {
            $user    = $block->context['wpuf-ud/userObject'];
            $user_id = $block->context['wpuf-ud/userId'] ?? 0;
        }
        // Fallback: try to get from attributes (legacy)
        if ( ! $user && ! empty( $attributes['userObject'] ) ) {
            $user    = $attributes['userObject'];
            $user_id = $attributes['userId'] ?? 0;
        }
        // If no user object found, return empty content
        if ( ! $user || ! is_object( $user ) || ! isset( $user->ID ) ) {
            return '';
        }
        // For user blocks, we render the specific user data based on block type
        $block_name = $block->name ?? '';

        switch ( $block_name ) {
            case 'wpuf-ud/avatar':
                return $this->render_user_avatar_block( [ 'attrs' => $attributes ], $block->context );
            case 'wpuf-ud/cover-photo':
                return $this->render_user_cover_photo_block( [ 'attrs' => $attributes ], $block->context );
            case 'wpuf-ud/name':
                return $this->render_user_name_block( [ 'attrs' => $attributes ], $block->context );
            case 'wpuf-ud/bio':
                return $this->render_user_bio_block( [ 'attrs' => $attributes ], $block->context );
            case 'wpuf-ud/contact-info':
                return $this->render_user_contact_info_block( [ 'attrs' => $attributes ], $block->context );
            case 'wpuf-ud/social-fields':
                return $this->render_user_social_fields_block( [ 'attrs' => $attributes ], $block->context );
            case 'wpuf-ud/custom-field':
                return $this->render_user_custom_field_block( [ 'attrs' => $attributes ], $block->context );
            case 'wpuf-ud/files':
                return $this->render_user_files_block( [ 'attrs' => $attributes ], $block->context );
            case 'wpuf-ud/posts':
                return $this->render_user_posts_block( [ 'attrs' => $attributes ], $block->context );
            case 'wpuf-ud/comments':
                return $this->render_user_comments_block( [ 'attrs' => $attributes ], $block->context );
            case 'wpuf-ud/tabs':
                // Pass full block so tabs renderer can access inner blocks for the About tab
                return $this->render_user_tabs_block( $block, $block->context );
            case 'wpuf-ud/profile-button':
                return $this->render_profile_button_block( [ 'attrs' => $attributes ], $block->context );
            case 'wpuf-ud/message-button':
                return $this->render_message_button_block( [ 'attrs' => $attributes ], $block->context );
            case 'wpuf-ud/social':
                return $this->render_user_social_fields_block( [ 'attrs' => $attributes ], $block->context );
            default:
                // For unknown blocks, render inner content
                return $this->render_inner_blocks_with_context( $block, $block->context );
        }
    }

    /**
     * Render user template with user context
     *
     * @since 4.2.0
     *
     * @param \WP_Block $block   Block object.
     * @param array     $context User context.
     *
     * @return string
     */
    private function render_user_template_with_context( $block, $context ) {
        $content = '';
        // Validate block object
        if ( ! $block || ! is_object( $block ) ) {
            return $content;
        }
        		// Try to find user-directory-item block in parsed_block first (more reliable)
		if ( ! empty( $block->parsed_block['innerBlocks'] ) ) {
			foreach ( $block->parsed_block['innerBlocks'] as $inner_block_data ) {
				if ( isset( $inner_block_data['blockName'] ) && $inner_block_data['blockName'] === 'wpuf-ud/directory-item' ) {
					// Found the user-directory-item block, render its inner blocks
					if ( ! empty( $inner_block_data['innerBlocks'] ) ) {
						foreach ( $inner_block_data['innerBlocks'] as $user_block_data ) {
							$content .= $this->render_parsed_block_with_context( $user_block_data, $context );
						}
					}
					break; // Found the template, no need to continue
				}
			}
		}
		// Fallback: Find the user-directory-item block in the inner content
		if ( empty( $content ) && ! empty( $block->inner_content ) ) {
			foreach ( $block->inner_content as $inner_block ) {
				// Handle string content (HTML markup)
				if ( is_string( $inner_block ) ) {
					$content .= $inner_block;
					continue;
				}
				// Handle null or empty inner blocks
				if ( empty( $inner_block ) ) {
					continue;
				}
				// Validate inner block object
				if ( ! is_object( $inner_block ) ) {
					continue;
				}
				// Check if the inner block has required properties
				if ( ! isset( $inner_block->name ) ) {
					continue;
				}
				        // Check if this is the directory-item block
        if ( $inner_block->name === 'wpuf-ud/directory-item' ) {
					// Render the user-directory-item's inner blocks with user context
					$content .= $this->render_inner_blocks_with_context( $inner_block, $context );
				} else {
					// Render other blocks normally
					$content .= $this->render_block_with_context( $inner_block, $context );
				}
			}
		}
        // If no content was rendered, try a fallback approach
        if ( empty( $content ) ) {
            // Try to render all inner blocks with context
            $content = $this->render_inner_blocks_with_context( $block, $context );
        }

        return $content;
    }

    /**
     * Render user avatar block
     *
     * @since 4.2.0
     *
     * @param array $block_data Block data.
     * @param array $context    User context.
     *
     * @return string
     */
    private function render_user_avatar_block( $block_data, $context ) {
        $user = $context['wpuf-ud/userObject'] ?? null;

        if ( ! $user || ! is_object( $user ) ) {
            return '';
        }

        $attributes = $block_data['attrs'] ?? [];

        // Enqueue avatar upload functionality for individual avatar blocks
        wp_enqueue_script(
            'cropperjs',
            WPUF_UD_ASSET_URI . '/vendors/cropper/cropper.min.js',
            [],
            '1.5.13',
            true
        );
        wp_enqueue_style(
            'cropperjs',
            WPUF_UD_ASSET_URI . '/vendors/cropper/cropper.min.css',
            [],
            '1.5.13'
        );
        wp_enqueue_script(
            'wpuf-profile-image-upload',
            WPUF_UD_ROOT_URI . '/assets/js/profile-image-upload.js',
            ['jquery', 'cropperjs'],
            WPUF_UD_VERSION,
            true
        );
        wp_enqueue_script(
            'wpuf-avatar-upload',
            WPUF_UD_ROOT_URI . '/assets/js/avatar-upload.js',
            ['jquery', 'cropperjs', 'wpuf-profile-image-upload'],
            WPUF_UD_VERSION,
            true
        );
        wp_enqueue_style(
            'wpuf-avatar-upload',
            WPUF_UD_ROOT_URI . '/assets/css/avatar-upload-css.css',
            [],
            WPUF_UD_VERSION
        );

        // Localize avatar upload script
        wp_localize_script(
            'wpuf-avatar-upload', 'wpuf_ud', [
            'ajaxUrl' => admin_url( 'admin-ajax.php' ),
            'nonce'  => wp_create_nonce( 'wpuf_avatar_upload_nonce' ),
        ]
        );

        // Load the template file
        $template_file = WPUF_UD_ROOT . '/templates/user-profile/blocks/user-avatar.php';
        if ( file_exists( $template_file ) ) {
            // Start output buffering
            ob_start();
            // Set variables for the template
            $content = ''; // Not used in avatar template
            $block = null; // Not used in avatar template
            // Check if we're in profile mode (not directory mode)
            $is_profile_mode = ! empty( $context['wpuf-ud/isProfileMode'] ) && empty( $context['wpuf-ud/isDirectoryMode'] );
            // Include the template with variables
            include $template_file;

            // Return the buffered content
            return ob_get_clean();
        }

        // Fallback if template doesn't exist - use new avatar logic
        $size = $attributes['avatarSize'] ?? 'medium';
        $shape = $attributes['avatarShape'] ?? 'circle';
        $fallback_type = $attributes['fallbackType'] ?? 'initials';
        $custom_size = $attributes['customSize'] ?? 150;

        // Calculate display size
        $display_size = wpuf_ud_get_avatar_display_size( $size, $custom_size );

        // Get avatar data with custom profile photo priority
        $avatar_data = wpuf_ud_get_block_avatar_data( $user, $display_size, $fallback_type );
        $avatar_url = $avatar_data['url'];
        $avatar_alt = $avatar_data['alt'];

        // Get shape class
        $shape_class = $shape === 'square' ? 'rounded' : 'rounded-full';

        // Get initials for fallback
        $initials = wpuf_ud_get_user_initials( $user );

        // Use wpuf_get_block_wrapper_attributes with proper block name for consistent styling
        $wrapper_attributes = wpuf_get_block_wrapper_attributes( $attributes, 'avatar', [
            'class' => 'wpuf-user-avatar',
        ] );

        if ( $avatar_url ) {
            return sprintf(
                '<div %1$s>
                    <img src="%2$s" alt="%3$s" class="wpuf-avatar-image %4$s" />
                </div>',
                $wrapper_attributes,
                esc_url( $avatar_url ),
                esc_attr( $avatar_alt ),
                esc_attr( $shape_class )
            );
        } else {
            // Show initials
            return sprintf(
                '<div %1$s>
                    <div class="wpuf-avatar--initials %2$s">
                        <span class="wpuf-avatar-initials-text">%3$s</span>
                    </div>
                </div>',
                $wrapper_attributes,
                esc_attr( $shape_class ),
                esc_html( $initials )
            );
        }
    }

    /**
     * Render user cover photo block
     *
     * @since 4.2.0
     *
     * @param array $block_data Block data.
     * @param array $context    User context.
     *
     * @return string
     */
    private function render_user_cover_photo_block( $block_data, $context ) {
        $user = $context['wpuf-ud/userObject'] ?? null;
        if ( ! $user || ! is_object( $user ) ) {
            return '';
        }

        $attributes = $block_data['attrs'] ?? [];

        // Enqueue cover photo upload functionality
        wp_enqueue_script(
            'cropperjs',
            WPUF_UD_ASSET_URI . '/vendors/cropper/cropper.min.js',
            [],
            '1.5.13',
            true
        );
        wp_enqueue_style(
            'cropperjs',
            WPUF_UD_ASSET_URI . '/vendors/cropper/cropper.min.css',
            [],
            '1.5.13'
        );
        wp_enqueue_script(
            'wpuf-profile-image-upload',
            WPUF_UD_ROOT_URI . '/assets/js/profile-image-upload.js',
            ['jquery', 'cropperjs'],
            WPUF_UD_VERSION,
            true
        );
        wp_enqueue_script(
            'wpuf-cover-photo-upload',
            WPUF_UD_ROOT_URI . '/assets/js/cover-photo-upload.js',
            ['jquery', 'cropperjs', 'wpuf-profile-image-upload'],
            WPUF_UD_VERSION,
            true
        );
        wp_enqueue_style(
            'wpuf-avatar-upload',
            WPUF_UD_ROOT_URI . '/assets/css/avatar-upload-css.css',
            [],
            WPUF_UD_VERSION
        );

        // Localize cover photo upload script with separate variable name
        wp_localize_script(
            'wpuf-cover-photo-upload',
            'wpuf_ud_cover_photo',
            [
                'ajaxUrl' => admin_url( 'admin-ajax.php' ),
                'nonce'   => wp_create_nonce( 'wpuf_cover_photo_upload_nonce' ),
            ]
        );

        // Load the template file
        $template_file = WPUF_UD_ROOT . '/templates/blocks/shared/components/cover-photo.php';
        if ( file_exists( $template_file ) ) {
            // Start output buffering
            ob_start();

            // Set variables for the template
            $content = ''; // Not used in cover photo template
            $block = null; // Not used in cover photo template

            // Map block attributes to template options
            $options = [
                'cover_height' => $attributes['coverHeight'] ?? 300,
                'cover_width' => $attributes['coverWidth'] ?? 'full-width',
                'custom_width_value' => $attributes['customWidthValue'] ?? 800,
                'custom_width_unit' => $attributes['customWidthUnit'] ?? 'px',
                'fit_type' => $attributes['fitType'] ?? 'cover',
                'fallback_type' => $attributes['fallbackType'] ?? 'placeholder',
                'link_to_profile' => $attributes['linkToProfile'] ?? false,
                'link_target' => $attributes['linkTarget'] ?? '_self',
                'placeholder_color' => $attributes['placeholderColor'] ?? '#f3f4f6',
                'class' => '',
            ];

            // Check if we're in profile mode (not directory mode)
            $is_profile_mode = ! empty( $context['wpuf-ud/isProfileMode'] ) && empty( $context['wpuf-ud/isDirectoryMode'] );

            // Include the template with variables
            include $template_file;

            // Get template output
            $final_html = ob_get_clean();

            // Use wpuf_get_block_wrapper_attributes with proper block name for consistent styling
            $wrapper_attributes = wpuf_get_block_wrapper_attributes( $attributes, 'cover-photo', [
                'class' => 'wpuf-user-cover-photo',
            ] );

            return sprintf( '<div %s>%s</div>', $wrapper_attributes, $final_html );
        }

        // Fallback if template doesn't exist - build inline HTML
        $size = $attributes['coverPhotoSize'] ?? 'medium';
        $aspect_ratio = $attributes['aspectRatio'] ?? '16-9';
        $display_mode = $attributes['displayMode'] ?? 'contained';
        $fallback_type = $attributes['fallbackType'] ?? 'placeholder';
        $placeholder_color = $attributes['placeholderColor'] ?? '#f3f4f6';
        $link_to_profile = $attributes['linkToProfile'] ?? false;
        $link_target = $attributes['linkTarget'] ?? '_self';

        // Calculate dimensions
        $dimensions = $this->get_cover_photo_dimensions( $size, $attributes );
        $height = $dimensions['height'];
        $width = $dimensions['width'];

        // Get cover photo data using the proper function that handles attachment ID to URL conversion
        $cover_photo_data = wpuf_ud_get_block_cover_photo_data( $user, $width );
        $cover_photo_url = $cover_photo_data['url'];

        // Build CSS classes
        $css_classes = ['wpuf-cover-photo'];
        $css_classes[] = 'wpuf-cover-photo--' . $size;
        $css_classes[] = 'wpuf-cover-photo--' . $aspect_ratio;
        $css_classes[] = 'wpuf-cover-photo--' . $display_mode;

        // Build inline styles
        $inline_styles = '';
        if ( $size === 'custom' ) {
            $inline_styles .= sprintf( 'height: %dpx; width: %dpx;', $height, $width );
        }

        // Generate cover photo HTML
        $cover_photo_html = '';
        if ( ! empty( $cover_photo_url ) ) {
            $cover_photo_html = sprintf(
                '<img src="%s" alt="%s" class="wpuf-cover-photo__image" style="%s" />',
                esc_url( $cover_photo_url ),
                esc_attr( sprintf( '%s %s', $user->display_name, __( 'Cover Photo', 'wpuf-pro' ) ) ),
                esc_attr( $inline_styles )
            );
        } else {
            // Fallback placeholder
            if ( $fallback_type === 'placeholder' ) {
                $cover_photo_html = sprintf(
                    '<div class="wpuf-cover-photo__placeholder" style="background-color: %s; %s">
                        <span class="wpuf-cover-photo__placeholder-text">%s</span>
                    </div>',
                    esc_attr( $placeholder_color ),
                    esc_attr( $inline_styles ),
                    esc_html__( 'No Cover Photo', 'wpuf-pro' )
                );
            } else {
                $cover_photo_html = sprintf(
                    '<div class="wpuf-cover-photo__solid" style="background-color: %s; %s"></div>',
                    esc_attr( $placeholder_color ),
                    esc_attr( $inline_styles )
                );
            }
        }

        // Build final HTML
        $final_html = sprintf(
            '<div class="%s" style="%s">
                <div class="wpuf-cover-photo__container">
                    %s
                </div>
            </div>',
            esc_attr( implode( ' ', $css_classes ) ),
            esc_attr( $inline_styles ),
            $cover_photo_html
        );

        // Wrap in link if needed
        if ( $link_to_profile ) {
            $author_url = get_author_posts_url( $user->ID );
            $target_attr = $link_target === '_blank' ? ' target="_blank" rel="noopener"' : '';

            $final_html = sprintf(
                '<a href="%s"%s class="wpuf-cover-photo__link">%s</a>',
                esc_url( $author_url ),
                $target_attr,
                $final_html
            );
        }

        // Use wpuf_get_block_wrapper_attributes with proper block name for consistent styling
        $wrapper_attributes = wpuf_get_block_wrapper_attributes( $attributes, 'cover-photo', [
            'class' => 'wpuf-user-cover-photo',
        ] );

        return sprintf( '<div %s>%s</div>', $wrapper_attributes, $final_html );
    }

    /**
     * Get cover photo dimensions based on size setting
     *
     * @since 4.2.0
     *
     * @param string $size Size setting.
     * @param array  $attributes Block attributes.
     *
     * @return array Array with height and width.
     */
    private function get_cover_photo_dimensions( $size, $attributes ) {
        $size_map = [
            'small' => ['height' => 150, 'width' => 400],
            'medium' => ['height' => 300, 'width' => 800],
            'large' => ['height' => 450, 'width' => 1200],
            'custom' => [
                'height' => $attributes['customHeight'] ?? 300,
                'width' => $attributes['customWidth'] ?? 800
            ],
        ];

        return $size_map[ $size ] ?? $size_map['medium'];
    }

    /**
     * Render user name block
     *
     * @since 4.2.0
     *
     * @param array $block_data Block data.
     * @param array $context    User context.
     *
     * @return string
     */
    private function render_user_name_block( $block_data, $context ) {
        // Enqueue frontend CSS only when block is rendered
        wp_enqueue_style(
            'wpuf-block-user-name',
            WPUF_UD_ROOT_URI . '/assets/css/block-user-name.css',
            [],
            WPUF_UD_VERSION
        );

        // Enqueue WordPress block editor styles to ensure CSS custom properties are available
        wp_enqueue_style( 'wp-block-library' );
        $user = $context['wpuf-ud/userObject'] ?? null;
        if ( ! $user || ! is_object( $user ) ) {
            return '';
        }

        // Handle both attribute formats: wrapped in 'attrs' key or direct parsed block
        $attributes = $block_data['attrs'] ?? $block_data ?? [];

        // Load the template file
        $template_file = WPUF_UD_ROOT . '/templates/user-profile/blocks/user-name.php';
        if ( file_exists( $template_file ) ) {
            // Start output buffering
            ob_start();

            // Ensure variables are available in template scope
            // These variables will be available to the included template
            $content = ''; // Not used in name template
            $block = null; // Not used in name template

            // Explicitly make variables available in template scope
            // This ensures $user and $attributes are accessible in the included template
            extract( [
                'user' => $user,
                'attributes' => $attributes,
                'content' => $content,
                'block' => $block,
            ] );

            // Include the template - variables should now be available in template scope
            include $template_file;

            // Return the buffered content
            return ob_get_clean();
        }
        // Fallback if template doesn't exist
        $name_format  = $attributes['nameFormat'] ?? 'display_name';

        $element_type = $attributes['headingLevel'] ?? 'p';
        $name = wpuf_ud_get_formatted_name( $user, $name_format, '' );

        // Use wpuf_get_block_wrapper_attributes with proper block name for consistent styling
        $wrapper_attributes = wpuf_get_block_wrapper_attributes( $attributes, 'name', [
            'class' => 'wpuf-user-name',
        ] );

        return sprintf(
            '<div %1$s><%2$s class="wpuf-name-text">%3$s</%2$s></div>',
            $wrapper_attributes,
            esc_attr( $element_type ),
            esc_html( $name )
        );
    }

    /**
     * Render user bio block
     *
     * @since 4.2.0
     *
     * @param array $block_data Block data.
     * @param array $context    User context.
     *
     * @return string
     */
    private function render_user_bio_block( $block_data, $context ) {
        $user = $context['wpuf-ud/userObject'] ?? null;
        if ( ! $user || ! is_object( $user ) ) {
            return '';
        }

        // Handle both attribute formats: wrapped in 'attrs' key or direct parsed block
        $attributes = $block_data['attrs'] ?? $block_data ?? [];

        // Always use the template file for full functionality
        ob_start();
        $template_path = WPUF_UD_ROOT . '/templates/user-profile/blocks/user-bio.php';
        if ( file_exists( $template_path ) ) {
            include $template_path;
        }
        return ob_get_clean();
    }

    /**
     * Render user contact info block
     *
     * @since 4.2.0
     *
     * @param array $block_data Block data.
     * @param array $context    User context.
     *
     * @return string
     */
    private function render_user_contact_info_block( $block_data, $context ) {
        $user = $context['wpuf-ud/userObject'] ?? null;
        if ( ! $user || ! is_object( $user ) ) {
            return '';
        }

        $attributes = $block_data['attrs'] ?? [];

        // Include the template with user context
        ob_start();
        include WPUF_UD_ROOT . '/templates/user-profile/blocks/user-contact-info.php';
        return ob_get_clean();
    }

    /**
     * Render user social fields block
     *
     * @since 4.2.0
     *
     * @param array $block_data Block data.
     * @param array $context    User context.
     *
     * @return string
     */
    private function render_user_social_fields_block( $block_data, $context ) {
        $user = $context['wpuf-ud/userObject'] ?? null;
        if ( ! $user || ! is_object( $user ) ) {
            return '';
        }

        $attributes = $block_data['attrs'] ?? [];

        // Include the template with user context
        ob_start();
        include WPUF_UD_ROOT . '/templates/user-profile/blocks/user-social-fields.php';
        return ob_get_clean();
    }

    /**
     * Render user custom field block
     *
     * @since 4.2.0
     *
     * @param array $block_data Block data.
     * @param array $context    User context.
     *
     * @return string
     */
    private function render_user_custom_field_block( $block_data, $context ) {
        $user = $context['wpuf-ud/userObject'] ?? null;
        if ( ! $user || ! is_object( $user ) ) {
            return '';
        }
        $attributes = $block_data['attrs'] ?? [];
        // Support new attribute 'metaFieldKey' with fallback to legacy 'fieldName'
        $meta_key = $attributes['metaFieldKey'] ?? ( $attributes['fieldName'] ?? '' );
        if ( empty( $meta_key ) ) {
            return '';
        }
        $field_value = get_user_meta( $user->ID, $meta_key, true );
        if ( empty( $field_value ) ) {
            return '';
        }
        $field_label = $attributes['fieldLabel'] ?? ucfirst( str_replace( '_', ' ', $meta_key ) );
        $show_label  = isset( $attributes['showLabel'] ) ? (bool) $attributes['showLabel'] : true;
        // Role-based visibility: show only if the profile user has one of the selected roles
        $selected_roles = $attributes['profileUserRoles'] ?? [ 'all' ];

        if ( ! is_array( $selected_roles ) || empty( $selected_roles ) ) {
            $selected_roles = [ 'all' ];
        }
        if ( ! in_array( 'all', $selected_roles, true ) ) {
            $user_roles = is_array( $user->roles ?? null ) ? $user->roles : [];
            if ( empty( array_intersect( $user_roles, $selected_roles ) ) ) {
                return '';
            }
        }

        // Viewer role-based visibility: check current viewer (logged-in user or guest)
        $viewer_roles = $attributes['viewerRoles'] ?? [ 'all' ];

        if ( ! is_array( $viewer_roles ) || empty( $viewer_roles ) ) {
            $viewer_roles = [ 'all' ];
        }

        if ( ! in_array( 'all', $viewer_roles, true ) ) {
            $current_user     = wp_get_current_user();
            // Administrators can always view
            if ( is_user_logged_in() && user_can( $current_user, 'administrator' ) ) {
                // allow
            } else {
                $is_guest_allowed = in_array( 'guest', $viewer_roles, true );
                $viewer_has_role  = false;
                if ( is_user_logged_in() ) {
                    $current_roles   = is_array( $current_user->roles ?? null ) ? $current_user->roles : [];
                    $viewer_has_role = ! empty( array_intersect( $current_roles, $viewer_roles ) );
                } else {
                    $viewer_has_role = $is_guest_allowed; // guest
                }
                if ( ! $viewer_has_role ) {
                    return '';
                }
            }
        }
        $label_html  = '';
        if ( $show_label && ! empty( $field_label ) ) {
            $label_html = sprintf( '<span class="wpuf-field-label">%s:</span>', esc_html( $field_label ) );
        }

        // Always use WordPress wrapper attributes for consistent styling
        $wrapper_attributes = wpuf_get_block_wrapper_attributes(
            $attributes,
            'user-custom-field',
            [ 'class' => 'wpuf-custom-field' ]
        );

        return sprintf(
            '<div %1$s>%2$s<span class="wpuf-field-value">%3$s</span></div>',
            $wrapper_attributes,
            $label_html,
            esc_html( $field_value )
        );
    }

    /**
     * Render user files block
     *
     * @since 4.2.0
     *
     * @param array $block_data Block data.
     * @param array $context    User context.
     *
     * @return string
     */
    private function render_user_files_block( $block_data, $context ) {
        $user = $context['wpuf-ud/userObject'] ?? null;
        if ( ! $user || ! is_object( $user ) ) {
            return '';
        }

        $attributes = $block_data['attrs'] ?? [];

        // Include the template with user context
        ob_start();
        include WPUF_UD_ROOT . '/templates/user-profile/blocks/user-files.php';
        return ob_get_clean();
    }

    /**
     * Render user posts block
     *
     * @since 4.2.0
     *
     * @param array $block_data Block data.
     * @param array $context    User context.
     *
     * @return string
     */
    private function render_user_posts_block( $block_data, $context ) {
        $user = $context['wpuf-ud/userObject'] ?? null;
        if ( ! $user || ! is_object( $user ) ) {
            return '';
        }
        $attributes     = $block_data['attrs'] ?? [];
        $posts_per_page = $attributes['postsPerPage'] ?? 10;
        $post_type      = $attributes['postType'] ?? 'post';
        $show_pagination = $attributes['showPagination'] ?? true;

        // Get current page from URL parameters
        $current_page = isset( $_GET['posts_page'] ) ? max( 1, intval( $_GET['posts_page'] ) ) : 1;
        $offset = ( $current_page - 1 ) * $posts_per_page;


        // Role-based visibility: show only if the profile user has one of the selected roles
        $selected_roles = $attributes['profileUserRoles'] ?? [ 'all' ];

        if ( ! is_array( $selected_roles ) || empty( $selected_roles ) ) {
            $selected_roles = [ 'all' ];
        }
        if ( ! in_array( 'all', $selected_roles, true ) ) {
            $user_roles = is_array( $user->roles ?? null ) ? $user->roles : [];
            if ( empty( array_intersect( $user_roles, $selected_roles ) ) ) {
                return '';
            }
        }

        // Viewer role-based visibility: check current viewer (logged-in user or guest)
        $viewer_roles = $attributes['viewerRoles'] ?? [ 'all' ];

        if ( ! is_array( $viewer_roles ) || empty( $viewer_roles ) ) {
            $viewer_roles = [ 'all' ];
        }

        if ( ! in_array( 'all', $viewer_roles, true ) ) {
            $current_user     = wp_get_current_user();
            // Administrators can always view
            if ( is_user_logged_in() && user_can( $current_user, 'administrator' ) ) {
                // allow
            } else {
                $is_guest_allowed = in_array( 'guest', $viewer_roles, true );
                $viewer_has_role  = false;
                if ( is_user_logged_in() ) {
                    $current_roles   = is_array( $current_user->roles ?? null ) ? $current_user->roles : [];
                    $viewer_has_role = ! empty( array_intersect( $current_roles, $viewer_roles ) );
                } else {
                    $viewer_has_role = $is_guest_allowed; // guest
                }
                if ( ! $viewer_has_role ) {
                    return '';
                }
            }
        }

        // Use WP_Query for both pagination and total count
        $posts_query = new \WP_Query( [
            'author'         => $user->ID,
            'post_type'      => $post_type,
            'post_status'    => 'publish',
            'posts_per_page' => $posts_per_page,
            'paged'          => $current_page,
            'orderby'        => 'date',
            'order'          => 'DESC',
        ] );

        $posts = $posts_query->posts;
        $total_posts = $posts_query->found_posts;
        $total_pages = $posts_query->max_num_pages;
        wp_reset_postdata();

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

        // Get dynamic post type label
        $post_type_label = $this->get_post_type_label( $post_type );

        // Use the template file for rendering
        ob_start();
        include WPUF_UD_ROOT . '/templates/user-profile/blocks/user-posts.php';
        $template_output = ob_get_clean();

        // Prepare pagination data
        $pagination = [
            'total_pages'  => ceil( $total_posts / $posts_per_page ),
            'total_items'  => $total_posts,
            'per_page'     => $posts_per_page,
            'current_page' => $current_page,
        ];

        // Get pagination HTML if needed and toggle is enabled
        $pagination_html = '';
        if ( $show_pagination && $pagination['total_pages'] > 1 ) {
            // Use AJAX pagination (same as tabs) for consistent behavior
            $pagination_html = $this->render_ajax_pagination( $pagination, 'posts' );
        }

        // Enqueue the existing user-tabs-frontend script for AJAX pagination
        wp_enqueue_script(
            'wpuf-user-tabs-frontend',
            WPUF_UD_ROOT_URI . '/assets/js/user-tabs-frontend.js',
            [ 'jquery' ],
            WPUF_UD_VERSION,
            true
        );

        // Localize script with AJAX data (reuse existing tabs script)
        wp_localize_script( 'wpuf-user-tabs-frontend', 'wpufUserTabs', [
            'ajaxUrl' => admin_url( 'admin-ajax.php' ),
            'nonce'   => wp_create_nonce( 'wpuf_user_tabs_nonce' ),
        ] );

        // Always use WordPress wrapper attributes for consistent styling
        $wrapper_attributes = get_block_wrapper_attributes( [
            'class' => 'wpuf-user-posts',
            'data-user-id' => $user->ID,
            'data-posts-per-page' => $posts_per_page,
            'data-post-type' => $post_type,
            'data-show-pagination' => $show_pagination ? 'true' : 'false',
            'data-current-page' => $current_page,
            'data-total-pages' => $pagination['total_pages'],
        ], $attributes );
        return sprintf(
            '<div %1$s>%2$s%3$s</div>',
            $wrapper_attributes,
            $template_output,
            $pagination_html
        );
    }

    /**
     * Render AJAX pagination for tab contexts
     *
     * @since 4.2.0
     *
     * @param array  $pagination Pagination data
     * @param string $tab_type   Tab type (posts, comments, etc.)
     *
     * @return string AJAX pagination HTML
     */
    private function render_ajax_pagination( $pagination, $tab_type ) {
        if ( empty( $pagination ) || $pagination['total_pages'] <= 1 ) {
            return '';
        }

        // Set up URL builder for AJAX context
        $GLOBALS['wpuf_pagination_url_builder'] = [ $this, 'build_ajax_pagination_url' ];

        // Start output buffering to capture template
        ob_start();
        include WPUF_UD_ROOT . '/templates/blocks/user-directory/components/pagination.php';
        $pagination_html = ob_get_clean();

        return $pagination_html;
    }

    /**
     * Build pagination URL for AJAX context
     *
     * @since 4.2.0
     *
     * @param string $base_url Base URL
     * @param array  $query_args Query arguments
     * @param int    $page Page number
     *
     * @return string AJAX pagination URL
     */
    public function build_ajax_pagination_url( $base_url, $query_args, $page ) {
        // For AJAX context, we don't need real URLs since JavaScript will handle clicks
        // Return a placeholder that JavaScript can extract the page number from
        return '#page-' . $page;
    }

    /**
     * Render user comments block
     *
     * @since 4.2.0
     *
     * @param array $block_data Block data.
     * @param array $context    User context.
     *
     * @return string
     */
    private function render_user_comments_block( $block_data, $context ) {
        $user = $context['wpuf-ud/userObject'] ?? null;
        if ( ! $user || ! is_object( $user ) ) {
            return '';
        }
        $attributes     = $block_data['attrs'] ?? [];
        $comments_per_page = $attributes['commentsPerPage'] ?? 10;
        $post_type      = $attributes['postType'] ?? 'post';
        $show_pagination = $attributes['showPagination'] ?? true;

        // Get current page from URL parameters
        $current_page = isset( $_GET['comments_page'] ) ? max( 1, intval( $_GET['comments_page'] ) ) : 1;
        $offset = ( $current_page - 1 ) * $comments_per_page;

        // Role-based visibility: show only if the profile user has one of the selected roles
        $selected_roles = $attributes['profileUserRoles'] ?? [ 'all' ];

        if ( ! is_array( $selected_roles ) || empty( $selected_roles ) ) {
            $selected_roles = [ 'all' ];
        }
        if ( ! in_array( 'all', $selected_roles, true ) ) {
            $user_roles = is_array( $user->roles ?? null ) ? $user->roles : [];
            if ( empty( array_intersect( $user_roles, $selected_roles ) ) ) {
                return '';
            }
        }

        // Viewer role-based visibility: check current viewer (logged-in user or guest)
        $viewer_roles = $attributes['viewerRoles'] ?? [ 'all' ];

        if ( ! is_array( $viewer_roles ) || empty( $viewer_roles ) ) {
            $viewer_roles = [ 'all' ];
        }

        if ( ! in_array( 'all', $viewer_roles, true ) ) {
            $current_user     = wp_get_current_user();
            // Administrators can always view
            if ( is_user_logged_in() && user_can( $current_user, 'administrator' ) ) {
                // allow
            } else {
                $is_guest_allowed = in_array( 'guest', $viewer_roles, true );
                $viewer_has_role  = false;
                if ( is_user_logged_in() ) {
                    $current_roles   = is_array( $current_user->roles ?? null ) ? $current_user->roles : [];
                    $viewer_has_role = ! empty( array_intersect( $current_roles, $viewer_roles ) );
                } else {
                    $viewer_has_role = $is_guest_allowed; // guest
                }
                if ( ! $viewer_has_role ) {
                    return '';
                }
            }
        }

        // Get total comments count first for pagination
        $total_comments_args = [
            'user_id' => $user->ID,
            'status'  => 'approve',
            'count'   => true
        ];

        // Filter by post type if specified
        if ( $post_type && $post_type !== 'all' ) {
            $post_ids = get_posts( [
                'post_type'      => $post_type,
                'post_status'    => 'publish',
                'fields'         => 'ids',
                'posts_per_page' => -1,
            ] );
            if ( ! empty( $post_ids ) ) {
                $total_comments_args['post__in'] = $post_ids;
            } else {
                // No posts of this type, return empty
                return '';
            }
        }

        $total_comments = get_comments( $total_comments_args );

        // Build comments query with pagination
        $comments_args = [
            'user_id' => $user->ID,
            'number'  => $comments_per_page,
            'offset'  => $offset,
            'status'  => 'approve',
            'orderby' => 'comment_date',
            'order'   => 'DESC',
        ];

        // Apply post type filter to comments query
        if ( $post_type && $post_type !== 'all' && ! empty( $post_ids ) ) {
            $comments_args['post__in'] = $post_ids;
        }

        $comments = get_comments( $comments_args );
        if ( empty( $comments ) ) {
            return '';
        }

        // Modern minimal design HTML
        $comments_html = '';
        foreach ( $comments as $comment ) {
            $comment_content = wp_strip_all_tags( $comment->comment_content );
            $comment_excerpt = wp_trim_words( $comment_content, 20, '...' );
            $comment_date    = date_i18n( 'M j, Y', strtotime( $comment->comment_date ) );
            $post_title     = get_the_title( $comment->comment_post_ID );
            $post_url       = get_permalink( $comment->comment_post_ID );
            $reply_count    = get_comments( [
                'parent' => $comment->comment_ID,
                'count'  => true,
            ] );

            $comments_html .= sprintf(
                '<div class="wpuf-px-4 wpuf-py-4">
                    <div class="wpuf-flex wpuf-items-start wpuf-gap-3">
                        <div class="wpuf-flex-shrink-0">
                            <div class="wpuf-w-8 wpuf-h-8 wpuf-bg-gray-200 wpuf-dark:bg-gray-700 wpuf-rounded-full wpuf-flex wpuf-items-center wpuf-justify-center">
                                <span class="wpuf-text-xs wpuf-font-medium wpuf-text-gray-600 wpuf-dark:text-gray-300">%s</span>
                            </div>
                        </div>
                        <div class="wpuf-flex-1 wpuf-min-w-0">
                            <div class="wpuf-flex wpuf-items-center wpuf-gap-2 wpuf-mb-1">
                                <span class="wpuf-text-sm wpuf-font-medium wpuf-text-gray-900 wpuf-dark:text-white">%s</span>
                                <span class="wpuf-text-xs wpuf-text-gray-500 wpuf-dark:text-gray-400">%s</span>
                            </div>
                            <p class="wpuf-text-sm wpuf-text-gray-700 wpuf-dark:text-gray-300 wpuf-mb-2">%s</p>
                            <div class="wpuf-flex wpuf-items-center wpuf-gap-4 wpuf-text-xs wpuf-text-gray-500 wpuf-dark:text-gray-400">
                                <span>%s: <a href="%s" class="wpuf-text-indigo-600 wpuf-hover:text-indigo-900 wpuf-dark:text-indigo-400 wpuf-dark:hover:text-indigo-300">%s</a></span>%s
                            </div>
                        </div>
                    </div>
                </div>',
                esc_html( strtoupper( substr( $user->display_name, 0, 1 ) ) ),
                esc_html( $user->display_name ),
                esc_html( $comment_date ),
                esc_html( $comment_excerpt ),
                esc_html__( 'On', 'wpuf-pro' ),
                esc_url( $post_url ),
                esc_html( $post_title ),
                $reply_count > 0 ? sprintf( '<span>%d %s</span>', $reply_count, esc_html__( 'replies', 'wpuf-pro' ) ) : ''
            );
        }

        // Modern minimal design wrapper
        $wrapper_html = sprintf(
            '<div class="wpuf-overflow-hidden wpuf-shadow wpuf-outline wpuf-outline-1 wpuf-outline-black/5 wpuf-rounded-lg wpuf-dark:shadow-none wpuf-dark:-outline-offset-1 wpuf-dark:outline-white/10">
                <div class="wpuf-divide-y wpuf-divide-gray-200 wpuf-bg-white wpuf-dark:divide-white/10 wpuf-dark:bg-gray-800/50">
                    %s
                </div>
            </div>',
            $comments_html
        );

        // Prepare pagination data
        $pagination = [
            'total_pages'  => ceil( $total_comments / $comments_per_page ),
            'total_items'  => $total_comments,
            'per_page'     => $comments_per_page,
            'current_page' => $current_page,
        ];

        // Get pagination HTML if needed and toggle is enabled
        $pagination_html = '';
        if ( $show_pagination && $pagination['total_pages'] > 1 ) {
            // Use AJAX pagination for all User Comments blocks (consistent behavior)
            $pagination_html = $this->render_ajax_pagination( $pagination, 'comments' );
        }

        // Enqueue the existing user-tabs-frontend script for AJAX pagination
        wp_enqueue_script(
            'wpuf-user-tabs-frontend',
            WPUF_UD_ROOT_URI . '/assets/js/user-tabs-frontend.js',
            [ 'jquery' ],
            WPUF_UD_VERSION,
            true
        );

        // Localize script with AJAX data (reuse existing tabs script)
        wp_localize_script( 'wpuf-user-tabs-frontend', 'wpufUserTabs', [
            'ajaxUrl' => admin_url( 'admin-ajax.php' ),
            'nonce'   => wp_create_nonce( 'wpuf_user_tabs_nonce' ),
        ] );

        // Always use WordPress wrapper attributes for consistent styling
        $wrapper_attributes = get_block_wrapper_attributes( [
            'class' => 'wpuf-user-comments',
            'data-user-id' => $user->ID,
            'data-comments-per-page' => $comments_per_page,
            'data-post-type' => $post_type,
            'data-show-pagination' => $show_pagination ? 'true' : 'false',
            'data-current-page' => $current_page,
            'data-total-pages' => $pagination['total_pages'],
        ], $attributes );
        return sprintf(
            '<div %1$s>%2$s%3$s</div>',
            $wrapper_attributes,
            $wrapper_html,
            $pagination_html
        );
    }

    /**
     * Render user tabs block
     *
     * @since 4.2.0
     *
     * @param array $block_data Block data.
     * @param array $context    User context.
     *
     * @return string
     */
    private function render_user_tabs_block( $block_input, $context ) {
        $user = $context['wpuf-ud/userObject'] ?? null;
        if ( ! $user || ! is_object( $user ) ) {
            return '';
        }

        // Normalize attributes and access to inner content based on input type
        $attributes      = [];
        $has_wp_block    = is_object( $block_input ) && ( $block_input instanceof \WP_Block );
        $parsed_block    = null;
        $inner_about_html = '';

        if ( $has_wp_block ) {
            $attributes   = is_array( $block_input->attributes ?? null ) ? $block_input->attributes : [];
            $parsed_block = $block_input->parsed_block ?? null;

            // Render inner blocks (about tab content) with user context
            $inner_about_html = $this->render_inner_blocks_with_context( $block_input, $context );
        } elseif ( is_array( $block_input ) ) {
            // Called with parsed block array
            $attributes = $block_input['attrs'] ?? [];
            $inner_about_html = '';

            // Render child innerBlocks (about tab content) with user context
            if ( ! empty( $block_input['innerBlocks'] ) && is_array( $block_input['innerBlocks'] ) ) {
                foreach ( $block_input['innerBlocks'] as $child_block ) {
                    $inner_about_html .= $this->render_parsed_block_with_context( $child_block, $context );
                }
            } elseif ( ! empty( $block_input['innerHTML'] ) && is_string( $block_input['innerHTML'] ) ) {
                // Fallback to innerHTML if present
                $inner_about_html = $block_input['innerHTML'];
            }
        }

        // Determine enabled tabs and order from attributes
        $enabled_tabs_attr = $attributes['enabledTabs'] ?? [ 'about', 'posts', 'comments', 'files', 'activity' ];
        $tab_order_attr    = $attributes['tabOrder'] ?? $enabled_tabs_attr;
        $custom_labels     = $attributes['customLabels'] ?? [];

        // Build ordered enabled tabs list
        $orders = array_values( array_unique( array_merge( (array) $tab_order_attr, (array) $enabled_tabs_attr ) ) );
        $enabled_set = array_fill_keys( (array) $enabled_tabs_attr, true );

        $default_labels = [
            'about'    => __( 'About', 'wpuf-pro' ),
            'posts'    => __( 'Posts', 'wpuf-pro' ),
            'comments' => __( 'Comments', 'wpuf-pro' ),
            'files'    => __( 'Files', 'wpuf-pro' ),
            'activity' => __( 'Activity', 'wpuf-pro' ),
        ];

        $enabled_tabs = [];
        foreach ( $orders as $index => $tab_id ) {
            if ( isset( $enabled_set[ $tab_id ] ) ) {
                $enabled_tabs[] = [
                    'id'    => $tab_id,
                    'label' => $custom_labels[ $tab_id ] ?? ( $default_labels[ $tab_id ] ?? $tab_id ),
                    'order' => $index,
                ];
            }
        }

        // Filter out Activity tab if WPUF_User_Activity class doesn't exist
        if ( ! class_exists( 'WPUF_User_Activity' ) ) {
            $enabled_tabs = array_filter( $enabled_tabs, function( $tab ) {
                return $tab['id'] !== 'activity';
            } );
            // Re-index the array after filtering
            $enabled_tabs = array_values( $enabled_tabs );
        }

        // Default active tab
        $default_active_tab = ! empty( $enabled_tabs ) ? $enabled_tabs[0]['id'] : 'about';

        // Build mobile dropdown
        $mobile_dropdown = '<div class="wpuf-grid wpuf-grid-cols-1 sm:wpuf-hidden">';
        $mobile_dropdown .= '<select aria-label="' . esc_attr__( 'Select a tab', 'wpuf-pro' ) . '" class="wpuf-col-start-1 wpuf-row-start-1 wpuf-w-full wpuf-appearance-none wpuf-rounded-md wpuf-bg-white wpuf-py-2 wpuf-pl-3 wpuf-pr-8 wpuf-text-base wpuf-text-gray-900 outline outline-1 -outline-offset-1 outline-gray-300 focus:outline focus:outline-2 focus:-outline-offset-2 focus:outline-current">';

        foreach ( $enabled_tabs as $tab ) {
            $tab_id = $tab['id'];
            $selected = $tab_id === $default_active_tab ? ' selected' : '';
            $mobile_dropdown .= sprintf(
                '<option value="%s"%s>%s</option>',
                esc_attr( $tab_id ),
                $selected,
                esc_html( $tab['label'] )
            );
        }
        $mobile_dropdown .= '</select>';
        $mobile_dropdown .= '<svg viewBox="0 0 16 16" fill="currentColor" data-slot="icon" aria-hidden="true" class="wpuf-pointer-events-none wpuf-col-start-1 wpuf-row-start-1 wpuf-mr-2 size-5 wpuf-self-center wpuf-justify-self-end fill-gray-500">';
        $mobile_dropdown .= '<path d="M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" fill-rule="evenodd" />';
        $mobile_dropdown .= '</svg>';
        $mobile_dropdown .= '</div>';

        // Build desktop tabs
        $desktop_tabs = '<div class="wpuf-hidden sm:wpuf-block">';
        $desktop_tabs .= '<div class="wpuf-border-b wpuf-border-gray-200">';
        $desktop_tabs .= '<nav aria-label="' . esc_attr__( 'Tabs', 'wpuf-pro' ) . '" class="wpuf--mb-px wpuf-flex">';

        foreach ( $enabled_tabs as $tab ) {
            $tab_id = $tab['id'];
            $active_class = $tab_id === $default_active_tab ? 'wpuf-border-current wpuf-text-current' : 'wpuf-border-transparent wpuf-text-gray-500 hover:wpuf-border-gray-300 hover:wpuf-text-gray-700';
            $aria_current = $tab_id === $default_active_tab ? ' aria-current="page"' : '';

            $desktop_tabs .= sprintf(
                '<a href="#" class="wpuf-w-1/%d wpuf-border-b-2 wpuf-px-1 wpuf-py-4 wpuf-text-center wpuf-text-sm wpuf-font-medium %s" data-tab-id="%s"%s>%s</a>',
                max( 1, count( $enabled_tabs ) ),
                esc_attr( $active_class ),
                esc_attr( $tab_id ),
                $aria_current,
                esc_html( $tab['label'] )
            );
        }

        $desktop_tabs .= '</nav>';
        $desktop_tabs .= '</div>';
        $desktop_tabs .= '</div>';

        // Build tab content area
        $tab_content = '<div class="wpuf-tab-content-area wpuf-mt-[48px]">';

        foreach ( $enabled_tabs as $tab ) {
            $tab_id = $tab['id'];
            $active_class = $tab_id === $default_active_tab ? 'wpuf-tab-active' : 'wpuf-hidden';

            if ( $tab_id === 'about' ) {
                // About tab with InnerBlocks content
                $tab_content .= sprintf(
                    '<div class="wpuf-tab-content %s" data-tab-id="%s">',
                    esc_attr( $active_class ),
                    esc_attr( $tab_id )
                );
                $tab_content .= '<div class="wpuf-about-tab-content">';

                // Always render inner blocks (About tab content)
                $tab_content .= $inner_about_html;

                $tab_content .= '</div>';
                $tab_content .= '</div>';
            } elseif ( $tab_id === 'activity' ) {
                // Activity tab: render content via hook if available; otherwise allow AJAX fallback
                $panel_classes = trim( 'wpuf-tab-content ' . $active_class );
                $loaded_class  = class_exists( 'WPUF_User_Activity' ) ? ' wpuf-tab-loaded' : '';
                $tab_content .= sprintf(
                    '<div class="%s%s" data-tab-id="%s">',
                    esc_attr( $panel_classes ),
                    esc_attr( $loaded_class ),
                    esc_attr( $tab_id )
                );
                $tab_content .= '<div class="wpuf-activity-tab-content">';
                if ( class_exists( 'WPUF_User_Activity' ) ) {
                    ob_start();
                    do_action( 'wpuf_ud_profile_sections' );
                    $tab_content .= ob_get_clean();
                } else {
                    // Show loader to allow JS to request via AJAX as a fallback
                    $tab_content .= '<div class="wpuf-tab-loading">Loading...</div>';
                }
                $tab_content .= '</div>';
                $tab_content .= '</div>';
            } elseif ( $tab_id === 'posts' ) {
                // Posts tab: render user posts using table layout like user-posts.php
                $tab_content .= sprintf(
                    '<div class="wpuf-tab-content %s" data-tab-id="%s">',
                    esc_attr( $active_class ),
                    esc_attr( $tab_id )
                );
                $tab_content .= '<div class="wpuf-posts-tab-content">';

                // Get user posts with pagination settings
                $posts_per_page = $attributes['postsPerPage'] ?? 10;
                $show_posts_pagination = $attributes['showPostsPagination'] ?? true;

                // Get current page from URL parameters
                $current_page = isset( $_GET['posts_page'] ) ? max( 1, intval( $_GET['posts_page'] ) ) : 1;
                $offset = ( $current_page - 1 ) * $posts_per_page;

                $posts = get_posts( [
                    'author'         => $user->ID,
                    'post_type'      => 'post',
                    'post_status'    => 'publish',
                    'posts_per_page' => $posts_per_page,
                    'offset'         => $offset,
                    'orderby'        => 'date',
                    'order'          => 'DESC',
                ] );

                // Get total posts count for pagination using WP_Query for better performance
                $count_query = new \WP_Query( [
                    'author'      => $user->ID,
                    'post_type'   => 'post',
                    'post_status' => 'publish',
                    'posts_per_page' => -1,
                    'fields'      => 'ids',
                    'no_found_rows' => false, // We need the total count
                ] );
                $total_posts_count = $count_query->found_posts;

                if ( ! empty( $posts ) ) {
                    $tab_content .= '<div class="wpuf-overflow-hidden wpuf-mt-8 wpuf-shadow wpuf-outline wpuf-outline-1 wpuf-outline-black/5 wpuf-rounded-lg wpuf-dark:shadow-none wpuf-dark:-outline-offset-1 wpuf-dark:outline-white/10">';
                    $tab_content .= '<table class="wpuf-relative wpuf-min-w-full wpuf-divide-y wpuf-divide-gray-300 wpuf-dark:divide-white/15">';

                    // Table header
                    $tab_content .= '<thead class="wpuf-bg-gray-50 wpuf-dark:bg-gray-800/75">';
                    $tab_content .= '<tr>';
                    $tab_content .= '<th scope="col" class="wpuf-py-3.5 wpuf-pr-3 wpuf-pl-4 wpuf-text-left wpuf-text-sm wpuf-font-semibold wpuf-text-gray-900 wpuf-sm:pl-6 wpuf-dark:text-gray-200">';
                    $tab_content .= esc_html( apply_filters( 'wpuf_user_posts_title_label', __( 'Post Title', 'wpuf-pro' ), 'post' ) );
                    $tab_content .= '</th>';
                    $tab_content .= '<th scope="col" class="wpuf-px-3 wpuf-py-3.5 wpuf-text-left wpuf-text-sm wpuf-font-semibold wpuf-text-gray-900 wpuf-dark:text-gray-200">';
                    $tab_content .= esc_html( apply_filters( 'wpuf_user_posts_publish_date_label', __( 'Publish Date', 'wpuf-pro' ), 'post' ) );
                    $tab_content .= '</th>';
                    $tab_content .= '<th scope="col" class="wpuf-py-3.5 wpuf-pr-4 wpuf-pl-3 wpuf-sm:pr-6">';
                    $tab_content .= '<span class="wpuf-sr-only">' . esc_html__( 'View', 'wpuf-pro' ) . '</span>';
                    $tab_content .= '</th>';
                    $tab_content .= '</tr>';
                    $tab_content .= '</thead>';

                    // Table body
                    $tab_content .= '<tbody class="wpuf-divide-y wpuf-divide-gray-200 wpuf-bg-white wpuf-dark:divide-white/10 wpuf-dark:bg-gray-800/50">';

                    foreach ( $posts as $post ) {
                        $tab_content .= '<tr>';
                        $tab_content .= '<td class="wpuf-py-4 wpuf-pr-3 wpuf-pl-4 wpuf-text-sm wpuf-font-medium wpuf-whitespace-nowrap wpuf-text-gray-900 wpuf-sm:pl-6 wpuf-dark:text-white">';
                        $tab_content .= esc_html( get_the_title( $post->ID ) );
                        $tab_content .= '</td>';
                        $tab_content .= '<td class="wpuf-px-3 wpuf-py-4 wpuf-text-sm wpuf-whitespace-nowrap wpuf-text-gray-500 wpuf-dark:text-gray-400">';
                        $tab_content .= esc_html( get_the_date( 'F j, Y', $post->ID ) );
                        $tab_content .= '</td>';
                        $tab_content .= '<td class="wpuf-py-4 wpuf-pr-4 wpuf-pl-3 wpuf-text-right wpuf-text-sm wpuf-font-medium wpuf-whitespace-nowrap wpuf-sm:pr-6">';
                        $tab_content .= '<a href="' . esc_url( get_permalink( $post->ID ) ) . '" class="wpuf-text-indigo-600 wpuf-hover:text-indigo-900 wpuf-dark:text-indigo-400 wpuf-dark:hover:text-indigo-300">';
                        $tab_content .= esc_html__( 'Link ->', 'wpuf-pro' );
                        $tab_content .= '<span class="wpuf-sr-only">, ' . esc_html( get_the_title( $post->ID ) ) . '</span>';
                        $tab_content .= '</a>';
                        $tab_content .= '</td>';
                        $tab_content .= '</tr>';
                    }

                    $tab_content .= '</tbody>';
                    $tab_content .= '</table>';
                    $tab_content .= '</div>';

                    // Add pagination if enabled and there are multiple pages
                    if ( $show_posts_pagination && $total_posts_count > $posts_per_page ) {
                        $total_pages = ceil( $total_posts_count / $posts_per_page );
                        $tab_content .= $this->render_pagination_template( $current_page, $total_pages, $posts_per_page, $total_posts_count, 'posts_page' );
                    }
                } else {
                    $tab_content .= '<div class="wpuf-tab-empty">' . esc_html__( 'No posts found.', 'wpuf-pro' ) . '</div>';
                }

                $tab_content .= '</div>';
                $tab_content .= '</div>';
            } elseif ( $tab_id === 'comments' ) {
                // Comments tab: render user comments with modern design
                $tab_content .= sprintf(
                    '<div class="wpuf-tab-content %s" data-tab-id="%s">',
                    esc_attr( $active_class ),
                    esc_attr( $tab_id )
                );

                // Get user comments with pagination settings
                $comments_per_page = $attributes['commentsPerPage'] ?? 10;
                $show_comments_pagination = $attributes['showCommentsPagination'] ?? true;

                // Get current page from URL parameters
                $current_comments_page = isset( $_GET['comments_page'] ) ? max( 1, intval( $_GET['comments_page'] ) ) : 1;
                $offset = ( $current_comments_page - 1 ) * $comments_per_page;

                $comments = get_comments( [
                    'user_id'        => $user->ID,
                    'status'         => 'approve',
                    'number'         => $comments_per_page,
                    'offset'         => $offset,
                    'order'          => 'DESC',
                ] );

                // Get total comments count for pagination
                $total_comments_count = get_comments( [
                    'user_id' => $user->ID,
                    'status'  => 'approve',
                    'count'   => true,
                ] );

                if ( ! empty( $comments ) ) {
                    // Modern minimal design wrapper
                    $tab_content .= '<div class="wpuf-overflow-hidden wpuf-shadow wpuf-outline wpuf-outline-1 wpuf-outline-black/5 wpuf-rounded-lg wpuf-dark:shadow-none wpuf-dark:-outline-offset-1 wpuf-dark:outline-white/10">';
                    $tab_content .= '<div class="wpuf-divide-y wpuf-divide-gray-200 wpuf-bg-white wpuf-dark:divide-white/10 wpuf-dark:bg-gray-800/50">';

                    foreach ( $comments as $comment ) {
                        $comment_content = wp_strip_all_tags( $comment->comment_content );
                        $comment_excerpt = wp_trim_words( $comment_content, 20, '...' );
                        $comment_date    = date_i18n( 'M j, Y', strtotime( $comment->comment_date ) );
                        $post_title     = get_the_title( $comment->comment_post_ID );
                        $post_url       = get_permalink( $comment->comment_post_ID );
                        $reply_count    = get_comments( [
                            'parent' => $comment->comment_ID,
                            'count'  => true,
                        ] );

                        $tab_content .= sprintf(
                            '<div class="wpuf-px-4 wpuf-py-4">
                                <div class="wpuf-flex wpuf-items-start wpuf-gap-3">
                                    <div class="wpuf-flex-shrink-0">
                                        <div class="wpuf-w-8 wpuf-h-8 wpuf-bg-gray-200 wpuf-dark:bg-gray-700 wpuf-rounded-full wpuf-flex wpuf-items-center wpuf-justify-center">
                                            <span class="wpuf-text-xs wpuf-font-medium wpuf-text-gray-600 wpuf-dark:text-gray-300">%s</span>
                                        </div>
                                    </div>
                                    <div class="wpuf-flex-1 wpuf-min-w-0">
                                        <div class="wpuf-flex wpuf-items-center wpuf-gap-2 wpuf-mb-1">
                                            <span class="wpuf-text-sm wpuf-font-medium wpuf-text-gray-900 wpuf-dark:text-white">%s</span>
                                            <span class="wpuf-text-xs wpuf-text-gray-500 wpuf-dark:text-gray-400">%s</span>
                                        </div>
                                        <p class="wpuf-text-sm wpuf-text-gray-700 wpuf-dark:text-gray-300 wpuf-mb-2">%s</p>
                                        <div class="wpuf-flex wpuf-items-center wpuf-gap-4 wpuf-text-xs wpuf-text-gray-500 wpuf-dark:text-gray-400">
                                            <span>%s: <a href="%s" class="wpuf-text-indigo-600 wpuf-hover:text-indigo-900 wpuf-dark:text-indigo-400 wpuf-dark:hover:text-indigo-300">%s</a></span>%s
                                        </div>
                                    </div>
                                </div>
                            </div>',
                            esc_html( strtoupper( substr( $user->display_name, 0, 1 ) ) ),
                            esc_html( $user->display_name ),
                            esc_html( $comment_date ),
                            esc_html( $comment_excerpt ),
                            esc_html__( 'On', 'wpuf-pro' ),
                            esc_url( $post_url ),
                            esc_html( $post_title ),
                            $reply_count > 0 ? sprintf( '<span>%d %s</span>', $reply_count, esc_html__( 'replies', 'wpuf-pro' ) ) : ''
                        );
                    }

                    $tab_content .= '</div>';
                    $tab_content .= '</div>';

                    // Add pagination if enabled and there are multiple pages
                    if ( $show_comments_pagination && $total_comments_count > $comments_per_page ) {
                        $total_pages = ceil( $total_comments_count / $comments_per_page );
                        $tab_content .= $this->render_pagination_template( $current_comments_page, $total_pages, $comments_per_page, $total_comments_count, 'comments_page' );
                    }
                } else {
                    $tab_content .= '<div class="wpuf-px-4 wpuf-py-8 wpuf-text-center">';
                    $tab_content .= '<p class="wpuf-text-gray-500">' . esc_html__( 'No comments found for this user.', 'wpuf-pro' ) . '</p>';
                    $tab_content .= '</div>';
                }

                $tab_content .= '</div>';
            } elseif ( $tab_id === 'files' ) {
                // Files tab: render user files using FileHelper
                $tab_content .= sprintf(
                    '<div class="wpuf-tab-content %s" data-tab-id="%s">',
                    esc_attr( $active_class ),
                    esc_attr( $tab_id )
                );
                $tab_content .= '<div class="wpuf-files-tab-content">';

                // Use FileHelper to get user files
                $files = \WPUF\UserDirectory\FileHelper::get_user_attachments( $user->ID, 20 );

                if ( ! empty( $files ) ) {
                    $tab_content .= \WPUF\UserDirectory\FileHelper::render_file_grid( $files );
                } else {
                    $tab_content .= '<div class="wpuf-tab-empty">' . esc_html__( 'No files found for this user.', 'wpuf-pro' ) . '</div>';
                }

                $tab_content .= '</div>';
                $tab_content .= '</div>';
            } else {
                // Other tabs will be loaded dynamically
                $tab_content .= sprintf(
                    '<div class="wpuf-tab-content %s" data-tab-id="%s">',
                    esc_attr( $active_class ),
                    esc_attr( $tab_id )
                );
                $tab_content .= '<div class="wpuf-tab-loading">' . esc_html__( 'Loading...', 'wpuf-pro' ) . '</div>';
                $tab_content .= '</div>';
            }
        }

        $tab_content .= '</div>';

        // Build the complete HTML
        $html = $mobile_dropdown . $desktop_tabs . $tab_content;

        // Create tab configuration data for frontend JavaScript
        $tab_data = array_map( function( $tab ) {
            return [
                'id'    => $tab['id'],
                'label' => $tab['label'],
                'order' => $tab['order'],
            ];
        }, $enabled_tabs );

        // Always use WordPress wrapper attributes for consistent styling
        // Ensure frontend script is available
        wp_enqueue_script(
            'wpuf-user-tabs-frontend',
            WPUF_UD_ROOT_URI . '/assets/js/user-tabs-frontend.js',
            [ 'jquery' ],
            WPUF_UD_VERSION,
            true
        );

        // Extract pagination settings from block attributes
        $posts_per_page = $attributes['postsPerPage'] ?? 10;
        $show_posts_pagination = $attributes['showPostsPagination'] ?? true;
        $comments_per_page = $attributes['commentsPerPage'] ?? 10;
        $show_comments_pagination = $attributes['showCommentsPagination'] ?? true;

        $wrapper_attributes = wpuf_get_block_wrapper_attributes(
            $attributes,
            'user-tabs',
            [
                'class'             => 'wpuf-user-tabs',
                'data-default-tab'  => $default_active_tab,
                'data-user-id'      => $user->ID,
                'data-posts-per-page' => $posts_per_page,
                'data-show-posts-pagination' => $show_posts_pagination ? 'true' : 'false',
                'data-comments-per-page' => $comments_per_page,
                'data-show-comments-pagination' => $show_comments_pagination ? 'true' : 'false',
            ]
        );

        // Add tab configuration script
        $tab_config_script = '<script type="application/json" class="wpuf-tab-config">' . wp_json_encode( $tab_data ) . '</script>';

        return sprintf( '<div %1$s>%2$s%3$s</div>', $wrapper_attributes, $tab_config_script, $html );
    }

    /**
     * Render pagination controls for tabs
     *
     * @since 4.2.0
     *
     * @param int    $current_page Current page number
     * @param int    $total_pages  Total number of pages
     * @param string $param_name   URL parameter name (e.g., 'posts_page', 'comments_page')
     *
     * @return string HTML for pagination controls
     */
    private function render_pagination_controls( $current_page, $total_pages, $param_name ) {
        if ( $total_pages <= 1 ) {
            return '';
        }

        $html = '<div class="wpuf-flex wpuf-items-center wpuf-justify-center wpuf-mt-8 wpuf-gap-2">';

        // Previous button
        if ( $current_page > 1 ) {
            $prev_page = $current_page - 1;
            $prev_url = $this->build_pagination_url( $param_name, $prev_page );
            $html .= sprintf(
                '<a href="%s" class="wpuf-px-3 wpuf-py-2 wpuf-text-sm wpuf-font-medium wpuf-text-gray-500 wpuf-bg-white wpuf-border wpuf-border-gray-300 wpuf-rounded-md wpuf-hover:bg-gray-50 wpuf-hover:text-gray-700">%s</a>',
                esc_url( $prev_url ),
                esc_html__( 'Previous', 'wpuf-pro' )
            );
        }

        // Page numbers
        $start_page = max( 1, $current_page - 2 );
        $end_page = min( $total_pages, $current_page + 2 );

        if ( $start_page > 1 ) {
            $html .= sprintf(
                '<a href="%s" class="wpuf-px-3 wpuf-py-2 wpuf-text-sm wpuf-font-medium wpuf-text-gray-500 wpuf-bg-white wpuf-border wpuf-border-gray-300 wpuf-rounded-md wpuf-hover:bg-gray-50 wpuf-hover:text-gray-700">1</a>',
                esc_url( $this->build_pagination_url( $param_name, 1 ) )
            );
            if ( $start_page > 2 ) {
                $html .= '<span class="wpuf-px-3 wpuf-py-2 wpuf-text-sm wpuf-text-gray-500">...</span>';
            }
        }

        for ( $i = $start_page; $i <= $end_page; $i++ ) {
            if ( $i === $current_page ) {
                $html .= sprintf(
                    '<span class="wpuf-px-3 wpuf-py-2 wpuf-text-sm wpuf-font-medium wpuf-text-white wpuf-bg-indigo-600 wpuf-border wpuf-border-indigo-600 wpuf-rounded-md">%d</span>',
                    $i
                );
            } else {
                $html .= sprintf(
                    '<a href="%s" class="wpuf-px-3 wpuf-py-2 wpuf-text-sm wpuf-font-medium wpuf-text-gray-500 wpuf-bg-white wpuf-border wpuf-border-gray-300 wpuf-rounded-md wpuf-hover:bg-gray-50 wpuf-hover:text-gray-700">%d</a>',
                    esc_url( $this->build_pagination_url( $param_name, $i ) ),
                    $i
                );
            }
        }

        if ( $end_page < $total_pages ) {
            if ( $end_page < $total_pages - 1 ) {
                $html .= '<span class="wpuf-px-3 wpuf-py-2 wpuf-text-sm wpuf-text-gray-500">...</span>';
            }
            $html .= sprintf(
                '<a href="%s" class="wpuf-px-3 wpuf-py-2 wpuf-text-sm wpuf-font-medium wpuf-text-gray-500 wpuf-bg-white wpuf-border wpuf-border-gray-300 wpuf-rounded-md wpuf-hover:bg-gray-50 wpuf-hover:text-gray-700">%d</a>',
                esc_url( $this->build_pagination_url( $param_name, $total_pages ) ),
                $total_pages
            );
        }

        // Next button
        if ( $current_page < $total_pages ) {
            $next_page = $current_page + 1;
            $next_url = $this->build_pagination_url( $param_name, $next_page );
            $html .= sprintf(
                '<a href="%s" class="wpuf-px-3 wpuf-py-2 wpuf-text-sm wpuf-font-medium wpuf-text-gray-500 wpuf-bg-white wpuf-border wpuf-border-gray-300 wpuf-rounded-md wpuf-hover:bg-gray-50 wpuf-hover:text-gray-700">%s</a>',
                esc_url( $next_url ),
                esc_html__( 'Next', 'wpuf-pro' )
            );
        }

        $html .= '</div>';
        return $html;
    }

    /**
     * Build pagination URL with parameter
     *
     * @since 4.2.0
     *
     * @param string $param_name Parameter name
     * @param int    $page      Page number
     *
     * @return string URL with pagination parameter
     */
    private function build_pagination_url( $param_name, $page ) {
        $current_url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
        $parsed_url = wp_parse_url( $current_url );
        $base_url = $parsed_url['path'] ?? '';

        $query_args = [];
        if ( ! empty( $parsed_url['query'] ) ) {
            parse_str( $parsed_url['query'], $query_args );
        }

        $query_args[ $param_name ] = $page;

        return $base_url . '?' . http_build_query( $query_args );
    }

    /**
     * Render pagination using the template for static rendering
     *
     * @since 4.2.0
     *
     * @param int    $current_page Current page number
     * @param int    $total_pages  Total number of pages
     * @param int    $per_page     Items per page
     * @param int    $total_items  Total number of items
     * @param string $param_name   URL parameter name (e.g., 'posts_page', 'comments_page')
     *
     * @return string HTML for pagination controls
     */
    private function render_pagination_template( $current_page, $total_pages, $per_page, $total_items, $param_name ) {
        if ( $total_pages <= 1 ) {
            return '';
        }

        // Prepare pagination data for template
        $pagination = [
            'total_pages'  => $total_pages,
            'current_page' => $current_page,
            'per_page'     => $per_page,
            'total_items'  => $total_items,
        ];

        // Set up URL builder for static context
        $GLOBALS['wpuf_pagination_url_builder'] = [ $this, 'build_static_pagination_url' ];

        // Store param_name for the URL builder
        $this->current_pagination_param = $param_name;

        // Start output buffering to capture template
        ob_start();
        include WPUF_UD_TEMPLATES . '/blocks/user-directory/components/pagination.php';
        $pagination_html = ob_get_clean();

        return $pagination_html;
    }

    /**
     * Build pagination URL for static context
     *
     * @since 4.2.0
     *
     * @param string $base_url Base URL
     * @param array  $query_args Query arguments
     * @param int    $page Page number
     *
     * @return string Pagination URL
     */
    public function build_static_pagination_url( $base_url, $query_args, $page ) {
        // Use the existing build_pagination_url method
        return $this->build_pagination_url( $this->current_pagination_param, $page );
    }

    /**
     * Check if current user can edit the given user's profile
     *
     * @since 4.2.0
     *
     * @param \WP_User $user User object for the profile
     *
     * @return bool
     */
    public function can_user_edit_profile( $user ) {
        // Get current user to check permissions
        $current_user_id = get_current_user_id();
        $can_edit = $current_user_id && $current_user_id === $user->ID;

        // Additional WPUF checks for edit profile functionality
        $account_page_id = wpuf_get_option( 'account_page', 'wpuf_my_account', 0 );
        $show_edit_profile = wpuf_get_option( 'show_edit_profile_menu', 'wpuf_my_account', 'off' );

        // Only allow edit if all conditions are met
        return $can_edit &&
               ! empty( $account_page_id ) &&
               'on' === $show_edit_profile;
    }

    /**
     * Render profile navigation buttons
     *
     * @since 4.2.0
     *
     * @param \WP_User $user User object for the profile
     *
     * @return string
     */
    private function render_profile_navigation_buttons( $user ) {
        // Check if current user can edit this profile
        $can_edit = $this->can_user_edit_profile( $user );

        // Build navigation HTML using Tailwind classes
        $html = '<div class="wpuf-profile-navigation wpuf-flex wpuf-justify-between wpuf-items-center wpuf-mb-6 wpuf-py-3">';

        // Back button (left side)
        $html .= '<button type="button" ';
        $html .= 'class="wpuf-nav-button wpuf-back-button wpuf-inline-flex wpuf-items-center wpuf-gap-2 wpuf-px-4 wpuf-py-2 wpuf-text-sm wpuf-font-medium wpuf-text-gray-700 wpuf-bg-white wpuf-border wpuf-border-gray-300 wpuf-rounded-md wpuf-shadow-sm hover:wpuf-bg-gray-50 hover:wpuf-text-gray-900 focus:wpuf-outline-none focus:wpuf-ring-2 focus:wpuf-ring-offset-2 focus:wpuf-ring-indigo-500 wpuf-transition-colors wpuf-duration-200" ';
        $html .= 'aria-label="' . esc_attr__( 'Go back to listing', 'wpuf-pro' ) . '"';
        $html .= '>';
        // Left arrow icon
        $html .= '<svg class="wpuf-w-4 wpuf-h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">';
        $html .= '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>';
        $html .= '</svg>';
        $html .= esc_html__( 'Back', 'wpuf-pro' );
        $html .= '</button>';

        // Edit profile button (right side) - only show if user can edit
        if ( $can_edit ) {
            $html .= '<button type="button" ';
            $html .= 'class="wpuf-nav-button wpuf-edit-button wpuf-inline-flex wpuf-items-center wpuf-gap-2 wpuf-px-4 wpuf-py-2 wpuf-text-sm wpuf-font-medium wpuf-text-gray-700 wpuf-bg-white wpuf-border wpuf-border-gray-300 wpuf-rounded-md wpuf-shadow-sm hover:wpuf-bg-gray-50 hover:wpuf-text-gray-900 focus:wpuf-outline-none focus:wpuf-ring-2 focus:wpuf-ring-offset-2 focus:wpuf-ring-indigo-500 wpuf-transition-colors wpuf-duration-200" ';
            $html .= 'onclick="wpufProfileEditMode()" ';
            $html .= 'aria-label="' . esc_attr__( 'Edit profile', 'wpuf-pro' ) . '"';
            $html .= '>';
            $html .= esc_html__( 'Edit Profile', 'wpuf-pro' );
            // Edit icon
            $html .= '<svg class="wpuf-w-4 wpuf-h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">';
            $html .= '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"></path>';
            $html .= '</svg>';
            $html .= '</button>';
        } else {
            // Empty space to maintain flexbox layout balance
            $html .= '<div></div>';
        }

        $html .= '</div>';

        return $html;
    }

    /**
     * Render a parsed block with user context
     *
     * @since 4.2.0
     *
     * @param array $block_data Parsed block data.
     * @param array $context    User context.
     *
     * @return string
     */
    private function render_parsed_block_with_context( $block_data, $context ) {
        if ( empty( $block_data ) || ! is_array( $block_data ) ) {
            return '';
        }

        $block_name = $block_data['blockName'] ?? '';
        $attributes = $block_data['attrs'] ?? [];
        $inner_blocks = $block_data['innerBlocks'] ?? [];

        // Handle different block types
        switch ( $block_name ) {
            case 'wpuf-ud/avatar':
                return $this->render_user_avatar_block( [ 'attrs' => $attributes ], $context );

            case 'wpuf-ud/cover-photo':
                return $this->render_user_cover_photo_block( [ 'attrs' => $attributes ], $context );

            case 'wpuf-ud/name':
                return $this->render_user_name_block( [ 'attrs' => $attributes ], $context );

            case 'wpuf-ud/contact':
                return $this->render_user_contact_info_block( [ 'attrs' => $attributes ], $context );

            case 'wpuf-ud/profile-button':
                return $this->render_profile_button_block( [ 'attrs' => $attributes ], $context );

            case 'wpuf-ud/message-button':
                return $this->render_message_button_block( [ 'attrs' => $attributes ], $context );

            case 'wpuf-ud/bio':
                return $this->render_user_bio_block( [ 'attrs' => $attributes ], $context );

            case 'wpuf-ud/custom-field':
                return $this->render_user_custom_field_block( [ 'attrs' => $attributes ], $context );

            case 'wpuf-ud/files':
                return $this->render_user_files_block( [ 'attrs' => $attributes ], $context );

            case 'wpuf-ud/posts':
                return $this->render_user_posts_block( [ 'attrs' => $attributes ], $context );

            case 'wpuf-ud/comments':
                return $this->render_user_comments_block( [ 'attrs' => $attributes ], $context );

            case 'wpuf-ud/tabs':
                return $this->render_user_tabs_block( [ 'attrs' => $attributes, 'innerBlocks' => $inner_blocks ], $context );

            case 'wpuf-ud/social':
                return $this->render_user_social_fields_block( [ 'attrs' => $attributes ], $context );

            case 'wpuf-ud/profile':
                // For profile blocks, render inner blocks with context and wrap with appropriate HTML
                // Add profile context flag to track nested calls
                $profile_context = array_merge( $context, [ 'wpuf-ud/fromProfile' => true ] );

                $inner_content = '';
                foreach ( $inner_blocks as $inner_block ) {
                    $inner_content .= $this->render_parsed_block_with_context( $inner_block, $profile_context );
                }

                // Build wrapper attributes for profile blocks
                $wrapper_attributes = $this->build_profile_block_wrapper_attributes( $attributes );
                return '<div ' . $wrapper_attributes . '>' . $inner_content . '</div>';

            case 'core/group':
            case 'core/columns':
            case 'core/column':
                // For core blocks, render inner blocks and wrap with appropriate HTML
                $inner_content = '';
                foreach ( $inner_blocks as $inner_block ) {
                    $inner_content .= $this->render_parsed_block_with_context( $inner_block, $context );
                }

                // For group blocks, manually build wrapper attributes to preserve alignment classes
                if ( $block_name === 'core/group' ) {
                    $wrapper_attributes = $this->build_group_block_wrapper_attributes( $attributes );
                    return '<div ' . $wrapper_attributes . '>' . $inner_content . '</div>';
                }

                // For columns blocks, build custom wrapper attributes
                if ( $block_name === 'core/columns' ) {

                    $wrapper_attributes = $this->build_columns_block_wrapper_attributes( $attributes );


                    return '<div ' . $wrapper_attributes . '>' . $inner_content . '</div>';
                }

                // For column blocks, build custom wrapper attributes
                if ( $block_name === 'core/column' ) {

                    $wrapper_attributes = $this->build_column_block_wrapper_attributes( $attributes );


                    return '<div ' . $wrapper_attributes . '>' . $inner_content . '</div>';
                }

                return $inner_content;

            default:
                // For WordPress core blocks and unknown blocks, use WordPress's built-in rendering
                if ( strpos( $block_name, 'core/' ) === 0 ) {
                    // Use WordPress's built-in block rendering for core blocks
                    $block_instance = new \WP_Block( $block_data );
                    return $block_instance->render();
                } else {
                    // For unknown blocks, try to render inner blocks
                    $inner_content = '';
                    foreach ( $inner_blocks as $inner_block ) {
                        $inner_content .= $this->render_parsed_block_with_context( $inner_block, $context );
                    }
                    return $inner_content;
                }
        }


    }

    /**
     * Render inner blocks with user context
     *
     * @since 4.2.0
     *
     * @param \WP_Block $block   Block object.
     * @param array     $context User context.
     *
     * @return string
     */
    private function render_inner_blocks_with_context( $block, $context ) {
        $content = '';
        // Validate block object
        if ( ! $block || ! is_object( $block ) ) {
            return $content;
        }
        // Get user object and attributes for placeholder replacement
        $user       = $context['wpuf-ud/userObject'] ?? null;
        $attributes = $context['wpuf-ud/attributes'] ?? [];

        // First, try to render from parsed_block['innerBlocks'] if available
        if ( ! empty( $block->parsed_block['innerBlocks'] ) ) {
            foreach ( $block->parsed_block['innerBlocks'] as $index => $inner_block_data ) {
                // Check if this is a WPUF block that needs special handling
                $block_name = $inner_block_data['blockName'] ?? '';
                if ( strpos( $block_name, 'wpuf-ud/' ) === 0 ) {
                    // Add profile context flag if we're in profile mode
                    $profile_context = $context;
                    if ( ! empty( $context['wpuf-ud/isProfileMode'] ) ) {
                        $profile_context = array_merge( $context, [ 'wpuf-ud/fromProfile' => true ] );
                    }

                    // Handle WPUF blocks with our custom render method
                    $block_content = $this->render_parsed_block_with_context( $inner_block_data, $profile_context );
                } else {
                    // Handle WordPress core blocks - render recursively to get inner blocks
                    $block_content = $this->render_parsed_block_recursively( $inner_block_data, $context );
                }

                $content .= $block_content;
            }
        }
        // Fallback to inner_content if no parsed blocks
        elseif ( ! empty( $block->inner_content ) ) {
            foreach ( $block->inner_content as $index => $inner_block ) {
                // Handle string content (HTML markup)
                if ( is_string( $inner_block ) ) {
                    $content .= $inner_block;
                    continue;
                }
                // Handle null or empty inner blocks
                if ( empty( $inner_block ) ) {
                    continue;
                }
                // Validate inner block object
                if ( ! is_object( $inner_block ) ) {
                    continue;
                }
                // Check if the inner block has required properties
                if ( ! isset( $inner_block->name ) ) {
                    continue;
                }
                // Check if this is the directory-item block
                if ( $inner_block->name === 'wpuf-ud/directory-item' ) {
                    // Render the user-directory-item's inner blocks with user context
                    $content .= $this->render_inner_blocks_with_context( $inner_block, $context );
                } else {
                    // Render other blocks normally
                    $content .= $this->render_block_with_context( $inner_block, $context );
                }
            }
        }

        return $content;
    }

    /**
     * Render a parsed block recursively, handling both WordPress core blocks and WPUF blocks
     *
     * @since 4.2.0
     *
     * @param array $block_data Parsed block data.
     * @param array $context    User context.
     *
     * @return string
     */
    private function render_parsed_block_recursively( $block_data, $context ) {
        $block_name = $block_data['blockName'] ?? '';
        $attributes = $block_data['attrs'] ?? [];
        $inner_blocks = $block_data['innerBlocks'] ?? [];

        // If this is a WPUF block, render it with our custom method
        if ( strpos( $block_name, 'wpuf-ud/' ) === 0 ) {
            return $this->render_parsed_block_with_context( $block_data, $context );
        }

        // For core blocks that we have dedicated methods for, use them to get proper styling
        if ( in_array( $block_name, [ 'core/group', 'core/columns', 'core/column' ] ) ) {

            return $this->render_parsed_block_with_context( $block_data, $context );
        }

        // For other WordPress core blocks, render inner blocks recursively
        $content = '';
        foreach ( $inner_blocks as $inner_block_data ) {
            $content .= $this->render_parsed_block_recursively( $inner_block_data, $context );
        }

        // For core blocks that need wrapper HTML, create a simple wrapper
        if ( ! empty( $content ) ) {
            // Get wrapper attributes for the block
            $wrapper_attributes = wpuf_get_block_wrapper_attributes( $attributes, str_replace( 'core/', '', $block_name ), [] );
            $content = '<div ' . $wrapper_attributes . '>' . $content . '</div>';
        }

        return $content;
    }

    /**
     * Render a single block with user context
     *
     * @since 4.2.0
     *
     * @param \WP_Block $inner_block Inner block object.
     * @param array     $context     User context.
     *
     * @return string
     */
    private function render_block_with_context( $inner_block, $context ) {
        // Validate inner block object
        if ( ! $inner_block || ! is_object( $inner_block ) ) {
            return '';
        }
        // Set the context for the block - ensure context is an array
        $existing_context     = is_array( $inner_block->context ?? null ) ? $inner_block->context : [];
        $inner_block->context = array_merge( $existing_context, $context );

        // Render the block
        return $inner_block->render();
    }

    /**
     * Clear debug log entries for this module
     *
     * @since 4.2.0
     * @return void
     */
    public function clear_debug_logs() {
        $debug_log_path = WP_CONTENT_DIR . '/debug.log';
        if ( file_exists( $debug_log_path ) ) {
            // Read the file and filter out WPUF User Directory entries
            $lines          = file( $debug_log_path, FILE_IGNORE_NEW_LINES );
            $filtered_lines = array_filter(
                $lines, function( $line ) {
                return strpos( $line, 'WPUF User Directory:' ) === false;
            }
            );
            // Write back the filtered content
            file_put_contents( $debug_log_path, implode( "\n", $filtered_lines ) . "\n" );
        }
    }

    /**
     * Render template block with user context using Query Loop style approach
     *
     * @since 4.2.0
     *
     * @param array $template_block Template block data.
     * @param array $user_context   User context.
     *
     * @return string
     */
    private function render_template_block_with_context( $template_block, $user_context ) {
        // Validate template_block parameter
        if ( ! $template_block || ! is_array( $template_block ) ) {
            // Return empty content if template_block is invalid
            return '';
        }

        // Instead of using WP_Block which causes infinite recursion,
        // we'll directly render the inner blocks using our existing render methods
        $content = '';

        if ( ! empty( $template_block['innerBlocks'] ) ) {
            foreach ( $template_block['innerBlocks'] as $inner_block_data ) {
                $content .= $this->render_parsed_block_with_context( $inner_block_data, $user_context );
            }
        }

        // Ensure template_block['attrs'] exists and is an array
        $attrs = isset( $template_block['attrs'] ) && is_array( $template_block['attrs'] ) ? $template_block['attrs'] : [];

        // Ensure attrs is a valid array for WordPress block processing
        if ( ! is_array( $attrs ) ) {
            $attrs = [];
        }

        // Filter out any non-scalar values that might cause issues with WordPress block processing
        $filtered_attrs = [];
        if ( is_array( $attrs ) ) {
            foreach ( $attrs as $key => $value ) {
                if ( is_scalar( $value ) || is_null( $value ) ) {
                    $filtered_attrs[ $key ] = $value;
                }
            }
        }

        // Use a safer approach to get wrapper attributes
        // Instead of calling get_block_wrapper_attributes directly, build the attributes manually
        $wrapper_classes = 'wpuf-user-card';
        $wrapper_styles = '';

        // Add any custom classes from attributes
        if ( ! empty( $filtered_attrs['className'] ) ) {
            $wrapper_classes .= ' ' . esc_attr( $filtered_attrs['className'] );
        }

        // Add any custom styles from attributes
        if ( ! empty( $filtered_attrs['style'] ) && is_string( $filtered_attrs['style'] ) ) {
            $wrapper_styles = ' style="' . esc_attr( $filtered_attrs['style'] ) . '"';
        }

        // Add any custom attributes
        $custom_attrs = '';
        if ( ! empty( $filtered_attrs['id'] ) ) {
            $custom_attrs .= ' id="' . esc_attr( $filtered_attrs['id'] ) . '"';
        }

        $final_content = '<div class="' . $wrapper_classes . '"' . $wrapper_styles . $custom_attrs . '>' . $content . '</div>';

        return $final_content;
    }

    /**
     * Build wrapper attributes for core/group blocks
     *
     * This method manually constructs the wrapper attributes for group blocks
     * to preserve proper alignment classes like is-content-justification-center
     * without relying on get_block_wrapper_attributes which expects a different context.
     *
     * @since 4.2.0
     *
     * @param array $attributes Block attributes from the parsed block.
     *
     * @return string HTML attributes string for the group block wrapper.
     */
    private function build_group_block_wrapper_attributes( $attributes ) {
        $classes = [ 'wp-block-group' ];
        $styles = [];

        // Handle layout attributes
        if ( ! empty( $attributes['layout'] ) && is_array( $attributes['layout'] ) ) {
            $layout = $attributes['layout'];

            // Handle flex layout
            if ( ! empty( $layout['type'] ) && $layout['type'] === 'flex' ) {
                $classes[] = 'is-layout-flex';
                $classes[] = 'wp-block-group-is-layout-flex';

                // Handle orientation
                if ( ! empty( $layout['orientation'] ) ) {
                    if ( $layout['orientation'] === 'vertical' ) {
                        $classes[] = 'is-vertical';
                    } elseif ( $layout['orientation'] === 'horizontal' ) {
                        $classes[] = 'is-horizontal';
                    }
                }

                // Handle justification (alignment)
                if ( ! empty( $layout['justifyContent'] ) ) {
                    switch ( $layout['justifyContent'] ) {
                        case 'left':
                            $classes[] = 'is-content-justification-left';
                            break;
                        case 'center':
                            $classes[] = 'is-content-justification-center';
                            break;
                        case 'right':
                            $classes[] = 'is-content-justification-right';
                            break;
                        case 'space-between':
                            $classes[] = 'is-content-justification-space-between';
                            break;
                    }
                }

                // Handle vertical alignment
                if ( ! empty( $layout['verticalAlignment'] ) ) {
                    switch ( $layout['verticalAlignment'] ) {
                        case 'top':
                            $classes[] = 'is-vertically-aligned-top';
                            break;
                        case 'center':
                            $classes[] = 'is-vertically-aligned-center';
                            break;
                        case 'bottom':
                            $classes[] = 'is-vertically-aligned-bottom';
                            break;
                    }
                }

                // Handle flex wrap
                if ( ! empty( $layout['flexWrap'] ) && $layout['flexWrap'] === 'nowrap' ) {
                    $classes[] = 'is-nowrap';
                }
            }

            // Handle constrained layout
            if ( ! empty( $layout['type'] ) && $layout['type'] === 'constrained' ) {
                $classes[] = 'is-layout-constrained';
                $classes[] = 'wp-block-group-is-layout-constrained';
            }
        }

        // Handle spacing attributes
        if ( ! empty( $attributes['spacing'] ) && is_array( $attributes['spacing'] ) ) {
            $spacing = $attributes['spacing'];

            // Handle margins
            if ( ! empty( $spacing['margin'] ) && is_array( $spacing['margin'] ) ) {
                foreach ( $spacing['margin'] as $side => $value ) {
                    if ( ! empty( $value ) ) {
                        $styles["margin-{$side}"] = $this->process_preset_value( $value );
                    }
                }
            }

            // Handle padding
            if ( ! empty( $spacing['padding'] ) && is_array( $spacing['padding'] ) ) {
                foreach ( $spacing['padding'] as $side => $value ) {
                    if ( ! empty( $value ) ) {
                        $styles["padding-{$side}"] = $this->process_preset_value( $value );
                    }
                }
            }

            // Handle block gap
            if ( isset( $spacing['blockGap'] ) ) {
                $styles['gap'] = $this->process_preset_value( $spacing['blockGap'] );
            }
        }

        // Handle border attributes
        if ( ! empty( $attributes['border'] ) && is_array( $attributes['border'] ) ) {
            $border = $attributes['border'];

            if ( ! empty( $border['radius'] ) ) {
                $styles['border-radius'] = $border['radius'];
            }
            if ( ! empty( $border['width'] ) ) {
                $styles['border-width'] = $border['width'];
            }
            if ( ! empty( $border['color'] ) ) {
                $styles['border-color'] = $this->process_preset_value( $border['color'] );
                $classes[] = 'has-border-color';
            }
        }

        // Handle dimensions attributes
        if ( ! empty( $attributes['dimensions'] ) && is_array( $attributes['dimensions'] ) ) {
            $dimensions = $attributes['dimensions'];

            if ( ! empty( $dimensions['minHeight'] ) ) {
                $styles['min-height'] = $this->process_preset_value( $dimensions['minHeight'] );
            }
            if ( ! empty( $dimensions['height'] ) ) {
                $styles['height'] = $this->process_preset_value( $dimensions['height'] );
            }
            if ( ! empty( $dimensions['maxHeight'] ) ) {
                $styles['max-height'] = $this->process_preset_value( $dimensions['maxHeight'] );
            }
            if ( ! empty( $dimensions['minWidth'] ) ) {
                $styles['min-width'] = $this->process_preset_value( $dimensions['minWidth'] );
            }
            if ( ! empty( $dimensions['width'] ) ) {
                $styles['width'] = $this->process_preset_value( $dimensions['width'] );
            }
            if ( ! empty( $dimensions['maxWidth'] ) ) {
                $styles['max-width'] = $this->process_preset_value( $dimensions['maxWidth'] );
            }
        }

        // Handle style attributes (WordPress block editor styles)
        if ( ! empty( $attributes['style'] ) && is_array( $attributes['style'] ) ) {
            $style_attr = $attributes['style'];

            // Handle border from style attribute
            if ( ! empty( $style_attr['border'] ) && is_array( $style_attr['border'] ) ) {
                $border = $style_attr['border'];

                if ( ! empty( $border['radius'] ) ) {
                    $styles['border-radius'] = $border['radius'];
                }
                if ( ! empty( $border['width'] ) ) {
                    $styles['border-width'] = $border['width'];
                }
                if ( ! empty( $border['color'] ) ) {
                    $styles['border-color'] = $this->process_preset_value( $border['color'] );
                    $classes[] = 'has-border-color';
                }
                // Check if we have individual border sides
                $has_individual_sides = false;
                if ( ( ! empty( $border['top'] ) && is_array( $border['top'] ) ) ||
                     ( ! empty( $border['bottom'] ) && is_array( $border['bottom'] ) ) ||
                     ( ! empty( $border['left'] ) && is_array( $border['left'] ) ) ||
                     ( ! empty( $border['right'] ) && is_array( $border['right'] ) ) ) {
                    $has_individual_sides = true;
                }

                // Only set general border-style if no individual sides are defined
                if ( ! $has_individual_sides && ! empty( $border['style'] ) ) {
                    $styles['border-style'] = $border['style'];
                }

                // Handle individual border sides
                if ( ! empty( $border['top'] ) && is_array( $border['top'] ) ) {
                    $top_border = $this->process_border_side( $border['top'] );
                    if ( ! empty( $top_border ) ) {
                        $styles['border-top'] = $top_border;
                    }
                }
                if ( ! empty( $border['bottom'] ) && is_array( $border['bottom'] ) ) {
                    $bottom_border = $this->process_border_side( $border['bottom'] );
                    if ( ! empty( $bottom_border ) ) {
                        $styles['border-bottom'] = $bottom_border;
                    }
                }
                if ( ! empty( $border['left'] ) && is_array( $border['left'] ) ) {
                    $left_border = $this->process_border_side( $border['left'] );
                    if ( ! empty( $left_border ) ) {
                        $styles['border-left'] = $left_border;
                    }
                }
                if ( ! empty( $border['right'] ) && is_array( $border['right'] ) ) {
                    $right_border = $this->process_border_side( $border['right'] );
                    if ( ! empty( $right_border ) ) {
                        $styles['border-right'] = $right_border;
                    }
                }
            }

            // Handle spacing from style attribute
            if ( ! empty( $style_attr['spacing'] ) && is_array( $style_attr['spacing'] ) ) {
                $spacing = $style_attr['spacing'];

                // Handle margins from style.spacing
                if ( ! empty( $spacing['margin'] ) && is_array( $spacing['margin'] ) ) {
                    foreach ( $spacing['margin'] as $side => $value ) {
                        if ( ! empty( $value ) ) {
                            $styles["margin-{$side}"] = $this->process_preset_value( $value );
                        }
                    }
                }

                // Handle padding from style.spacing
                if ( ! empty( $spacing['padding'] ) && is_array( $spacing['padding'] ) ) {
                    foreach ( $spacing['padding'] as $side => $value ) {
                        if ( ! empty( $value ) ) {
                            $styles["padding-{$side}"] = $this->process_preset_value( $value );
                        }
                    }
                }

                // Handle block gap from style.spacing
                if ( isset( $spacing['blockGap'] ) ) {
                    $styles['gap'] = $this->process_preset_value( $spacing['blockGap'] );
                }
            }

            // Handle dimensions from style attribute
            if ( ! empty( $style_attr['dimensions'] ) && is_array( $style_attr['dimensions'] ) ) {
                $dimensions = $style_attr['dimensions'];

                if ( ! empty( $dimensions['minHeight'] ) ) {
                    $styles['min-height'] = $this->process_preset_value( $dimensions['minHeight'] );
                }
                if ( ! empty( $dimensions['height'] ) ) {
                    $styles['height'] = $this->process_preset_value( $dimensions['height'] );
                }
                if ( ! empty( $dimensions['maxHeight'] ) ) {
                    $styles['max-height'] = $this->process_preset_value( $dimensions['maxHeight'] );
                }
                if ( ! empty( $dimensions['minWidth'] ) ) {
                    $styles['min-width'] = $this->process_preset_value( $dimensions['minWidth'] );
                }
                if ( ! empty( $dimensions['width'] ) ) {
                    $styles['width'] = $this->process_preset_value( $dimensions['width'] );
                }
                if ( ! empty( $dimensions['maxWidth'] ) ) {
                    $styles['max-width'] = $this->process_preset_value( $dimensions['maxWidth'] );
                }
            }
        }

        // Add default style class if not present
        if ( ! in_array( 'is-style-default', $classes ) ) {
            $classes[] = 'is-style-default';
        }

        // Handle fontSize attribute
        if ( ! empty( $attributes['fontSize'] ) ) {
            $classes[] = 'has-' . sanitize_html_class( $attributes['fontSize'] ) . '-font-size';
        }

        // Handle color attributes
        if ( ! empty( $attributes['textColor'] ) ) {
            $text_slug = sanitize_key( $attributes['textColor'] );
            $classes[] = 'has-text-color';
            $classes[] = 'has-' . $text_slug . '-color';
        }
        if ( ! empty( $attributes['backgroundColor'] ) ) {
            $bg_slug = sanitize_key( $attributes['backgroundColor'] );
            $classes[] = 'has-background';
            $classes[] = 'has-' . $bg_slug . '-background-color';
        }

        // Handle style.color structure
        if ( ! empty( $attributes['style']['color'] ) && is_array( $attributes['style']['color'] ) ) {
            $color_style = $attributes['style']['color'];
            if ( ! empty( $color_style['text'] ) ) {
                $styles['color'] = $this->process_preset_value( $color_style['text'] );
                $classes[] = 'has-text-color';
            }
            if ( ! empty( $color_style['background'] ) ) {
                $styles['background-color'] = $this->process_preset_value( $color_style['background'] );
                $classes[] = 'has-background';
            }
        }

        // Handle custom className
        if ( ! empty( $attributes['className'] ) ) {
            $classes[] = sanitize_html_class( $attributes['className'] );
        }

        // Build the attributes string
        $class_string = implode( ' ', array_filter( $classes ) );
        $style_string = '';

        if ( ! empty( $styles ) ) {
            $style_parts = [];
            foreach ( $styles as $property => $value ) {
                $style_parts[] = esc_attr( $property ) . ': ' . esc_attr( $value );
            }
            $style_string = ' style="' . implode( '; ', $style_parts ) . '"';
        }

        return 'class="' . esc_attr( $class_string ) . '"' . $style_string;
    }

    /**
     * Build wrapper attributes for core/columns blocks
     *
     * @since 4.2.0
     *
     * @param array $attributes Block attributes.
     * @return string Wrapper attributes string.
     */
    private function build_columns_block_wrapper_attributes( $attributes ) {
        $classes = [ 'wp-block-columns' ];
        $styles = [];


        // Handle layout attributes
        if ( ! empty( $attributes['layout'] ) && is_array( $attributes['layout'] ) ) {
            $layout = $attributes['layout'];

            // Handle flex layout
            if ( ! empty( $layout['type'] ) && $layout['type'] === 'flex' ) {
                $classes[] = 'is-layout-flex';
                $classes[] = 'wp-block-columns-is-layout-flex';

                // Handle orientation
                if ( ! empty( $layout['orientation'] ) ) {
                    if ( $layout['orientation'] === 'vertical' ) {
                        $classes[] = 'is-vertical';
                    } elseif ( $layout['orientation'] === 'horizontal' ) {
                        $classes[] = 'is-horizontal';
                    }
                }

                // Handle justification (alignment)
                if ( ! empty( $layout['justifyContent'] ) ) {
                    switch ( $layout['justifyContent'] ) {
                        case 'left':
                            $classes[] = 'is-content-justification-left';
                            break;
                        case 'center':
                            $classes[] = 'is-content-justification-center';
                            break;
                        case 'right':
                            $classes[] = 'is-content-justification-right';
                            break;
                        case 'space-between':
                            $classes[] = 'is-content-justification-space-between';
                            break;
                    }
                }

                // Handle vertical alignment
                if ( ! empty( $layout['verticalAlignment'] ) ) {
                    switch ( $layout['verticalAlignment'] ) {
                        case 'top':
                            $classes[] = 'is-vertically-aligned-top';
                            break;
                        case 'center':
                            $classes[] = 'is-vertically-aligned-center';
                            break;
                        case 'bottom':
                            $classes[] = 'is-vertically-aligned-bottom';
                            break;
                    }
                }

                // Handle flex wrap
                if ( ! empty( $layout['flexWrap'] ) && $layout['flexWrap'] === 'nowrap' ) {
                    $classes[] = 'is-nowrap';
                }
            }

            // Handle constrained layout
            if ( ! empty( $layout['type'] ) && $layout['type'] === 'constrained' ) {
                $classes[] = 'is-layout-constrained';
                $classes[] = 'wp-block-columns-is-layout-constrained';
            }
        }

        // Handle spacing attributes
        if ( ! empty( $attributes['spacing'] ) && is_array( $attributes['spacing'] ) ) {
            $spacing = $attributes['spacing'];

            // Handle margins
            if ( ! empty( $spacing['margin'] ) && is_array( $spacing['margin'] ) ) {
                foreach ( $spacing['margin'] as $side => $value ) {
                    if ( ! empty( $value ) ) {
                        $styles["margin-{$side}"] = $this->process_preset_value( $value );
                    }
                }
            }

            // Handle padding
            if ( ! empty( $spacing['padding'] ) && is_array( $spacing['padding'] ) ) {
                foreach ( $spacing['padding'] as $side => $value ) {
                    if ( ! empty( $value ) ) {
                        $styles["padding-{$side}"] = $this->process_preset_value( $value );
                    }
                }
            }

            // Handle block gap
            if ( isset( $spacing['blockGap'] ) ) {
                $styles['gap'] = $this->process_preset_value( $spacing['blockGap'] );
            }
        }

        // Handle border attributes
        if ( ! empty( $attributes['border'] ) && is_array( $attributes['border'] ) ) {
            $border = $attributes['border'];

            if ( ! empty( $border['radius'] ) ) {
                $styles['border-radius'] = $border['radius'];
            }
            if ( ! empty( $border['width'] ) ) {
                $styles['border-width'] = $border['width'];
            }
            if ( ! empty( $border['color'] ) ) {
                $styles['border-color'] = $this->process_preset_value( $border['color'] );
                $classes[] = 'has-border-color';
            }
        }

        // Handle dimensions attributes
        if ( ! empty( $attributes['dimensions'] ) && is_array( $attributes['dimensions'] ) ) {
            $dimensions = $attributes['dimensions'];

            if ( ! empty( $dimensions['minHeight'] ) ) {
                $styles['min-height'] = $this->process_preset_value( $dimensions['minHeight'] );
            }
            if ( ! empty( $dimensions['height'] ) ) {
                $styles['height'] = $this->process_preset_value( $dimensions['height'] );
            }
            if ( ! empty( $dimensions['maxHeight'] ) ) {
                $styles['max-height'] = $this->process_preset_value( $dimensions['maxHeight'] );
            }
            if ( ! empty( $dimensions['minWidth'] ) ) {
                $styles['min-width'] = $this->process_preset_value( $dimensions['minWidth'] );
            }
            if ( ! empty( $dimensions['width'] ) ) {
                $styles['width'] = $this->process_preset_value( $dimensions['width'] );
            }
            if ( ! empty( $dimensions['maxWidth'] ) ) {
                $styles['max-width'] = $this->process_preset_value( $dimensions['maxWidth'] );
            }
        }

        // Handle style attributes (WordPress block editor styles)
        if ( ! empty( $attributes['style'] ) && is_array( $attributes['style'] ) ) {
            $style_attr = $attributes['style'];

            // Handle border from style attribute
            if ( ! empty( $style_attr['border'] ) && is_array( $style_attr['border'] ) ) {
                $border = $style_attr['border'];

                if ( ! empty( $border['radius'] ) ) {
                    $styles['border-radius'] = $border['radius'];
                }
                if ( ! empty( $border['width'] ) ) {
                    $styles['border-width'] = $border['width'];
                }
                if ( ! empty( $border['color'] ) ) {
                    $styles['border-color'] = $this->process_preset_value( $border['color'] );
                    $classes[] = 'has-border-color';
                }
                // Check if we have individual border sides
                $has_individual_sides = false;
                if ( ( ! empty( $border['top'] ) && is_array( $border['top'] ) ) ||
                     ( ! empty( $border['bottom'] ) && is_array( $border['bottom'] ) ) ||
                     ( ! empty( $border['left'] ) && is_array( $border['left'] ) ) ||
                     ( ! empty( $border['right'] ) && is_array( $border['right'] ) ) ) {
                    $has_individual_sides = true;
                }

                // Only set general border-style if no individual sides are defined
                if ( ! $has_individual_sides && ! empty( $border['style'] ) ) {
                    $styles['border-style'] = $border['style'];
                }

                // Handle individual border sides
                if ( ! empty( $border['top'] ) && is_array( $border['top'] ) ) {
                    $top_border = $this->process_border_side( $border['top'] );
                    if ( ! empty( $top_border ) ) {
                        $styles['border-top'] = $top_border;
                    }
                }
                if ( ! empty( $border['bottom'] ) && is_array( $border['bottom'] ) ) {
                    $bottom_border = $this->process_border_side( $border['bottom'] );
                    if ( ! empty( $bottom_border ) ) {
                        $styles['border-bottom'] = $bottom_border;
                    }
                }
                if ( ! empty( $border['left'] ) && is_array( $border['left'] ) ) {
                    $left_border = $this->process_border_side( $border['left'] );
                    if ( ! empty( $left_border ) ) {
                        $styles['border-left'] = $left_border;
                    }
                }
                if ( ! empty( $border['right'] ) && is_array( $border['right'] ) ) {
                    $right_border = $this->process_border_side( $border['right'] );
                    if ( ! empty( $right_border ) ) {
                        $styles['border-right'] = $right_border;
                    }
                }
            }

            // Handle spacing from style attribute
            if ( ! empty( $style_attr['spacing'] ) && is_array( $style_attr['spacing'] ) ) {
                $spacing = $style_attr['spacing'];

                // Handle margins from style.spacing
                if ( ! empty( $spacing['margin'] ) && is_array( $spacing['margin'] ) ) {
                    foreach ( $spacing['margin'] as $side => $value ) {
                        if ( ! empty( $value ) ) {
                            $styles["margin-{$side}"] = $this->process_preset_value( $value );
                        }
                    }
                }

                // Handle padding from style.spacing
                if ( ! empty( $spacing['padding'] ) && is_array( $spacing['padding'] ) ) {
                    foreach ( $spacing['padding'] as $side => $value ) {
                        if ( ! empty( $value ) ) {
                            $styles["padding-{$side}"] = $this->process_preset_value( $value );
                        }
                    }
                }

                // Handle block gap from style.spacing
                if ( isset( $spacing['blockGap'] ) ) {
                    $styles['gap'] = $this->process_preset_value( $spacing['blockGap'] );
                }
            }

            // Handle dimensions from style attribute
            if ( ! empty( $style_attr['dimensions'] ) && is_array( $style_attr['dimensions'] ) ) {
                $dimensions = $style_attr['dimensions'];

                if ( ! empty( $dimensions['minHeight'] ) ) {
                    $styles['min-height'] = $this->process_preset_value( $dimensions['minHeight'] );
                }
                if ( ! empty( $dimensions['height'] ) ) {
                    $styles['height'] = $this->process_preset_value( $dimensions['height'] );
                }
                if ( ! empty( $dimensions['maxHeight'] ) ) {
                    $styles['max-height'] = $this->process_preset_value( $dimensions['maxHeight'] );
                }
                if ( ! empty( $dimensions['minWidth'] ) ) {
                    $styles['min-width'] = $this->process_preset_value( $dimensions['minWidth'] );
                }
                if ( ! empty( $dimensions['width'] ) ) {
                    $styles['width'] = $this->process_preset_value( $dimensions['width'] );
                }
                if ( ! empty( $dimensions['maxWidth'] ) ) {
                    $styles['max-width'] = $this->process_preset_value( $dimensions['maxWidth'] );
                }
            }
        }

        // Handle color attributes
        if ( ! empty( $attributes['textColor'] ) ) {
            $text_slug = sanitize_key( $attributes['textColor'] );
            $classes[] = 'has-text-color';
            $classes[] = 'has-' . $text_slug . '-color';
        }
        if ( ! empty( $attributes['backgroundColor'] ) ) {
            $bg_slug = sanitize_key( $attributes['backgroundColor'] );
            $classes[] = 'has-background';
            $classes[] = 'has-' . $bg_slug . '-background-color';
        }

        // Handle style.color structure
        if ( ! empty( $attributes['style']['color'] ) && is_array( $attributes['style']['color'] ) ) {
            $color_style = $attributes['style']['color'];
            if ( ! empty( $color_style['text'] ) ) {
                $styles['color'] = $this->process_preset_value( $color_style['text'] );
                $classes[] = 'has-text-color';
            }
            if ( ! empty( $color_style['background'] ) ) {
                $styles['background-color'] = $this->process_preset_value( $color_style['background'] );
                $classes[] = 'has-background';
            }
        }

        // Handle style.background for gradients
        if ( ! empty( $attributes['style']['background'] ) ) {
            $background_style = $attributes['style']['background'];
            if ( is_string( $background_style ) ) {
                // Direct gradient string
                $styles['background'] = $background_style;
                $classes[] = 'has-background';
            } elseif ( is_array( $background_style ) ) {
                // Handle gradient object structure
                if ( ! empty( $background_style['gradient'] ) ) {
                    $styles['background'] = $background_style['gradient'];
                    $classes[] = 'has-background';
                } elseif ( ! empty( $background_style['backgroundImage'] ) ) {
                    $styles['background-image'] = $background_style['backgroundImage'];
                    $classes[] = 'has-background';
                }
            }
        }

        // Handle style.color.gradient for gradients (WordPress core format)
        if ( ! empty( $attributes['style']['color']['gradient'] ) ) {
            $gradient = $attributes['style']['color']['gradient'];
            $styles['background'] = $gradient;
            $classes[] = 'has-background';

        }

        // Handle custom className
        if ( ! empty( $attributes['className'] ) ) {
            $classes[] = sanitize_html_class( $attributes['className'] );
        }

        // Build the attributes string
        $class_string = implode( ' ', array_filter( $classes ) );
        $style_string = '';

        if ( ! empty( $styles ) ) {
            $style_parts = [];
            foreach ( $styles as $property => $value ) {
                $style_parts[] = esc_attr( $property ) . ': ' . esc_attr( $value );
            }
            $style_string = ' style="' . implode( '; ', $style_parts ) . '"';
        }

        $result = 'class="' . esc_attr( $class_string ) . '"' . $style_string;


        return $result;
    }

    /**
     * Build wrapper attributes for core/column blocks
     *
     * @since 4.2.0
     *
     * @param array $attributes Block attributes.
     * @return string Wrapper attributes string.
     */
    private function build_column_block_wrapper_attributes( $attributes ) {
        $classes = [ 'wp-block-column' ];
        $styles = [];


        // Handle width attribute (specific to columns)
        if ( ! empty( $attributes['width'] ) ) {
            $width = $attributes['width'];
            $styles['flex-basis'] = $width;

            // Also add as a CSS custom property for potential use
            $styles['--wp--custom--column-width'] = $width;
        }

        // Handle color attributes
        if ( ! empty( $attributes['textColor'] ) ) {
            $text_slug = sanitize_key( $attributes['textColor'] );
            $classes[] = 'has-text-color';
            $classes[] = 'has-' . $text_slug . '-color';
        }
        if ( ! empty( $attributes['backgroundColor'] ) ) {
            $bg_slug = sanitize_key( $attributes['backgroundColor'] );
            $classes[] = 'has-background';
            $classes[] = 'has-' . $bg_slug . '-background-color';
        }

        // Handle style.color structure
        if ( ! empty( $attributes['style']['color'] ) && is_array( $attributes['style']['color'] ) ) {
            $color_style = $attributes['style']['color'];
            if ( ! empty( $color_style['text'] ) ) {
                $styles['color'] = $this->process_preset_value( $color_style['text'] );
                $classes[] = 'has-text-color';
            }
            if ( ! empty( $color_style['background'] ) ) {
                $styles['background-color'] = $this->process_preset_value( $color_style['background'] );
                $classes[] = 'has-background';
            }
        }

        // Handle style.background for gradients
        if ( ! empty( $attributes['style']['background'] ) ) {
            $background_style = $attributes['style']['background'];


            if ( is_string( $background_style ) ) {
                // Direct gradient string
                $styles['background'] = $background_style;
                $classes[] = 'has-background';

            } elseif ( is_array( $background_style ) ) {
                // Handle gradient object structure
                if ( ! empty( $background_style['gradient'] ) ) {
                    $styles['background'] = $background_style['gradient'];
                    $classes[] = 'has-background';

                } elseif ( ! empty( $background_style['backgroundImage'] ) ) {
                    $styles['background-image'] = $background_style['backgroundImage'];
                    $classes[] = 'has-background';

                }
            }
        }

        // Handle style.color.gradient for gradients (WordPress core format)
        if ( ! empty( $attributes['style']['color']['gradient'] ) ) {
            $gradient = $attributes['style']['color']['gradient'];
            $styles['background'] = $gradient;
            $classes[] = 'has-background';

        }

        // Handle vertical alignment (specific to columns)
        if ( ! empty( $attributes['verticalAlignment'] ) ) {
            switch ( $attributes['verticalAlignment'] ) {
                case 'top':
                    $classes[] = 'is-vertically-aligned-top';
                    break;
                case 'center':
                    $classes[] = 'is-vertically-aligned-center';
                    break;
                case 'bottom':
                    $classes[] = 'is-vertically-aligned-bottom';
                    break;
            }
        }

        // Handle layout attributes
        if ( ! empty( $attributes['layout'] ) && is_array( $attributes['layout'] ) ) {
            $layout = $attributes['layout'];

            // Handle flex layout
            if ( ! empty( $layout['type'] ) && $layout['type'] === 'flex' ) {
                $classes[] = 'is-layout-flex';
                $classes[] = 'wp-block-column-is-layout-flex';

                // Handle orientation
                if ( ! empty( $layout['orientation'] ) ) {
                    if ( $layout['orientation'] === 'vertical' ) {
                        $classes[] = 'is-vertical';
                    } elseif ( $layout['orientation'] === 'horizontal' ) {
                        $classes[] = 'is-horizontal';
                    }
                }

                // Handle justification (alignment)
                if ( ! empty( $layout['justifyContent'] ) ) {
                    switch ( $layout['justifyContent'] ) {
                        case 'left':
                            $classes[] = 'is-content-justification-left';
                            break;
                        case 'center':
                            $classes[] = 'is-content-justification-center';
                            break;
                        case 'right':
                            $classes[] = 'is-content-justification-right';
                            break;
                        case 'space-between':
                            $classes[] = 'is-content-justification-space-between';
                            break;
                    }
                }

                // Handle vertical alignment
                if ( ! empty( $layout['verticalAlignment'] ) ) {
                    switch ( $layout['verticalAlignment'] ) {
                        case 'top':
                            $classes[] = 'is-vertically-aligned-top';
                            break;
                        case 'center':
                            $classes[] = 'is-vertically-aligned-center';
                            break;
                        case 'bottom':
                            $classes[] = 'is-vertically-aligned-bottom';
                            break;
                    }
                }

                // Handle flex wrap
                if ( ! empty( $layout['flexWrap'] ) && $layout['flexWrap'] === 'nowrap' ) {
                    $classes[] = 'is-nowrap';
                }
            }

            // Handle constrained layout
            if ( ! empty( $layout['type'] ) && $layout['type'] === 'constrained' ) {
                $classes[] = 'is-layout-constrained';
                $classes[] = 'wp-block-column-is-layout-constrained';
            }
        }

        // Handle spacing attributes
        if ( ! empty( $attributes['spacing'] ) && is_array( $attributes['spacing'] ) ) {
            $spacing = $attributes['spacing'];

            // Handle margins
            if ( ! empty( $spacing['margin'] ) && is_array( $spacing['margin'] ) ) {
                foreach ( $spacing['margin'] as $side => $value ) {
                    if ( ! empty( $value ) ) {
                        $styles["margin-{$side}"] = $this->process_preset_value( $value );
                    }
                }
            }

            // Handle padding
            if ( ! empty( $spacing['padding'] ) && is_array( $spacing['padding'] ) ) {
                foreach ( $spacing['padding'] as $side => $value ) {
                    if ( ! empty( $value ) ) {
                        $styles["padding-{$side}"] = $this->process_preset_value( $value );
                    }
                }
            }

            // Handle block gap
            if ( isset( $spacing['blockGap'] ) ) {
                $styles['gap'] = $this->process_preset_value( $spacing['blockGap'] );
            }
        }

        // Handle border attributes
        if ( ! empty( $attributes['border'] ) && is_array( $attributes['border'] ) ) {
            $border = $attributes['border'];

            if ( ! empty( $border['radius'] ) ) {
                $styles['border-radius'] = $border['radius'];
            }
            if ( ! empty( $border['width'] ) ) {
                $styles['border-width'] = $border['width'];
            }
            if ( ! empty( $border['color'] ) ) {
                $styles['border-color'] = $this->process_preset_value( $border['color'] );
                $classes[] = 'has-border-color';
            }
        }

        // Handle dimensions attributes
        if ( ! empty( $attributes['dimensions'] ) && is_array( $attributes['dimensions'] ) ) {
            $dimensions = $attributes['dimensions'];

            if ( ! empty( $dimensions['minHeight'] ) ) {
                $styles['min-height'] = $this->process_preset_value( $dimensions['minHeight'] );
            }
            if ( ! empty( $dimensions['height'] ) ) {
                $styles['height'] = $this->process_preset_value( $dimensions['height'] );
            }
            if ( ! empty( $dimensions['maxHeight'] ) ) {
                $styles['max-height'] = $this->process_preset_value( $dimensions['maxHeight'] );
            }
            if ( ! empty( $dimensions['minWidth'] ) ) {
                $styles['min-width'] = $this->process_preset_value( $dimensions['minWidth'] );
            }
            if ( ! empty( $dimensions['width'] ) ) {
                $styles['width'] = $this->process_preset_value( $dimensions['width'] );
            }
            if ( ! empty( $dimensions['maxWidth'] ) ) {
                $styles['max-width'] = $this->process_preset_value( $dimensions['maxWidth'] );
            }
        }

        // Handle style attributes (WordPress block editor styles)
        if ( ! empty( $attributes['style'] ) && is_array( $attributes['style'] ) ) {
            $style_attr = $attributes['style'];

            // Handle border from style attribute
            if ( ! empty( $style_attr['border'] ) && is_array( $style_attr['border'] ) ) {
                $border = $style_attr['border'];

                if ( ! empty( $border['radius'] ) ) {
                    $styles['border-radius'] = $border['radius'];
                }
                if ( ! empty( $border['width'] ) ) {
                    $styles['border-width'] = $border['width'];
                }
                if ( ! empty( $border['color'] ) ) {
                    $styles['border-color'] = $this->process_preset_value( $border['color'] );
                    $classes[] = 'has-border-color';
                }
                // Check if we have individual border sides
                $has_individual_sides = false;
                if ( ( ! empty( $border['top'] ) && is_array( $border['top'] ) ) ||
                     ( ! empty( $border['bottom'] ) && is_array( $border['bottom'] ) ) ||
                     ( ! empty( $border['left'] ) && is_array( $border['left'] ) ) ||
                     ( ! empty( $border['right'] ) && is_array( $border['right'] ) ) ) {
                    $has_individual_sides = true;
                }

                // Only set general border-style if no individual sides are defined
                if ( ! $has_individual_sides && ! empty( $border['style'] ) ) {
                    $styles['border-style'] = $border['style'];
                }

                // Handle individual border sides
                if ( ! empty( $border['top'] ) && is_array( $border['top'] ) ) {
                    $top_border = $this->process_border_side( $border['top'] );
                    if ( ! empty( $top_border ) ) {
                        $styles['border-top'] = $top_border;
                    }
                }
                if ( ! empty( $border['bottom'] ) && is_array( $border['bottom'] ) ) {
                    $bottom_border = $this->process_border_side( $border['bottom'] );
                    if ( ! empty( $bottom_border ) ) {
                        $styles['border-bottom'] = $bottom_border;
                    }
                }
                if ( ! empty( $border['left'] ) && is_array( $border['left'] ) ) {
                    $left_border = $this->process_border_side( $border['left'] );
                    if ( ! empty( $left_border ) ) {
                        $styles['border-left'] = $left_border;
                    }
                }
                if ( ! empty( $border['right'] ) && is_array( $border['right'] ) ) {
                    $right_border = $this->process_border_side( $border['right'] );
                    if ( ! empty( $right_border ) ) {
                        $styles['border-right'] = $right_border;
                    }
                }
            }

            // Handle spacing from style attribute
            if ( ! empty( $style_attr['spacing'] ) && is_array( $style_attr['spacing'] ) ) {
                $spacing = $style_attr['spacing'];

                // Handle margins from style.spacing
                if ( ! empty( $spacing['margin'] ) && is_array( $spacing['margin'] ) ) {
                    foreach ( $spacing['margin'] as $side => $value ) {
                        if ( ! empty( $value ) ) {
                            $styles["margin-{$side}"] = $this->process_preset_value( $value );
                        }
                    }
                }

                // Handle padding from style.spacing
                if ( ! empty( $spacing['padding'] ) && is_array( $spacing['padding'] ) ) {
                    foreach ( $spacing['padding'] as $side => $value ) {
                        if ( ! empty( $value ) ) {
                            $styles["padding-{$side}"] = $this->process_preset_value( $value );
                        }
                    }
                }

                // Handle block gap from style.spacing
                if ( isset( $spacing['blockGap'] ) ) {
                    $styles['gap'] = $this->process_preset_value( $spacing['blockGap'] );
                }
            }

            // Handle dimensions from style attribute
            if ( ! empty( $style_attr['dimensions'] ) && is_array( $style_attr['dimensions'] ) ) {
                $dimensions = $style_attr['dimensions'];

                if ( ! empty( $dimensions['minHeight'] ) ) {
                    $styles['min-height'] = $this->process_preset_value( $dimensions['minHeight'] );
                }
                if ( ! empty( $dimensions['height'] ) ) {
                    $styles['height'] = $this->process_preset_value( $dimensions['height'] );
                }
                if ( ! empty( $dimensions['maxHeight'] ) ) {
                    $styles['max-height'] = $this->process_preset_value( $dimensions['maxHeight'] );
                }
                if ( ! empty( $dimensions['minWidth'] ) ) {
                    $styles['min-width'] = $this->process_preset_value( $dimensions['minWidth'] );
                }
                if ( ! empty( $dimensions['width'] ) ) {
                    $styles['width'] = $this->process_preset_value( $dimensions['width'] );
                }
                if ( ! empty( $dimensions['maxWidth'] ) ) {
                    $styles['max-width'] = $this->process_preset_value( $dimensions['maxWidth'] );
                }
            }
        }

        // Handle custom className
        if ( ! empty( $attributes['className'] ) ) {
            $classes[] = sanitize_html_class( $attributes['className'] );
        }

        // Build the attributes string
        $class_string = implode( ' ', array_filter( $classes ) );
        $style_string = '';

        if ( ! empty( $styles ) ) {
            $style_parts = [];
            foreach ( $styles as $property => $value ) {
                $style_parts[] = esc_attr( $property ) . ': ' . esc_attr( $value );
            }
            $style_string = ' style="' . implode( '; ', $style_parts ) . '"';
        }

        $result = 'class="' . esc_attr( $class_string ) . '"' . $style_string;


        return $result;
    }

    /**
     * Build wrapper attributes for wpuf-ud/profile blocks
     *
     * @since 4.2.0
     *
     * @param array $attributes Block attributes.
     * @return string Wrapper attributes string.
     */
    private function build_profile_block_wrapper_attributes( $attributes ) {
        $classes = [ 'wpuf-user-profile' ];
        $styles = [];

        // Handle color attributes
        if ( ! empty( $attributes['textColor'] ) ) {
            $text_slug = sanitize_key( $attributes['textColor'] );
            $classes[] = 'has-text-color';
            $classes[] = 'has-' . $text_slug . '-color';
        }
        if ( ! empty( $attributes['backgroundColor'] ) ) {
            $bg_slug = sanitize_key( $attributes['backgroundColor'] );
            $classes[] = 'has-background';
            $classes[] = 'has-' . $bg_slug . '-background-color';
        }

        // Handle style.color structure
        if ( ! empty( $attributes['style']['color'] ) && is_array( $attributes['style']['color'] ) ) {
            $color_style = $attributes['style']['color'];
            if ( ! empty( $color_style['text'] ) ) {
                $styles['color'] = $this->process_preset_value( $color_style['text'] );
                $classes[] = 'has-text-color';
            }
            if ( ! empty( $color_style['background'] ) ) {
                $styles['background-color'] = $this->process_preset_value( $color_style['background'] );
                $classes[] = 'has-background';
            }
        }

        // Handle layout attributes
        if ( ! empty( $attributes['layout'] ) && is_array( $attributes['layout'] ) ) {
            $layout = $attributes['layout'];

            // Handle flex layout
            if ( ! empty( $layout['type'] ) && $layout['type'] === 'flex' ) {
                $classes[] = 'is-layout-flex';
                $classes[] = 'wpuf-user-profile-is-layout-flex';

                // Handle orientation
                if ( ! empty( $layout['orientation'] ) ) {
                    if ( $layout['orientation'] === 'vertical' ) {
                        $classes[] = 'is-vertical';
                    } elseif ( $layout['orientation'] === 'horizontal' ) {
                        $classes[] = 'is-horizontal';
                    }
                }

                // Handle justification (alignment)
                if ( ! empty( $layout['justifyContent'] ) ) {
                    switch ( $layout['justifyContent'] ) {
                        case 'left':
                            $classes[] = 'is-content-justification-left';
                            break;
                        case 'center':
                            $classes[] = 'is-content-justification-center';
                            break;
                        case 'right':
                            $classes[] = 'is-content-justification-right';
                            break;
                        case 'space-between':
                            $classes[] = 'is-content-justification-space-between';
                            break;
                    }
                }

                // Handle vertical alignment
                if ( ! empty( $layout['verticalAlignment'] ) ) {
                    switch ( $layout['verticalAlignment'] ) {
                        case 'top':
                            $classes[] = 'is-vertically-aligned-top';
                            break;
                        case 'center':
                            $classes[] = 'is-vertically-aligned-center';
                            break;
                        case 'bottom':
                            $classes[] = 'is-vertically-aligned-bottom';
                            break;
                    }
                }

                // Handle flex wrap
                if ( ! empty( $layout['flexWrap'] ) && $layout['flexWrap'] === 'nowrap' ) {
                    $classes[] = 'is-nowrap';
                }
            }

            // Handle constrained layout
            if ( ! empty( $layout['type'] ) && $layout['type'] === 'constrained' ) {
                $classes[] = 'is-layout-constrained';
                $classes[] = 'wpuf-user-profile-is-layout-constrained';
            }
        }

        // Handle spacing attributes
        if ( ! empty( $attributes['spacing'] ) && is_array( $attributes['spacing'] ) ) {
            $spacing = $attributes['spacing'];

            // Handle margins
            if ( ! empty( $spacing['margin'] ) && is_array( $spacing['margin'] ) ) {
                foreach ( $spacing['margin'] as $side => $value ) {
                    if ( ! empty( $value ) ) {
                        $styles["margin-{$side}"] = $this->process_preset_value( $value );
                    }
                }
            }

            // Handle padding
            if ( ! empty( $spacing['padding'] ) && is_array( $spacing['padding'] ) ) {
                foreach ( $spacing['padding'] as $side => $value ) {
                    if ( ! empty( $value ) ) {
                        $styles["padding-{$side}"] = $this->process_preset_value( $value );
                    }
                }
            }

            // Handle block gap
            if ( isset( $spacing['blockGap'] ) ) {
                $styles['gap'] = $this->process_preset_value( $spacing['blockGap'] );
            }
        }

        // Handle border attributes
        if ( ! empty( $attributes['border'] ) && is_array( $attributes['border'] ) ) {
            $border = $attributes['border'];

            if ( ! empty( $border['radius'] ) ) {
                $styles['border-radius'] = $border['radius'];
            }
            if ( ! empty( $border['width'] ) ) {
                $styles['border-width'] = $border['width'];
            }
            if ( ! empty( $border['color'] ) ) {
                $styles['border-color'] = $this->process_preset_value( $border['color'] );
                $classes[] = 'has-border-color';
            }
        }

        // Handle dimensions attributes
        if ( ! empty( $attributes['dimensions'] ) && is_array( $attributes['dimensions'] ) ) {
            $dimensions = $attributes['dimensions'];

            if ( ! empty( $dimensions['minHeight'] ) ) {
                $styles['min-height'] = $this->process_preset_value( $dimensions['minHeight'] );
            }
            if ( ! empty( $dimensions['height'] ) ) {
                $styles['height'] = $this->process_preset_value( $dimensions['height'] );
            }
            if ( ! empty( $dimensions['maxHeight'] ) ) {
                $styles['max-height'] = $this->process_preset_value( $dimensions['maxHeight'] );
            }
            if ( ! empty( $dimensions['minWidth'] ) ) {
                $styles['min-width'] = $this->process_preset_value( $dimensions['minWidth'] );
            }
            if ( ! empty( $dimensions['width'] ) ) {
                $styles['width'] = $this->process_preset_value( $dimensions['width'] );
            }
            if ( ! empty( $dimensions['maxWidth'] ) ) {
                $styles['max-width'] = $this->process_preset_value( $dimensions['maxWidth'] );
            }
        }

        // Handle style attributes (WordPress block editor styles)
        if ( ! empty( $attributes['style'] ) && is_array( $attributes['style'] ) ) {
            $style_attr = $attributes['style'];

            // Handle border from style attribute
            if ( ! empty( $style_attr['border'] ) && is_array( $style_attr['border'] ) ) {
                $border = $style_attr['border'];

                if ( ! empty( $border['radius'] ) ) {
                    $styles['border-radius'] = $border['radius'];
                }
                if ( ! empty( $border['width'] ) ) {
                    $styles['border-width'] = $border['width'];
                }
                if ( ! empty( $border['color'] ) ) {
                    $styles['border-color'] = $this->process_preset_value( $border['color'] );
                    $classes[] = 'has-border-color';
                }
                // Check if we have individual border sides
                $has_individual_sides = false;
                if ( ( ! empty( $border['top'] ) && is_array( $border['top'] ) ) ||
                     ( ! empty( $border['bottom'] ) && is_array( $border['bottom'] ) ) ||
                     ( ! empty( $border['left'] ) && is_array( $border['left'] ) ) ||
                     ( ! empty( $border['right'] ) && is_array( $border['right'] ) ) ) {
                    $has_individual_sides = true;
                }

                // Only set general border-style if no individual sides are defined
                if ( ! $has_individual_sides && ! empty( $border['style'] ) ) {
                    $styles['border-style'] = $border['style'];
                }

                // Handle individual border sides
                if ( ! empty( $border['top'] ) && is_array( $border['top'] ) ) {
                    $top_border = $this->process_border_side( $border['top'] );
                    if ( ! empty( $top_border ) ) {
                        $styles['border-top'] = $top_border;
                    }
                }
                if ( ! empty( $border['bottom'] ) && is_array( $border['bottom'] ) ) {
                    $bottom_border = $this->process_border_side( $border['bottom'] );
                    if ( ! empty( $bottom_border ) ) {
                        $styles['border-bottom'] = $bottom_border;
                    }
                }
                if ( ! empty( $border['left'] ) && is_array( $border['left'] ) ) {
                    $left_border = $this->process_border_side( $border['left'] );
                    if ( ! empty( $left_border ) ) {
                        $styles['border-left'] = $left_border;
                    }
                }
                if ( ! empty( $border['right'] ) && is_array( $border['right'] ) ) {
                    $right_border = $this->process_border_side( $border['right'] );
                    if ( ! empty( $right_border ) ) {
                        $styles['border-right'] = $right_border;
                    }
                }
            }

            // Handle spacing from style attribute
            if ( ! empty( $style_attr['spacing'] ) && is_array( $style_attr['spacing'] ) ) {
                $spacing = $style_attr['spacing'];

                // Handle margins from style.spacing
                if ( ! empty( $spacing['margin'] ) && is_array( $spacing['margin'] ) ) {
                    foreach ( $spacing['margin'] as $side => $value ) {
                        if ( ! empty( $value ) ) {
                            $styles["margin-{$side}"] = $this->process_preset_value( $value );
                        }
                    }
                }

                // Handle padding from style.spacing
                if ( ! empty( $spacing['padding'] ) && is_array( $spacing['padding'] ) ) {
                    foreach ( $spacing['padding'] as $side => $value ) {
                        if ( ! empty( $value ) ) {
                            $styles["padding-{$side}"] = $this->process_preset_value( $value );
                        }
                    }
                }

                // Handle block gap from style.spacing
                if ( isset( $spacing['blockGap'] ) ) {
                    $styles['gap'] = $this->process_preset_value( $spacing['blockGap'] );
                }
            }

            // Handle dimensions from style attribute
            if ( ! empty( $style_attr['dimensions'] ) && is_array( $style_attr['dimensions'] ) ) {
                $dimensions = $style_attr['dimensions'];

                if ( ! empty( $dimensions['minHeight'] ) ) {
                    $styles['min-height'] = $this->process_preset_value( $dimensions['minHeight'] );
                }
                if ( ! empty( $dimensions['height'] ) ) {
                    $styles['height'] = $this->process_preset_value( $dimensions['height'] );
                }
                if ( ! empty( $dimensions['maxHeight'] ) ) {
                    $styles['max-height'] = $this->process_preset_value( $dimensions['maxHeight'] );
                }
                if ( ! empty( $dimensions['minWidth'] ) ) {
                    $styles['min-width'] = $this->process_preset_value( $dimensions['minWidth'] );
                }
                if ( ! empty( $dimensions['width'] ) ) {
                    $styles['width'] = $this->process_preset_value( $dimensions['width'] );
                }
                if ( ! empty( $dimensions['maxWidth'] ) ) {
                    $styles['max-width'] = $this->process_preset_value( $dimensions['maxWidth'] );
                }
            }
        }

        // Handle custom className
        if ( ! empty( $attributes['className'] ) ) {
            $classes[] = sanitize_html_class( $attributes['className'] );
        }

        // Build the attributes string
        $class_string = implode( ' ', array_filter( $classes ) );
        $style_string = '';

        if ( ! empty( $styles ) ) {
            $style_parts = [];
            foreach ( $styles as $property => $value ) {
                $style_parts[] = esc_attr( $property ) . ': ' . esc_attr( $value );
            }
            $style_string = ' style="' . implode( '; ', $style_parts ) . '"';
        }

        return 'class="' . esc_attr( $class_string ) . '"' . $style_string;
    }

    /**
     * Process individual border side values
     *
     * @since 4.2.0
     *
     * @param array $border_side Border side configuration
     * @return string Processed border side CSS
     */
    private function process_border_side( $border_side ) {
        if ( empty( $border_side ) || ! is_array( $border_side ) ) {
            return '';
        }

        $border_parts = [];

        // Handle width
        if ( isset( $border_side['width'] ) && ! empty( $border_side['width'] ) ) {
            $border_parts[] = esc_attr( $border_side['width'] );
        }

        // Handle style
        if ( isset( $border_side['style'] ) && ! empty( $border_side['style'] ) ) {
            $border_parts[] = esc_attr( $border_side['style'] );
        }

        // Handle color
        if ( isset( $border_side['color'] ) && ! empty( $border_side['color'] ) ) {
            $border_parts[] = $this->process_preset_value( $border_side['color'] );
        }

        return implode( ' ', $border_parts );
    }

    /**
     * Process WordPress preset values and convert them to CSS custom properties
     *
     * @since 4.2.0
     *
     * @param string $value The value to process.
     * @return string The processed value.
     */
    private function process_preset_value( $value ) {
        // Handle spacing presets
        if ( strpos( $value, 'var:preset|spacing|' ) === 0 ) {
            $preset_slug = str_replace( 'var:preset|spacing|', '', $value );
            return "var(--wp--preset--spacing--{$preset_slug})";
        }

        // Handle size presets
        if ( strpos( $value, 'var:preset|size|' ) === 0 ) {
            $preset_slug = str_replace( 'var:preset|size|', '', $value );
            return "var(--wp--preset--size--{$preset_slug})";
        }

        // Handle color presets
        if ( strpos( $value, 'var:preset|color|' ) === 0 ) {
            $preset_slug = str_replace( 'var:preset|color|', '', $value );
            return "var(--wp--preset--color--{$preset_slug})";
        }

        // Handle typography presets
        if ( strpos( $value, 'var:preset|typography|' ) === 0 ) {
            $preset_slug = str_replace( 'var:preset|typography|', '', $value );
            return "var(--wp--preset--typography--{$preset_slug})";
        }

        // Return the original value if it's not a preset
        return $value;
    }

    /**
     * Render search field for block context
     *
     * @since 4.2.0
     *
     * @param array  $all_data Block data and attributes.
     * @param string $context  Rendering context ('block' or 'shortcode').
     *
     * @return string
     */
    public function render_search_field( $all_data, $context = 'block' ) {
        // Extract search-related attributes
        $enable_search      = $all_data['enable_search'] ?? true;
        $search_placeholder = $all_data['search_placeholder'] ?? __( 'Search Users', 'wpuf-pro' );
        $searchable_fields  = $all_data['searchable_fields'] ?? ['user_login', 'user_email', 'display_name'];
        $block_id           = $all_data['blockId'] ?? $all_data['anchor'] ?? 'wpuf-directory-' . uniqid();
        $page_id            = $all_data['pageId'] ?? get_the_ID();

        // Don't render if search is disabled
        if ( ! $enable_search ) {
            return '';
        }

        // Convert searchable_fields to JSON for data attribute
        $searchable_fields_json = is_array( $searchable_fields ) ? wp_json_encode( $searchable_fields ) : $searchable_fields;

        // Start output buffering
        ob_start();

        // Block-specific search field rendering
        if ( $context === 'block' ) {
            ?>
            <div class="wpuf-user-directory-search">
                <div class="wpuf-flex wpuf-items-center wpuf-gap-3">
                    <!-- Search Input -->
                    <div
                        class="wpuf-flex wpuf-items-center wpuf-bg-white wpuf-border wpuf-border-gray-300 wpuf-rounded-sm wpuf-px-3 wpuf-ud-search-wrapper"
                        data-block-id="<?php echo esc_attr( $block_id ); ?>"
                        data-page-id="<?php echo esc_attr( $page_id ); ?>"
                        data-searchable-fields="<?php echo esc_attr( $searchable_fields_json ); ?>">
                        <svg class="wpuf-w-4 wpuf-h-4 wpuf-text-gray-400" fill="none" stroke="currentColor" stroke-width="2"
                             viewBox="0 0 24 24" aria-hidden="true">
                            <path stroke-linecap="round" stroke-linejoin="round"
                                  d="M21 21l-4.35-4.35m0 0A7.5 7.5 0 104.5 4.5a7.5 7.5 0 0012.15 12.15z"/>
                        </svg>
                        <input
                            type="text"
                            id="wpuf-search-<?php echo esc_attr( $block_id ); ?>"
                            class="wpuf-ud-search-input wpuf-ml-2 wpuf-bg-transparent wpuf-border-0 wpuf-w-full wpuf-text-sm wpuf-text-gray-900 wpuf-placeholder-gray-400 focus:!wpuf-outline-none focus:!wpuf-ring-0 focus:!wpuf-ring-offset-0"
                            placeholder="<?php echo esc_attr( $search_placeholder ); ?>"
                            autocomplete="off"
                            aria-label="<?php esc_attr_e( 'Search users', 'wpuf-pro' ); ?>"
                        />
                    </div>

                    <!-- Search In Dropdown -->
                    <div class="wpuf-relative">
                        <select
                            id="wpuf-search-in-<?php echo esc_attr( $block_id ); ?>"
                            class="wpuf-ud-search-in wpuf-bg-white wpuf-border wpuf-border-gray-300 wpuf-rounded-sm wpuf-px-3 wpuf-py-2 wpuf-text-sm wpuf-text-gray-900 focus:wpuf-outline-none focus:wpuf-ring-2 focus:wpuf-ring-indigo-500 focus:wpuf-border-indigo-500"
                            aria-label="<?php esc_attr_e( 'Search in field', 'wpuf-pro' ); ?>">
                            <option value=""><?php esc_html_e( 'Search In', 'wpuf-pro' ); ?></option>
                            <?php
                            // Get all available searchable fields for labels
                            $all_searchable_fields = $this->get_searchable_fields();
                            $all_fields_map = array();
                            foreach ( $all_searchable_fields as $field ) {
                                $all_fields_map[ $field['value'] ] = $field['label'];
                            }

                            // Only show the selected searchable fields in the dropdown
                            foreach ( $searchable_fields as $field_value ) {
                                $field_label = isset( $all_fields_map[ $field_value ] ) ? $all_fields_map[ $field_value ] : $field_value;
                                echo '<option value="' . esc_attr( $field_value ) . '">' . esc_html( $field_label ) . '</option>';
                            }
                            ?>
                        </select>
                    </div>
                </div>
            </div>
            <?php
        } else {
            // Shortcode context - use shortcode-specific template
            ?>
            <div class="wpuf-user-directory-search">
                <div class="wpuf-flex wpuf-items-center wpuf-gap-3">
                    <!-- Search Input -->
                    <div
                        class="wpuf-flex wpuf-items-center wpuf-bg-white wpuf-border wpuf-border-gray-300 wpuf-rounded-sm wpuf-px-3 wpuf-ud-search-wrapper"
                        data-block-id="<?php echo esc_attr( $block_id ); ?>"
                        data-page-id="<?php echo esc_attr( $page_id ); ?>"
                        data-searchable-fields="<?php echo esc_attr( $searchable_fields_json ); ?>">
                        <svg class="wpuf-w-4 wpuf-h-4 wpuf-text-gray-400" fill="none" stroke="currentColor" stroke-width="2"
                             viewBox="0 0 24 24" aria-hidden="true">
                            <path stroke-linecap="round" stroke-linejoin="round"
                                  d="M21 21l-4.35-4.35m0 0A7.5 7.5 0 104.5 4.5a7.5 7.5 0 0012.15 12.15z"/>
                        </svg>
                        <input
                            type="text"
                            id="wpuf-search-<?php echo esc_attr( $block_id ); ?>"
                            class="wpuf-ud-search-input wpuf-ml-2 wpuf-bg-transparent wpuf-border-0 wpuf-w-full wpuf-text-sm wpuf-text-gray-900 wpuf-placeholder-gray-400 focus:wpuf-outline-none"
                            placeholder="<?php echo esc_attr( $search_placeholder ); ?>"
                            autocomplete="off"
                            aria-label="<?php esc_attr_e( 'Search users', 'wpuf-pro' ); ?>"
                        />
                    </div>

                    <!-- Search In Dropdown -->
                    <div class="wpuf-relative">
                        <select
                            id="wpuf-search-in-<?php echo esc_attr( $block_id ); ?>"
                            class="wpuf-ud-search-in wpuf-bg-white wpuf-border wpuf-border-gray-300 wpuf-rounded-sm wpuf-px-3 wpuf-py-2 wpuf-text-sm wpuf-text-gray-900 focus:wpuf-outline-none focus:wpuf-ring-2 focus:wpuf-ring-indigo-500 focus:wpuf-border-indigo-500"
                            aria-label="<?php esc_attr_e( 'Search in field', 'wpuf-pro' ); ?>">
                            <option value=""><?php esc_html_e( 'Search In', 'wpuf-pro' ); ?></option>
                            <?php
                            // Get all available searchable fields for labels
                            $all_searchable_fields = $this->get_searchable_fields();
                            $all_fields_map = array();
                            foreach ( $all_searchable_fields as $field ) {
                                $all_fields_map[ $field['value'] ] = $field['label'];
                            }

                            // Only show the selected searchable fields in the dropdown
                            foreach ( $searchable_fields as $field_value ) {
                                $field_label = isset( $all_fields_map[ $field_value ] ) ? $all_fields_map[ $field_value ] : $field_value;
                                echo '<option value="' . esc_attr( $field_value ) . '">' . esc_html( $field_label ) . '</option>';
                            }
                            ?>
                        </select>
                    </div>
                </div>
            </div>
            <?php
        }

        // Return the buffered content
        return ob_get_clean();
    }

    /**
     * Render frontend sorting controls for user directory
     *
     * @since 4.2.0
     *
     * @param array $all_data Block attributes and data.
     * @param string $context Rendering context ('block' or 'shortcode').
     */
    public function render_sorting_controls( $all_data, $context = 'block' ) {
        // Extract sorting-related attributes
        $enable_frontend_sorting = $all_data['enable_frontend_sorting'] ?? false;
        $orderby                 = $all_data['orderby'] ?? 'id';
        $order                   = $all_data['order'] ?? 'desc';
        $available_sort_options  = $all_data['available_sort_options'] ?? ['id', 'user_login', 'user_email', 'display_name', 'user_registered'];
        $block_id                = $all_data['blockId'] ?? $all_data['anchor'] ?? 'wpuf-directory-' . uniqid();
        $page_id                 = $all_data['pageId'] ?? get_the_ID();

        // Don't render if frontend sorting is disabled
        if ( ! $enable_frontend_sorting ) {
            return '';
        }

        // Start output buffering
        ob_start();

        // Block-specific sorting controls rendering
        if ( $context === 'block' ) {
            ?>
            <div class="wpuf-user-directory-sorting">
                <div class="wpuf-flex wpuf-gap-4 wpuf-items-center">
                    <!-- Sort By Dropdown -->
                    <div class="wpuf-flex wpuf-items-center wpuf-gap-2">
                        <label for="wpuf-sort-by-<?php echo esc_attr( $block_id ); ?>" class="wpuf-text-sm wpuf-font-medium wpuf-text-gray-700">
                            <?php esc_html_e( 'Sort by:', 'wpuf-pro' ); ?>
                        </label>
                        <select
                            id="wpuf-sort-by-<?php echo esc_attr( $block_id ); ?>"
                            class="wpuf-ud-sort-by wpuf-px-3 wpuf-py-2 wpuf-bg-white wpuf-border wpuf-border-gray-300 wpuf-rounded-sm wpuf-text-sm focus:wpuf-outline-none"
                            data-block-id="<?php echo esc_attr( $block_id ); ?>"
                            data-page-id="<?php echo esc_attr( $page_id ); ?>"
                        >
                            <?php
                            // Ensure available_sort_options is an array
                            if ( ! is_array( $available_sort_options ) ) {
                                $available_sort_options = ['id', 'user_login', 'user_email', 'display_name', 'user_registered'];
                            }

                            // Only show the available sort options in the dropdown
                            foreach ( $available_sort_options as $field_value ) {
                                $field_value = trim( $field_value );
                                $field_label = $this->get_human_readable_field_label( $field_value );
                                $selected = ( $field_value === $orderby ) ? 'selected' : '';
                                echo '<option value="' . esc_attr( $field_value ) . '" ' . $selected . '>' . esc_html( $field_label ) . '</option>';
                            }
                            ?>
                        </select>
                    </div>

                    <!-- Sort Order Dropdown -->
                    <div class="wpuf-flex wpuf-items-center wpuf-gap-2">
                        <label for="wpuf-sort-order-<?php echo esc_attr( $block_id ); ?>" class="wpuf-text-sm wpuf-font-medium wpuf-text-gray-700">
                            <?php esc_html_e( 'Order:', 'wpuf-pro' ); ?>
                        </label>
                        <select
                            id="wpuf-sort-order-<?php echo esc_attr( $block_id ); ?>"
                            class="wpuf-ud-sort-order wpuf-px-4 wpuf-py-2 wpuf-bg-white wpuf-border wpuf-border-gray-300 wpuf-rounded-sm wpuf-text-sm focus:wpuf-outline-none"
                            data-block-id="<?php echo esc_attr( $block_id ); ?>"
                            data-page-id="<?php echo esc_attr( $page_id ); ?>"
                        >
                            <option value="asc" <?php selected( $order, 'asc' ); ?>><?php esc_html_e( 'ASC', 'wpuf-pro' ); ?></option>
                            <option value="desc" <?php selected( $order, 'desc' ); ?>><?php esc_html_e( 'DESC', 'wpuf-pro' ); ?></option>
                        </select>
                    </div>
                </div>
            </div>
            <?php
        } else {
            // Shortcode context - use shortcode-specific template
            ?>
            <div class="wpuf-user-directory-sorting">
                <div class="wpuf-flex wpuf-gap-4 wpuf-items-center">
                    <!-- Sort By Dropdown -->
                    <div class="wpuf-flex wpuf-items-center wpuf-gap-2">
                        <label for="wpuf-sort-by-<?php echo esc_attr( $block_id ); ?>" class="wpuf-text-sm wpuf-font-medium wpuf-text-gray-700">
                            <?php esc_html_e( 'Sort by:', 'wpuf-pro' ); ?>
                        </label>
                        <select
                            id="wpuf-sort-by-<?php echo esc_attr( $block_id ); ?>"
                            class="wpuf-ud-sort-by wpuf-px-3 wpuf-py-4 wpuf-bg-white wpuf-border wpuf-border-gray-300 wpuf-rounded-sm wpuf-text-sm focus:wpuf-outline-none"
                            data-block-id="<?php echo esc_attr( $block_id ); ?>"
                            data-page-id="<?php echo esc_attr( $page_id ); ?>"
                        >
                            <?php
                            // Get all available orderby fields for labels
                            $all_orderby_fields = $this->get_order_by_options();
                            $all_fields_map = array();
                            foreach ( $all_orderby_fields as $field ) {
                                $all_fields_map[ $field['value'] ] = $field['label'];
                            }

                            // Ensure available_sort_options is an array
                            if ( ! is_array( $available_sort_options ) ) {
                                $available_sort_options = ['id', 'user_login', 'user_email', 'display_name', 'user_registered'];
                            }

                            // Only show the available sort options in the dropdown
                            foreach ( $available_sort_options as $field_value ) {
                                $field_value = trim( $field_value );
                                $field_label = isset( $all_fields_map[ $field_value ] ) ? $all_fields_map[ $field_value ] : $this->get_human_readable_field_label( $field_value );

                                // Apply sort-specific filter hook
                                $field_label = apply_filters( 'wpuf_user_directory_sort_field_label', $field_label, $field_value );

                                $selected = ( $field_value === $orderby ) ? 'selected' : '';
                                echo '<option value="' . esc_attr( $field_value ) . '" ' . $selected . '>' . esc_html( $field_label ) . '</option>';
                            }
                            ?>
                        </select>
                    </div>

                    <!-- Sort Order Dropdown -->
                    <div class="wpuf-flex wpuf-items-center wpuf-gap-2">
                        <label for="wpuf-sort-order-<?php echo esc_attr( $block_id ); ?>" class="wpuf-text-sm wpuf-font-medium wpuf-text-gray-700">
                            <?php esc_html_e( 'Order:', 'wpuf-pro' ); ?>
                        </label>
                        <select
                            id="wpuf-sort-order-<?php echo esc_attr( $block_id ); ?>"
                            class="wpuf-ud-sort-order wpuf-px-3 wpuf-py-3 wpuf-bg-white wpuf-border wpuf-border-gray-300 wpuf-rounded-sm wpuf-text-sm focus:wpuf-outline-none"
                            data-block-id="<?php echo esc_attr( $block_id ); ?>"
                            data-page-id="<?php echo esc_attr( $page_id ); ?>"
                        >
                            <option value="asc" <?php selected( $order, 'asc' ); ?>><?php esc_html_e( 'Ascending (A-Z)', 'wpuf-pro' ); ?></option>
                            <option value="desc" <?php selected( $order, 'desc' ); ?>><?php esc_html_e( 'Descending (Z-A)', 'wpuf-pro' ); ?></option>
                        </select>
                    </div>
                </div>
            </div>
            <?php
        }

        // Return the buffered content
        return ob_get_clean();
    }

    /**
     * Check for profile view parameters and get user object
     *
     * @since 4.2.0
     *
     * @param array $attributes Block attributes.
     *
     * @return \WP_User|null User object if profile view, null otherwise.
     */
    private function get_profile_user_from_query( $attributes ) {
        $profile_user_id = null;
        $profile_user    = null;
        $profile_base    = $attributes['profile_base'] ?? 'id';

        // Check for profile view parameters based on profile_base setting
        if ( $profile_base === 'id' && isset( $_GET['id'] ) && is_numeric( $_GET['id'] ) ) {
            $profile_user_id = (int) $_GET['id'];
            $profile_user    = get_user_by( 'ID', $profile_user_id );
        } elseif ( in_array( $profile_base, [ 'user', 'user_login', 'username' ] ) && isset( $_GET['user'] ) && ! empty( $_GET['user'] ) ) {
            $profile_user = get_user_by( 'login', sanitize_text_field( $_GET['user'] ) );
            if ( $profile_user ) {
                $profile_user_id = $profile_user->ID;
            }
        }

        // Fallback: Check for any profile parameters regardless of profile_base setting
        // This ensures compatibility when profile_base settings between blocks differ
        if ( ! $profile_user ) {
            if ( isset( $_GET['id'] ) && is_numeric( $_GET['id'] ) ) {
                $profile_user_id = (int) $_GET['id'];
                $profile_user    = get_user_by( 'ID', $profile_user_id );
            } elseif ( isset( $_GET['user'] ) && ! empty( $_GET['user'] ) ) {
                $profile_user = get_user_by( 'login', sanitize_text_field( $_GET['user'] ) );
                if ( $profile_user ) {
                    $profile_user_id = $profile_user->ID;
                }
            }
        }

        if ( $profile_user ) {
            $profile_user->user_meta = get_user_meta( $profile_user->ID );
        }

        // Return user object if found and valid
        if ( $profile_user && $profile_user_id ) {
            return $profile_user;
        }

        return null;
    }

    /**
     * Render user profile block
     *
     * @since 4.2.0
     *
     * @param \WP_User  $user       User object.
     * @param array     $attributes Block attributes.
     * @param string    $content    Block content.
     * @param \WP_Block $block      Block object.
     *
     * @return string
     */
    private function render_user_profile_block( $user, $attributes, $content, $block ) {
        // Enqueue frontend JavaScript for user tabs functionality
        wp_enqueue_script(
            'wpuf-user-tabs-frontend',
            WPUF_UD_ROOT_URI . '/assets/js/user-tabs-frontend.js',
            ['jquery'],
            WPUF_UD_VERSION,
            true
        );

        // Enqueue frontend JavaScript for profile navigation functionality
        wp_enqueue_script(
            'wpuf-profile-navigation',
            WPUF_UD_ROOT_URI . '/src/js/profile-navigation.js',
            ['jquery'],
            WPUF_UD_VERSION,
            true
        );

        // Enqueue avatar upload functionality
        wp_enqueue_script(
            'cropperjs',
            WPUF_UD_ASSET_URI . '/vendors/cropper/cropper.min.js',
            [],
            '1.5.13',
            true
        );
        wp_enqueue_style(
            'cropperjs',
            WPUF_UD_ASSET_URI . '/vendors/cropper/cropper.min.css',
            [],
            '1.5.13'
        );
        wp_enqueue_script(
            'wpuf-avatar-upload',
            WPUF_UD_ROOT_URI . '/assets/js/avatar-upload.js',
            ['jquery', 'cropperjs'],
            WPUF_UD_VERSION,
            true
        );
        wp_enqueue_style(
            'wpuf-avatar-upload',
            WPUF_UD_ROOT_URI . '/assets/css/avatar-upload-css.css',
            [],
            WPUF_UD_VERSION
        );

        // Localize script with necessary data
        wp_localize_script(
            'wpuf-user-tabs-frontend', 'wpufUserTabs', [
            'ajaxUrl'    => admin_url( 'admin-ajax.php' ),
            'nonce'      => wp_create_nonce( 'wpuf_user_tabs_nonce' ),
            'userId'     => $user->ID,
            'userObject' => [
                'id'           => $user->ID,
                'display_name' => $user->display_name,
                'user_login'   => $user->user_login,
                'user_email'   => $user->user_email,
                'description'  => $user->description,
            ],
            'labels'     => [
                'about'    => __( 'About', 'wpuf-pro' ),
                'posts'    => __( 'Posts', 'wpuf-pro' ),
                'comments' => __( 'Comments', 'wpuf-pro' ),
            ],
            'settings'   => [
                'postsPerPage'    => apply_filters( 'wpuf_user_tabs_posts_per_page', 10 ),
                'commentsPerPage' => apply_filters( 'wpuf_user_tabs_comments_per_page', 10 ),
                'excerptLength'   => apply_filters( 'wpuf_user_tabs_excerpt_length', 20 ),
                'commentLength'   => apply_filters( 'wpuf_user_tabs_comment_length', 100 ),
            ],
        ]
        );

        // Localize avatar upload script
        wp_localize_script(
            'wpuf-avatar-upload', 'wpuf_ud', [
            'ajaxUrl' => admin_url( 'admin-ajax.php' ),
            'nonce'  => wp_create_nonce( 'wpuf_avatar_upload_nonce' ),
        ]
        );
        // Localize navigation script with WPUF settings
        $account_page_id = wpuf_get_option( 'account_page', 'wpuf_my_account', 0 );
        $account_page_url = $account_page_id ? get_permalink( $account_page_id ) : '';

        wp_localize_script( 'wpuf-profile-navigation', 'wpufUserDirectory', array(
            'account_page_url' => $account_page_url,
            'can_edit_profile' => ! empty( $account_page_id ) && 'on' === wpuf_get_option( 'show_edit_profile_menu', 'wpuf_my_account', 'off' ),
        ) );

        // Get the block wrapper attributes with WordPress styling using the custom function
        $wrapper_attributes = wpuf_get_block_wrapper_attributes(
            $attributes, 'user-profile', [
            'class' => 'wpuf-user-profile',
        ]
        );

        // Start building the HTML output
        $html = '<div ' . $wrapper_attributes . '>';

        // Add navigation buttons at the top
        $html .= $this->render_profile_navigation_buttons( $user );

        // Create user context for profile view
        $user_context = [
                            'wpuf-ud/userId'            => $user->ID,
            'wpuf-ud/userObject'        => $user,
                          'wpuf-ud/isDirectoryMode'   => false,
            'wpuf-ud/isProfileMode'     => true,
                          'wpuf-ud/attributes'        => $attributes,
                          'wpuf-ud/directorySettings' => [
                'use_pretty_urls' => true,
            ],
        ];

        // Debug: Check if block has inner content
        $has_inner_content = ! empty( $block->inner_content );
        $has_parsed_blocks = ! empty( $block->parsed_block['innerBlocks'] );

        // Render the inner blocks with user context using the same approach as directory-item

        $inner_content = $this->render_inner_blocks_with_context( $block, $user_context );

        // If no inner content was rendered, show a fallback message
        if ( empty( $inner_content ) ) {
            $html .= '<div class="wpuf-profile-no-content">';
            $html .= '<p>' . esc_html__( 'No profile content found. Please add some blocks to display user information.', 'wpuf-pro' ) . '</p>';
            $html .= '</div>';
        } else {
            $html .= $inner_content;
        }

        $html .= '</div>';

        return $html;
    }

    /**
     * Render standalone user profile block
     *
     * This handles standalone user-profile blocks that are placed independently on pages.
     * It checks if there's already a user-directory block handling profile rendering
     * to avoid duplicate content.
     *
     * @since 4.2.0
     *
     * @param array     $attributes Block attributes.
     * @param string    $content    Block content.
     * @param \WP_Block $block      Block object.
     *
     * @return string
     */
    public function render_user_profile_standalone_block( $attributes, $content, $block ) {
        // Default attributes for user-profile block
        $defaults = [
            'profile_base'        => 'id',
            'tagName'             => 'div',
        ];

        $attributes = wp_parse_args( $attributes, $defaults );

        // Get page context for better coordination
        $page_context = $this->get_page_context();

        // Check if there are profile query parameters first (priority for standalone profile pages)
        $profile_user = $this->get_profile_user_from_query( $attributes );

        if ( $profile_user ) {
            // Enqueue frontend CSS only when block is rendered
            wp_enqueue_style(
                'wpuf-block-user-profile',
                WPUF_UD_ROOT_URI . '/assets/css/block-user-profile.css',
                [],
                WPUF_UD_VERSION
            );

            // Enqueue WordPress block editor styles to ensure CSS custom properties are available
            wp_enqueue_style( 'wp-block-library' );

            // Enqueue frontend JavaScript for user tabs functionality
            wp_enqueue_script(
                'wpuf-user-tabs-frontend',
                WPUF_UD_ROOT_URI . '/assets/js/user-tabs-frontend.js',
                ['jquery'],
                WPUF_UD_VERSION,
                true
            );

            // Add context information for debugging (only in development)
            if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
                $debug_info = sprintf(
                    '<!-- Profile Block Context: Directory Block: %s, Profile Params: %s -->',
                    $page_context['has_directory_block'] ? 'Yes' : 'No',
                    $page_context['has_profile_params'] ? 'Yes' : 'No'
                );
                return $debug_info . $this->render_user_profile_block( $profile_user, $attributes, $content, $block );
            }

            return $this->render_user_profile_block( $profile_user, $attributes, $content, $block );
        }

        // For standalone profile blocks, ONLY show if there are valid query parameters
        // If no query parameters are present, return empty string to hide the block
        // This allows the directory block to be the primary content when no profile is selected

        // Add debug information in development mode
        if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
            $debug_info = sprintf(
                '<!-- Profile Block Hidden: No query parameters found. Directory Block: %s -->',
                $page_context['has_directory_block'] ? 'Yes' : 'No'
            );
            return $debug_info;
        }

        return '<!-- Directory hidden -->';
    }

    /**
     * Check if there's a user-directory block on the current page
     *
     * @since 4.2.0
     *
     * @return bool
     */
    private function has_user_directory_block_on_page() {
        global $post;

        if ( ! $post || ! $post->post_content ) {
            return false;
        }

        // Check if the page content contains a user-directory block
        return strpos( $post->post_content, 'wp:wpuf-ud/directory' ) !== false;
    }

    /**
     * Check if there's a user-profile block on the current page
     *
     * This helps coordinate conditional rendering between directory and profile blocks.
     *
     * @since $$next-version$$
     *
     * @return bool
     */
    private function has_user_profile_block_on_page() {
        global $post;

        if ( ! $post || ! $post->post_content ) {
            return false;
        }

        // Check if the page content contains a user-profile block
        return strpos( $post->post_content, 'wp:wpuf-ud/profile' ) !== false;
    }

    /**
     * Check if there are valid profile query parameters present
     *
     * @since $$next-version$$
     *
     * @param array $attributes Block attributes
     * @return bool
     */
    private function has_profile_query_parameters( $attributes = [] ) {
        $profile_user = $this->get_profile_user_from_query( $attributes );
        return $profile_user !== null;
    }

    /**
     * Get the current page context for profile/directory coordination
     *
     * @since $$next-version$$
     *
     * @return array Context information
     */
    private function get_page_context() {
        return [
            'has_directory_block' => $this->has_user_directory_block_on_page(),
            'has_profile_block'   => $this->has_user_profile_block_on_page(),
            'has_profile_params'  => $this->has_profile_query_parameters(),
            'current_url'         => $_SERVER['REQUEST_URI'] ?? '',
        ];
    }

    /**
     * Render error message for profile block
     *
     * @since 4.2.0
     *
     * @param array $attributes Block attributes.
     *
     * @return string
     */
    private function render_profile_error_message( $attributes ) {
        // Get the block wrapper attributes
        $wrapper_attributes = wpuf_get_block_wrapper_attributes(
            $attributes, 'user-profile', [
                'class' => 'wpuf-user-profile wpuf-user-profile-error',
            ]
        );

        $html = '<div ' . $wrapper_attributes . '>';
        $html .= '<div class="wpuf-profile-error-message">';
        $html .= '<div class="wpuf-profile-error-content">';
        $html .= '<div class="wpuf-profile-error-icon">👤</div>';
        $html .= '<h3>' . esc_html__( 'No User Profile', 'wpuf-pro' ) . '</h3>';
        $html .= '<p>' . esc_html__( 'Please log in or provide a valid user ID/username to view a profile.', 'wpuf-pro' ) . '</p>';
        $html .= '</div>';
        $html .= '</div>';
        $html .= '</div>';

        return $html;
    }

    /**
     * Get current page number for pagination
     *
     * @since 4.2.0
     *
     * @return int
     */
    private function get_current_page() {
        $current_page = 1;

        // Support both ?page=2 and /page/2/
        if ( get_query_var( 'paged' ) ) {
            $current_page = (int) get_query_var( 'paged' );
        } elseif ( ! empty( $_GET['page'] ) ) {
            $current_page = (int) $_GET['page'];
        } else {
            // Check for pretty permalink format /page/X/
            $request_uri = $_SERVER['REQUEST_URI'] ?? '';
            if ( preg_match( '/\/page\/(\d+)/', $request_uri, $matches ) ) {
                $current_page = (int) $matches[1];
            }
        }

        return max( 1, $current_page );
    }

    /**
     * Render pagination HTML for blocks
     *
     * @since 4.2.0
     *
     * @param int    $current_page Current page number.
     * @param int    $total_pages  Total number of pages.
     * @param int    $total_items  Total number of items.
     * @param int    $per_page     Items per page.
     * @param string $block_id     Block ID for JavaScript.
     * @param int    $page_id      Page ID.
     *
     * @return string Pagination HTML.
     */
    private function render_block_pagination( $current_page, $total_pages, $total_items, $per_page, $block_id, $page_id ) {
        // Prepare pagination data
        $pagination = [
            'total_pages'  => $total_pages,
            'total_items'  => $total_items,
            'per_page'     => $per_page,
            'current_page' => $current_page,
        ];

        // Get current URL for pagination links
        $http_host = isset( $_SERVER['HTTP_HOST'] ) ? $_SERVER['HTTP_HOST'] : '';
        $request_uri = isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : '';

        if ( ! empty( $http_host ) && ! empty( $request_uri ) ) {
            $current_url = ( is_ssl() ? 'https://' : 'http://' ) . $http_host . $request_uri;
            $parsed_url = wp_parse_url( $current_url );

            // Ensure wp_parse_url didn't return null
            if ( is_array( $parsed_url ) ) {
                $base_url = isset( $parsed_url['path'] ) ? $parsed_url['path'] : '';

                $query_args = [];
                if ( ! empty( $parsed_url['query'] ) ) {
                    parse_str( $parsed_url['query'], $query_args );
                }
            } else {
                // Fallback if wp_parse_url fails
                $base_url = $request_uri;
                $query_args = [];
            }
        } else {
            // Fallback if server variables are not available
            $base_url = '/';
            $query_args = [];
        }

        unset( $query_args['page'] ); // We'll set this per link

        // Start output buffering to capture pagination template
        ob_start();

        // Add wrapper with search/pagination data attributes for JavaScript
        echo '<div class="wpuf-user-directory-pagination-wrapper wpuf-ud-pagination"
                  data-block-id="' . esc_attr( $block_id ) . '"
                  data-page-id="' . esc_attr( $page_id ) . '">';

        // Include the pagination template
        include WPUF_UD_TEMPLATES . '/blocks/user-directory/components/pagination.php';

        echo '</div>';

        return ob_get_clean();
    }

    /**
     * Replace button profile URLs with actual user profile links for a specific user
     *
     * This method intercepts core/button blocks during rendering and replaces
     * {{profile_url}} placeholders with actual profile URLs based on the provided user context.
     *
     * @since 4.2.0
     *
     * @param string   $block_content The block content.
     * @param array    $block         The block data.
     * @param array    $user_context  The specific user context for this iteration.
     *
     * @return string Modified block content with replaced URLs.
     */
    private function replace_button_profile_urls_for_user( $block_content, $block, $user_context ) {
        // Only process core/button blocks
        if ( ! isset( $block['blockName'] ) || $block['blockName'] !== 'core/button' ) {
            return $block_content;
        }

        // Only process if we have user context (meaning we're inside a user-directory)
        if ( empty( $user_context['wpuf-ud/userObject'] ) ) {
            return $block_content;
        }

        $user = $user_context['wpuf-ud/userObject'];
        $attributes = $user_context['wpuf-ud/attributes'] ?? [];

        // Replace {{profile_url}} placeholders in the button URL
        $button_attributes = $block['attrs'] ?? [];
        $current_url = $button_attributes['url'] ?? '';

        // Check if this button has a profile URL placeholder
        if ( $this->has_profile_url_placeholder( $current_url ) ) {
            // Generate the pretty profile URL for this specific user
            $profile_url = $this->generate_pretty_profile_url( $user );

            // Replace the content's href attribute with the generated profile URL
            $block_content = $this->replace_href_in_content( $block_content, $profile_url );
        }

        return $block_content;
    }


    /**
     * Check if URL contains profile URL placeholder
     *
     * @since 4.2.0
     *
     * @param string $url URL to check.
     *
     * @return bool True if URL contains placeholder.
     */
    private function has_profile_url_placeholder( $url ) {
        if ( empty( $url ) ) {
            return false;
        }

        $placeholders = [
            '{{profile_url}}',
            '{{profile-url}}',
            '{{profileUrl}}',
            '[profile_url]',
            '[profile-url]'
        ];

        foreach ( $placeholders as $placeholder ) {
            if ( strpos( $url, $placeholder ) !== false ) {
                return true;
            }
        }

        return false;
    }

    /**
     * Replace href attribute in button content with profile URL
     *
     * @since 4.2.0
     *
     * @param string $content     Button HTML content.
     * @param string $profile_url Profile URL to replace with.
     *
     * @return string Modified content.
     */
    private function replace_href_in_content( $content, $profile_url ) {
        // Match href attributes that contain placeholders
        $placeholders = [
            '{{profile_url}}',
            '{{profile-url}}',
            '{{profileUrl}}',
            '[profile_url]',
            '[profile-url]'
        ];

        foreach ( $placeholders as $placeholder ) {
            $pattern = '/href=["\']([^"\']*' . preg_quote( $placeholder, '/' ) . '[^"\']*)["\']*/';
            $content = preg_replace( $pattern, 'href="' . esc_url( $profile_url ) . '"', $content );
        }

        return $content;
    }

    /**
     * Render profile button block
     *
     * @since 4.2.0
     *
     * @param array $block_data Block data.
     * @param array $context    User context.
     *
     * @return string
     */
    private function render_profile_button_block( $block_data, $context ) {
        $user = $context['wpuf-ud/userObject'] ?? null;
        if ( ! $user || ! is_object( $user ) ) {
            return '';
        }

        $attributes = $block_data['attrs'] ?? [];

        // Get button attributes
        $button_text = $attributes['buttonText'] ?? __( 'View Profile', 'wpuf-pro' );
        $link_target = $attributes['linkTarget'] ?? '_self';
        $rel = $attributes['rel'] ?? '';

        // Generate pretty profile URL using username
        $profile_url = $this->generate_pretty_profile_url( $user );

        // Use wpuf_get_block_wrapper_attributes with proper block name for consistent styling
        $wrapper_attributes = wpuf_get_block_wrapper_attributes( $attributes, 'profile-button', [
            'class' => 'wpuf-profile-button',
            'data-user-id' => $user->ID,
        ] );
        return sprintf(
            '<div %1$s><a href="%2$s" target="%3$s" rel="%4$s">%5$s</a></div>',
            $wrapper_attributes,
            esc_url( $profile_url ),
            esc_attr( $link_target ),
            esc_attr( $rel ),
            esc_html( $button_text )
        );
    }

    /**
     * Render message button block
     *
     * @since 4.2.0
     *
     * @param array $block_data Block data.
     * @param array $context    User context.
     *
     * @return string
     */
    private function render_message_button_block( $block_data, $context ) {
        // Check if WPUF Private Message class exists
        if ( ! class_exists( 'WPUF_Private_Message' ) ) {
            return '';
        }

        $user = $context['wpuf-ud/userObject'] ?? null;
        if ( ! $user || ! is_object( $user ) ) {
            return '';
        }

        $attributes = $block_data['attrs'] ?? [];

        // Get button attributes
        $button_text = $attributes['buttonText'] ?? __( 'Message', 'wpuf-pro' );
        $link_target = $attributes['linkTarget'] ?? '_self';

        // Get account page ID and URL
        $account_page_id = wpuf_get_option( 'account_page', 'wpuf_my_account', 0 );
        if ( empty( $account_page_id ) ) {
            return '';
        }

        $account_page_url = get_permalink( $account_page_id );
        if ( ! $account_page_url ) {
            return '';
        }

        // Build the message URL: siteurl + account page + ?section=message#/user/{user_id}
        $message_url = add_query_arg( 'section', 'message', $account_page_url ) . '#/user/' . $user->ID;

        // Use wpuf_get_block_wrapper_attributes with proper block name for consistent styling
        $wrapper_attributes = wpuf_get_block_wrapper_attributes( $attributes, 'message-button', [
            'class' => 'wpuf-message-button',
            'data-user-id' => $user->ID,
        ] );

        return sprintf(
            '<div %1$s><a href="%2$s" target="%3$s" class="wpuf-message-button-link">%4$s</a></div>',
            $wrapper_attributes,
            esc_url( $message_url ),
            esc_attr( $link_target ),
            esc_html( $button_text )
        );
    }

    /**
     * Extract the opening wrapper tag from innerHTML
     *
     * @since 4.2.0
     *
     * @param string $inner_html The innerHTML content.
     *
     * @return string|null The opening wrapper tag or null if not found.
     */
    private function extract_wrapper_start( $inner_html ) {
        // Find the first opening tag
        if ( preg_match( '/<([^>]+)>/', $inner_html, $matches ) ) {
            return '<' . $matches[1] . '>';
        }
        return null;
    }

    /**
     * Extract the closing wrapper tag from innerHTML
     *
     * @since 4.2.0
     *
     * @param string $inner_html The innerHTML content.
     *
     * @return string|null The closing wrapper tag or null if not found.
     */
    private function extract_wrapper_end( $inner_html ) {
        // Find the last closing tag
        if ( preg_match( '/<\/([^>]+)>/', $inner_html, $matches ) ) {
            return '</' . $matches[1] . '>';
        }
        return null;
    }

    /**
     * Generate pretty profile URL for a specific user
     *
     * @since 4.2.0
     *
     * @param object $user User object.
     * @param string $base_url Optional base URL to use instead of detecting from current request.
     *
     * @return string Pretty profile URL.
     */
    public function generate_pretty_profile_url( $user, $base_url = null ) {
        if ( ! $user || ! is_object( $user ) || empty( $user->user_login ) ) {
            return '';
        }

        // ULTRA-SIMPLIFIED APPROACH: If we have base_url, just append username
        if ( ! empty( $base_url ) || ! empty( $_GET['base_url'] ) ) {
            // Use provided base_url parameter first, then fall back to $_GET
            $base_url = $base_url ?: $_GET['base_url'];

            // Debug logging
            // Clean up the base URL: remove trailing slash and any query parameters
            $base_url = rtrim( $base_url, '/' );

            // Remove query parameters if present (e.g., ?search=term&orderby=name)
            if ( strpos( $base_url, '?' ) !== false ) {
                $base_url = strtok( $base_url, '?' );
            }

            // Simply append username to the clean page URL
            return $base_url . '/' . $user->user_login;
        }

        // FALLBACK: Complex logic for when base_url is not available
        $current_url = home_url( $_SERVER['REQUEST_URI'] ?? '' );

        // Clean up pagination from the current URL
        $current_url = preg_replace( '#/page/\d+/?$#', '', $current_url );

        // Remove any existing profile parameters
        $current_url = remove_query_arg( [ 'id', 'user', 'user_id', 'username' ], $current_url );

        // Parse the URL to get the path
        $parsed_url = parse_url( $current_url );
        $path = $parsed_url['path'] ?? '/';

        // Remove any existing username from the path, but preserve the directory block URL
        $path_segments = explode( '/', trim( $path, '/' ) );

        if ( ! empty( $path_segments ) ) {
            $last_segment = end( $path_segments );
            // Only remove if it's a username-like pattern (contains numbers, which directory names usually don't)
            if ( preg_match( '/[0-9]/', $last_segment ) && preg_match( '/^[a-zA-Z0-9_-]+$/', $last_segment ) ) {
                array_pop( $path_segments );
                $path = '/' . implode( '/', $path_segments );
                if ( ! empty( $path_segments ) ) {
                    $path .= '/';
                }
            }
        }

        // Ensure path ends with a slash (but not if it's just root)
        if ( $path !== '/' && ! str_ends_with( $path, '/' ) ) {
            $path .= '/';
        }

        // Build the pretty URL by appending username to the directory block URL
        $pretty_url = $path . $user->user_login;

        // Rebuild the full URL
        $scheme = $parsed_url['scheme'] ?? 'http';
        $host = $parsed_url['host'] ?? '';
        $port = ! empty( $parsed_url['port'] ) ? ':' . $parsed_url['port'] : '';
        $query = ! empty( $parsed_url['query'] ) ? '?' . $parsed_url['query'] : '';

        return $scheme . '://' . $host . $port . $pretty_url . $query;
    }

    /**
     * Generate profile URL for a user (legacy method - kept for compatibility)
     *
     * @since 4.2.0
     *
     * @param object $user         User object.
     * @param string $profile_base Profile base setting (ignored - always uses username).
     * @param string $base_url     Base URL for the profile.
     *
     * @return string Profile URL.
     * @deprecated Use generate_pretty_profile_url instead
     */
    private function generate_profile_url( $user, $profile_base = 'user', $base_url = '' ) {
        return $this->generate_pretty_profile_url( $user );
    }

    /**
     * Render search results table rows for reuse by API and frontend
     *
     * @since 4.2.0
     *
     * @param array $users Array of WP_User objects.
     * @param array $attributes Block attributes.
     * @param string $context Rendering context ('block', 'api', or 'ajax').
     *
     * @return string HTML content for table rows (without wrapper).
     */
    public function render_search_results_table_rows( $users, $attributes, $context = 'block' ) {
        if ( empty( $users ) ) {
            $search_term = ! empty( $attributes['search'] ) ? sanitize_text_field( $attributes['search'] ) : '';
            $no_users_message = ! empty( $search_term )
                ? __( 'No users found matching your search criteria.', 'wpuf-pro' )
                : __( 'No users found.', 'wpuf-pro' );

            return '<tr class="wpuf-user-directory-no-users">
                <td colspan="' . $this->get_table_column_count( $attributes ) . '" class="wpuf-text-center wpuf-py-8 wpuf-px-4">
                    <div class="wpuf-text-gray-500 wpuf-text-lg wpuf-mb-2">' . esc_html( $no_users_message ) . '</div>
                    <div class="wpuf-text-gray-400 wpuf-text-sm">' . __( 'Try adjusting your search terms or filters.', 'wpuf-pro' ) . '</div>
                </td>
            </tr>';
        }

        $html = '';
        $show_avatar = isset( $attributes['show_avatar'] ) ? $attributes['show_avatar'] : true;
        $avatar_size = isset( $attributes['avatar_size'] ) ? $attributes['avatar_size'] : 'medium';
        $avatar_shape = isset( $attributes['avatar_shape'] ) ? $attributes['avatar_shape'] : 'circle';
        $avatar_fallback_type = isset( $attributes['avatar_fallback_type'] ) ? $attributes['avatar_fallback_type'] : 'gravatar';

                // Dynamically discover the actual table structure by examining the attributes
        // This should match exactly what the frontend table_layout method uses
        $table_columns = [];

        // Start with the explicitly defined table columns
        if ( isset( $attributes['table_columns'] ) && is_array( $attributes['table_columns'] ) ) {
            $table_columns = $attributes['table_columns'];
        }

        // If no table_columns defined, try to discover from other attributes
        if ( empty( $table_columns ) ) {
            // Look for columns in various possible locations
            if ( isset( $attributes['columns'] ) && is_array( $attributes['columns'] ) ) {
                $table_columns = $attributes['columns'];
            } elseif ( isset( $attributes['meta_field_columns'] ) && is_array( $attributes['meta_field_columns'] ) ) {
                $table_columns = array_keys( $attributes['meta_field_columns'] );
            } else {
                // Fallback to basic columns
                $table_columns = ['username', 'email', 'display_name'];
            }
        }



        // Ensure table_columns is an array
        if ( ! is_array( $table_columns ) ) {
            $table_columns = ['username', 'email', 'display_name'];
        }

        foreach ( $users as $user ) {
            $html .= '<tr class="wpuf-hover:wpuf-bg-gray-50">';

            // Avatar column (if enabled)
            if ( $show_avatar ) {
                $html .= '<td class="wpuf-px-4 wpuf-py-3 wpuf-whitespace-nowrap wpuf-border-b wpuf-border-gray-300">';
                $html .= $this->render_user_avatar( $user, $avatar_size, $avatar_shape, $avatar_fallback_type );
                $html .= '</td>';
            }

            // Dynamic columns using the reusable render_table_cell method
            foreach ( $table_columns as $column ) {
                $html .= '<td class="wpuf-px-4 wpuf-py-3 wpuf-whitespace-nowrap wpuf-border-b wpuf-border-gray-300">';
                $html .= $this->render_table_cell( $user, $column );
                $html .= '</td>';
            }

            // View Profile button column
            $html .= '<td class="wpuf-px-4 wpuf-py-3 wpuf-whitespace-nowrap wpuf-border-b wpuf-border-gray-300">';
            $html .= $this->render_profile_button( $user, $attributes );
            $html .= '</td>';

            $html .= '</tr>';
        }

        return $html;
    }

    /**
     * Handle AJAX search results for table layout
     *
     * @since 4.2.0
     *
     * @param array $users Array of WP_User objects from search.
     * @param array $attributes Block attributes.
     * @param string $search_term Search term used.
     *
     * @return array Response data for AJAX.
     */
    public function handle_ajax_search_results( $users, $attributes, $search_term = '' ) {
        $total = count( $users );

        // Prepare response data
        $response_data = [
            'success' => true,
            'usercount' => $total,
            'announce' => sprintf( __( '%d users found.', 'wpuf-pro' ), $total ),
        ];

        if ( $total === 0 ) {
            // No users found - return empty rows HTML
            $response_data['rows_html'] = $this->render_search_results_table_rows( [], $attributes, 'ajax' );
        } else {
            // Users found - render table rows
            $response_data['rows_html'] = $this->render_search_results_table_rows( $users, $attributes, 'ajax' );
        }

        return $response_data;
    }

    /**
     * Public method to render table cell content for reuse by API
     *
     * @since 4.2.0
     *
     * @param \WP_User $user User object.
     * @param string $column Column key.
     *
     * @return string Cell content.
     */
    public function render_table_cell_public( $user, $column ) {
        return $this->render_table_cell( $user, $column );
    }
}
