<?php

/**
 * @param $args
 *
 * @since 2.0.0
 *
 * @return array
 */
function wpuf_get_users_list( $args = [] ) {
    $users_obj = get_users( $args );
    $users = [];

    foreach ( $users_obj as $user ) {
        $users[$user->ID] = $user->display_name;
    }

    return $users;
}

/**
 * Get user directory users based on directory settings.
 *
 * @param array $filters Directory settings and query parameters.
 * @param array $extra_args Optional. Extra WP_User_Query args to merge.
 *
 * @since 4.2.0
 *
 * @return array [ 'users' => array of WP_User, 'total' => int ]
 */
function wpuf_ud_get_users( $filters = [], $extra_args = [] ) {
    $args = [];

    // Roles
    if ( ! empty( $filters['roles'] ) &&  is_array( $filters['roles'] ) && ! in_array( 'all', $filters['roles'], true ) ) {
        $args['role__in'] = $filters['roles'];
    }

    // Exclude roles
    if ( ! empty( $filters['exclude_roles'] ) && is_array( $filters['exclude_roles'] ) ) {
        $args['role__not_in'] = $filters['exclude_roles'];
    }

    // Exclude users
    if ( ! empty( $filters['exclude_users'] ) && is_array( $filters['exclude_users'] ) ) {
        $args['exclude'] = array_map( 'intval', $filters['exclude_users'] );
    }

    // Pagination (use offset and number)
    $per_page = 10;
    if ( ! empty( $filters['per_page'] ) ) {
        $per_page = intval( $filters['per_page'] );
    } elseif ( ! empty( $filters['max_item_per_page'] ) ) {
        $per_page = intval( $filters['max_item_per_page'] );
    }

    $args['number'] = $per_page;
    $args['offset'] = isset( $filters['offset'] ) ? intval( $filters['offset'] ) : 0;
    $args['count_total'] = true;

    // Store max_item for later use but don't modify query args yet
    $max_item = null;
    if ( isset( $filters['max_item'] ) && intval( $filters['max_item'] ) > 0 ) {
        $max_item = intval( $filters['max_item'] );
    }

    // Search and Sort meta field handling
    $search_meta_key = null;
    $sort_meta_key = null;

    // Check if we're sorting by a meta field
    if ( ! empty( $filters['orderby'] ) ) {
        $orderby = sanitize_key( $filters['orderby'] );

        // First, check if this is a known meta field
        $meta_fields = wpuf_get_user_meta_fields();
        if ( is_array( $meta_fields ) && array_key_exists( $orderby, $meta_fields ) ) {
            // Meta field sorting
            $sort_meta_key = $orderby;
            $args['meta_key'] = $orderby;
            $args['orderby'] = 'meta_value';
        } else {
            // Core field sorting - map common field names to WordPress core fields
            $core_field_mapping = [
                'id' => 'ID',
                'username' => 'user_login',
                'email' => 'user_email',
                'display_name' => 'display_name',
                'user_registered' => 'user_registered',
                'registered' => 'user_registered',
                'login' => 'user_login',
                'user_login' => 'user_login',
                'user_email' => 'user_email',
                'ID' => 'ID',
                'user_id' => 'ID'
            ];

            if ( array_key_exists( $orderby, $core_field_mapping ) ) {
                // Valid core field
                $args['orderby'] = $core_field_mapping[ $orderby ];
            } else {
                // Unknown field - assume it's a meta field and set up meta ordering
                $sort_meta_key = $orderby;
                $args['meta_key'] = $orderby;
                $args['orderby'] = 'meta_value';

                // Try to detect if this is a numeric field
                if ( ! empty( $filters['directory_id'] ) ) {
                    $sample_users = get_users( [ 'number' => 1, 'meta_key' => $orderby ] );
                    if ( ! empty( $sample_users ) ) {
                        $sample_value = get_user_meta( $sample_users[0]->ID, $orderby, true );
                        if ( is_numeric( $sample_value ) ) {
                            $args['orderby'] = 'meta_value_num';
                        }
                    }
                }
            }
        }
    } else {
        $args['orderby'] = 'ID';
    }

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

    // Search
    if ( ! empty( $filters['search'] ) ) {
        $search = sanitize_text_field( $filters['search'] );

        // Check if we're doing meta search
        if ( ! empty( $filters['search_meta_field'] ) ) {
            $search_meta_key = $filters['search_meta_field'];
        } elseif ( ! empty( $filters['searchable_fields'] ) && is_array( $filters['searchable_fields'] ) ) {
            // Core field search
            $args['search'] = '*' . esc_attr( $search ) . '*';
            $args['search_columns'] = array_map( 'sanitize_key', $filters['searchable_fields'] );
        }
    }

    // Handle meta field conflicts between search and sort
    if ( $search_meta_key && $sort_meta_key ) {
        // Both search and sort are using meta fields - use meta_query for search and meta_key for sort
        if ( ! empty( $filters['search'] ) ) {
            $args['meta_query'] = [
                [
                    'key' => $search_meta_key,
                    'value' => $search,
                    'compare' => 'LIKE'
                ]
            ];
        }
        // For sorting, we need to use the meta_key directly as orderby
        $args['orderby'] = $sort_meta_key;
    } elseif ( $search_meta_key ) {
        // Only search is using meta field
        if ( ! empty( $filters['search'] ) ) {
            $args['meta_key'] = $search_meta_key;
            $args['meta_value'] = $search;
            $args['meta_compare'] = 'LIKE';
        }
    } elseif ( $sort_meta_key ) {
        // Only sort is using meta field - use the meta_key directly as orderby
        $args['orderby'] = $sort_meta_key;
    }

    // Merge extra args
    if ( ! empty( $extra_args ) && is_array( $extra_args ) ) {
        $args = array_merge( $args, $extra_args );
    }

    /**
     * Filter user directory query args.
     *
     * @param array $args      WP_User_Query args
     * @param array $filters  Directory settings
     */
    $args = apply_filters( 'wpuf_ud_user_query_args', $args, $filters );

    $user_query = new WP_User_Query( $args );
    $users      = $user_query->get_results();
    $total      = $user_query->get_total();

    // Apply max_item limitations after getting true total
    if ( $max_item !== null ) {
        $offset = $args['offset'];

        // If we're beyond the max_item limit, return empty results
        if ( $offset >= $max_item ) {
            $users = [];
        } else {
            // Limit the returned users to not exceed max_item
            $remaining = $max_item - $offset;
            $limit_for_this_page = min( $per_page, $remaining );

            if ( count( $users ) > $limit_for_this_page ) {
                $users = array_slice( $users, 0, $limit_for_this_page );
            }
        }

        // Set total to the minimum of actual total or max_item for pagination
        $total = min( $total, $max_item );
    }

    return [
        'users' => $users,
        'total' => $total,
    ];
}

/**
 * Build a URL with query args, excluding 'page'.
 *
 * @param string $base_url Base URL to append query args to.
 * @param array  $query_args Query arguments to include.
 * @param int    $page Page number to set in the query args.
 *
 * @return string Full URL with query args.
 */
function wpuf_ud_build_page_url( $base_url, $query_args, $page ) {
    global $wp_rewrite;

    // Ensure we have valid parameters
    if ( empty( $base_url ) ) {
        $base_url = '/';
    }

    if ( ! is_array( $query_args ) ) {
        $query_args = [];
    }

    $page = absint( $page );
    if ( $page < 1 ) {
        $page = 1;
    }

    $is_pretty = $wp_rewrite->using_permalinks();

    // Remove trailing slash for consistency
    $base_url = untrailingslashit( $base_url );

    if ( $is_pretty ) {
        // Remove existing /page/X/ if present
        $base_url = preg_replace( '#/page/\\d+/?$#', '', $base_url );
        $url = $base_url . '/page/' . $page . '/';
        if ( ! empty( $query_args ) ) {
            $url = add_query_arg( $query_args, $url );
        }
    } else {
        $query_args['page'] = $page;
        $url = add_query_arg( $query_args, $base_url );
    }

    return esc_url( $url );
}

/**
 * Build pagination URL for comments
 *
 * @since 4.2.3
 *
 * @param string $base_url Base URL for pagination links
 * @param array  $query_args Query arguments to preserve
 * @param int    $page Page number
 * @return string Full URL with query args
 */
function wpuf_ud_build_comments_page_url( $base_url, $query_args, $page ) {
    // Use the same logic as wpuf_ud_build_page_url but with comments_page parameter
    global $wp_rewrite;

    // Ensure we have valid parameters
    if ( empty( $base_url ) ) {
        $base_url = '/';
    }

    if ( ! is_array( $query_args ) ) {
        $query_args = [];
    }

    $page = absint( $page );
    if ( $page < 1 ) {
        $page = 1;
    }

    $is_pretty = $wp_rewrite->using_permalinks();

    // Remove trailing slash for consistency
    $base_url = untrailingslashit( $base_url );

    if ( $is_pretty ) {
        // For comments, we'll use query parameters even with pretty permalinks
        // to avoid conflicts with directory pagination
        $query_args['comments_page'] = $page;
        $url = add_query_arg( $query_args, $base_url );
    } else {
        $query_args['comments_page'] = $page;
        $url = add_query_arg( $query_args, $base_url );
    }

    return esc_url( $url );
}

/**
 * Render comments pagination using the existing pagination template
 *
 * @since 4.2.3
 *
 * @param array  $pagination Pagination data
 * @param string $base_url Base URL for pagination links
 * @param array  $query_args Query arguments to preserve
 * @return string Pagination HTML
 */
function wpuf_ud_render_comments_pagination( $pagination, $base_url = '', $query_args = [] ) {
    // Validate pagination data
    if ( empty( $pagination ) || ! is_array( $pagination ) ) {
        return '';
    }

    // Check if pagination is needed
    if ( empty( $pagination['total_pages'] ) || $pagination['total_pages'] <= 1 ) {
        return '';
    }

    // Temporarily override the URL builder function for this template
    $original_builder = 'wpuf_ud_build_page_url';
    $GLOBALS['wpuf_pagination_url_builder'] = 'wpuf_ud_build_comments_page_url';

    // Start output buffering
    ob_start();

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

    // Get the output
    $pagination_html = ob_get_clean();

    // Restore original builder
    unset( $GLOBALS['wpuf_pagination_url_builder'] );

    return $pagination_html;
}

/**
 * Build pagination URL for posts
 *
 * @since 4.2.3
 *
 * @param string $base_url Base URL for pagination links
 * @param array  $query_args Query arguments to preserve
 * @param int    $page Page number
 * @return string Full URL with query args
 */
function wpuf_ud_build_posts_page_url( $base_url, $query_args, $page ) {
    // Use the same logic as wpuf_ud_build_page_url but with posts_page parameter
    global $wp_rewrite;

    // Ensure we have valid parameters
    if ( empty( $base_url ) ) {
        $base_url = '/';
    }

    if ( ! is_array( $query_args ) ) {
        $query_args = [];
    }

    $page = absint( $page );
    if ( $page < 1 ) {
        $page = 1;
    }

    $is_pretty = $wp_rewrite->using_permalinks();

    // Remove trailing slash for consistency
    $base_url = untrailingslashit( $base_url );

    if ( $is_pretty ) {
        // For posts, we'll use query parameters even with pretty permalinks
        // to avoid conflicts with directory pagination
        $query_args['posts_page'] = $page;
        $url = add_query_arg( $query_args, $base_url );
    } else {
        $query_args['posts_page'] = $page;
        $url = add_query_arg( $query_args, $base_url );
    }

    return esc_url( $url );
}

/**
 * Render posts pagination using the existing pagination template
 *
 * @since 4.2.3
 *
 * @param array  $pagination Pagination data
 * @param string $base_url Base URL for pagination links
 * @param array  $query_args Query arguments to preserve
 * @return string Pagination HTML
 */
function wpuf_ud_render_posts_pagination( $pagination, $base_url = '', $query_args = [] ) {
    // Validate pagination data
    if ( empty( $pagination ) || ! is_array( $pagination ) ) {
        return '';
    }

    // Check if pagination is needed
    if ( empty( $pagination['total_pages'] ) || $pagination['total_pages'] <= 1 ) {
        return '';
    }

    // Temporarily override the URL builder function for this template
    $original_builder = 'wpuf_ud_build_page_url';
    $GLOBALS['wpuf_pagination_url_builder'] = 'wpuf_ud_build_posts_page_url';

    // Start output buffering
    ob_start();

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

    // Get the output
    $pagination_html = ob_get_clean();

    // Restore original builder
    unset( $GLOBALS['wpuf_pagination_url_builder'] );

    return $pagination_html;
}

/**
 * Global variable to store current profile user context for blocks
 *
 * @var WP_User|null
 */
global $wpuf_ud_current_profile_user;

/**
 * Set current profile user context for child blocks
 *
 * @param WP_User|null $user User object or null to clear context
 * @since 4.2.0
 */
function wpuf_ud_set_current_profile_user( $user ) {
    global $wpuf_ud_current_profile_user;
    $wpuf_ud_current_profile_user = $user;
}

/**
 * Get current profile user from global context
 *
 * @return WP_User|null Current profile user or null if not set
 * @since 4.2.0
 */
function wpuf_ud_get_current_profile_user() {
    global $wpuf_ud_current_profile_user;
    return $wpuf_ud_current_profile_user;
}

/**
 * Locate a template file within the user directory module
 *
 * @param string $template_file Template file name (e.g. 'user-profile/blocks/user-avatar.php')
 * @param string $path Optional. Path to check first (unused but kept for compatibility)
 * @param string $default_path Default path to look for templates
 * @return string|false Full path to template file or false if not found
 * @since 4.2.0
 */
function wpuf_locate_template( $template_file, $path = '', $default_path = '' ) {
    // Check if template exists in theme first (for customization)
    $theme_template = locate_template( array(
        'wpuf-user-directory/' . $template_file,
        'wpuf/' . $template_file,
        $template_file,
    ) );

    if ( $theme_template ) {
        return $theme_template;
    }

    // Check in default path (plugin templates)
    if ( $default_path && file_exists( $default_path . $template_file ) ) {
        return $default_path . $template_file;
    }

    // Check in plugin templates directory as fallback
    $plugin_template = WPUF_UD_TEMPLATES . '/' . $template_file;
    if ( file_exists( $plugin_template ) ) {
        return $plugin_template;
    }

    return false;
}

/**
 * Get user roles in various formats
 *
 * @param string $format Format type: 'key_value' (default), 'js_array', 'display_only'
 * @param WP_User|null $user User object for display format, ignored for other formats
 *
 * @return array User roles in requested format
 * @since 4.2.0
 */
function wpuf_ud_get_user_roles( $format = 'key_value', $user = null ) {
    global $wp_roles;

    if ( ! isset( $wp_roles ) ) {
        $wp_roles = new WP_Roles();
    }

    switch ( $format ) {
        case 'js_array':
            // For JavaScript components that need value/label objects
            $roles = array(
                array(
                    'value' => 'all',
                    'label' => __( 'All Roles', 'wpuf-pro' ),
                ),
            );

            foreach ( $wp_roles->get_names() as $role => $name ) {
                $roles[] = array(
                    'value' => $role,
                    'label' => translate_user_role( $name ),
                );
            }
            return $roles;

        case 'display_only':
            // For displaying a specific user's roles
            if ( ! $user || ! isset( $user->roles ) || ! is_array( $user->roles ) ) {
                return [];
            }

            return array_map( function( $role ) {
                return ucwords( str_replace( '_', ' ', $role ) );
            }, $user->roles );

        case 'key_value':
        default:
            // For MultiSelect components and simple key-value needs
            $roles = [];

            foreach ( $wp_roles->get_names() as $role => $name ) {
                $roles[ $role ] = translate_user_role( $name );
            }

            return $roles;
    }
}

/**
 * Get user roles formatted for display
 *
 * @param WP_User $user User object
 *
 * @return array Array of role names formatted for display
 *
 * @since 4.2.0
 * @deprecated 4.2.0 Use wpuf_ud_get_user_roles('display_only', $user) instead
 */
function wpuf_ud_get_user_roles_display( $user ) {
    return wpuf_ud_get_user_roles( 'display_only', $user );
}

/**
 * Get image sizes formatted for JavaScript
 *
 * @return array Image sizes with value/label pairs
 * @since 4.2.0
 */
function wpuf_ud_get_image_sizes_for_js() {
    $sizes = array();

    foreach ( get_intermediate_image_sizes() as $size ) {
        $sizes[] = array(
            'value' => $size,
            'label' => ucwords( str_replace( array( '-', '_' ), ' ', $size ) ),
        );
    }

    // Add full size
    $sizes[] = array(
        'value' => 'full',
        'label' => __( 'Full Size', 'wpuf-pro' ),
    );

    return $sizes;
}

/**
 * Get user initials from display name, user login, or email
 *
 * @param WP_User $user User object
 *
 * @return string Initials or '?' if no name available
 *
 * @since 4.2.0
 */
function wpuf_ud_get_user_initials( $user ) {
    $name = $user->display_name ?: $user->user_login ?: $user->user_email ?: '';

    if ( empty( $name ) ) {
        return '?';
    }

    $words = explode( ' ', $name );
    $initials = '';

    foreach ( $words as $word ) {
        if ( ! empty( $word ) ) {
            $initials .= strtoupper( substr( $word, 0, 1 ) );
        }
    }

    return substr( $initials, 0, 2 );
}

/**
 * Get avatar display size based on block attributes
 *
 * @param string $avatar_size Avatar size from block attributes
 * @param int $custom_size Custom size if specified
 *
 * @return int Display size in pixels
 *
 * @since 4.2.0
 */
function wpuf_ud_get_avatar_display_size( $avatar_size, $custom_size ) {
    $sizes = [
        'small'     => 32,
        'medium'    => 96,
        'large'     => 150,
        'xlarge'    => 300,
        'custom'    => $custom_size
    ];

    return isset( $sizes[ $avatar_size ] ) ? $sizes[ $avatar_size ] : 96;
}

/**
 * Get avatar URL for a user, checking for custom avatars
 *
 * @param WP_User $user User object
 * @param int $size Size in pixels
 *
 * @return string|false Avatar URL or false if no custom avatar
 *
 * @since 4.2.0
 */
function wpuf_ud_get_avatar_url( $user, $size ) {
    // First check for wpuf_profile_photo meta
    $profile_photo_id = get_user_meta( $user->ID, 'wpuf_profile_photo', true );

    if ( $profile_photo_id ) {
        $photo_url = wp_get_attachment_url( $profile_photo_id );
        if ( $photo_url ) {
            return $photo_url;
        }
    }

    // Check if user has a real Gravatar
    $email_hash = md5( strtolower( trim( $user->user_email ) ) );
    $gravatar_check_url = "https://www.gravatar.com/avatar/{$email_hash}?d=404&s={$size}";
    $response = wp_remote_head( $gravatar_check_url, [ 'timeout' => 2 ] );

    if ( ! is_wp_error( $response ) && wp_remote_retrieve_response_code( $response ) === 200 ) {
        // User has a real Gravatar
        return "https://www.gravatar.com/avatar/{$email_hash}?s={$size}";
    }

    // No custom avatar found
    return false;
}

/**
 * Get user avatar HTML with fallbacks
 *
 * @param WP_User|int $user User object or ID
 * @param int $size Avatar size in pixels
 * @param string $class CSS classes for the avatar
 * @return string HTML for avatar with fallback to initials
 * @since 4.2.0
 */
function wpuf_ud_get_user_avatar_html( $user, $size = 128, $class = '' ) {
    // Get user object if ID is passed
    if ( is_numeric( $user ) ) {
        $user = get_user_by( 'id', $user );
    }

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

    // Get avatar URL (checks wpuf_profile_photo first, then gravatar)
    $avatar_url = wpuf_ud_get_avatar_url( $user, $size );

    // Get user's name for initials
    $first_name = get_user_meta( $user->ID, 'first_name', true );
    $last_name = get_user_meta( $user->ID, 'last_name', true );

    // Calculate initials
    if ( $first_name && $last_name ) {
        $initials = strtoupper( substr( $first_name, 0, 1 ) . substr( $last_name, 0, 1 ) );
    } else {
        $name = $user->display_name ?: $user->user_login;
        $name_parts = explode( ' ', $name );
        if ( count( $name_parts ) >= 2 ) {
            $initials = strtoupper( substr( $name_parts[0], 0, 1 ) . substr( $name_parts[1], 0, 1 ) );
        } else {
            $initials = strtoupper( substr( $name, 0, 2 ) );
        }
    }

    // If we have an avatar URL, return just the img
    if ( $avatar_url ) {
        return sprintf(
            '<img src="%s" alt="%s" class="%s" width="%d" height="%d" style="width: %dpx; height: %dpx; object-fit: cover;" />',
            esc_url( $avatar_url ),
            esc_attr( $user->display_name ),
            esc_attr( $class ),
            $size,
            $size,
            $size,
            $size
        );
    }

    // No avatar URL, show initials directly
    return sprintf(
        '<div class="%s !wpuf-bg-gray-400 !wpuf-text-white !wpuf-flex !wpuf-items-center !wpuf-justify-center !wpuf-font-semibold" style="width: %dpx; height: %dpx; font-size: %dpx !important;">%s</div>',
        esc_attr( $class ),
        $size,
        $size,
        max( $size / 2.5, 16 ),
        esc_html( $initials )
    );
}

/**
 * Get avatar styling for templates
 *
 * @param array $attributes Block attributes
 * @param WP_User $user User object
 * @return array Styling data
 *
 * @since 4.2.0
 */
function wpuf_get_avatar_styling( $attributes, $user ) {
    $avatar_shape = $attributes['avatarShape'] ?? 'circle';
    $avatar_size = $attributes['avatarSize'] ?? 'thumbnail';
    $custom_size = $attributes['customSize'] ?? 150;

    // CSS Classes (for predefined patterns)
    $classes = [ 'wpuf-user-avatar' ];
    $classes[] = 'wpuf-avatar--' . $avatar_shape; // circle, square, rounded
    $classes[] = 'wpuf-avatar--' . $avatar_size;  // thumbnail, medium, large

    // Inline Styles (for custom/dynamic values)
    $inline_styles = [];

    // Custom size needs inline style
    if ( $avatar_size === 'custom' ) {
        $inline_styles['width'] = $custom_size . 'px';
        $inline_styles['height'] = $custom_size . 'px';
    }

    // Block editor styles (spacing, borders, colors)
    if ( ! empty( $attributes['style'] ) ) {
        $inline_styles = array_merge( $inline_styles, $attributes['style'] );
    }

    return [
        'classes' => implode( ' ', $classes ),
        'styles' => $inline_styles
    ];
}



/**
 * Get profile URL for user
 *
 * @param WP_User $user User object
 * @param array $all_data All data array
 * @return string Profile URL
 *
 * @since 4.2.0
 */
function wpuf_ud_get_profile_url( $user, $all_data ) {
    $profile_base = $all_data['profile_base'] ?? 'username';


    // Get the current page/post URL
    $current_url = '';

    // First, check if base_url is provided in all_data (from AJAX requests)
    if ( ! empty( $all_data['base_url'] ) ) {
        // Use the base URL provided from AJAX request
        $current_url = $all_data['base_url'];

        // If it's just a path, build a full URL
        if ( strpos( $current_url, 'http' ) !== 0 ) {
            $scheme = is_ssl() ? 'https' : 'http';
            $host = $_SERVER['HTTP_HOST'] ?? '';
            $current_url = $scheme . '://' . $host . $current_url;
        }

        // Skip the fallback URL detection since we have a valid base_url
        goto skip_fallback_url_detection;
    } else {
        // Fallback to detecting current URL
        // Try to get the current post/page URL
        if ( is_singular() ) {
            $current_url = get_permalink();
        } elseif ( is_home() ) {
            $current_url = home_url();
        } elseif ( is_front_page() ) {
            $current_url = home_url();
        } else {
            // Fallback to current request URL
            $current_url = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
        }

    }

    skip_fallback_url_detection:

    // Parse the current URL
    $parsed_url = parse_url($current_url);
    $scheme = $parsed_url['scheme'] ?? 'http';
    $host = $parsed_url['host'] ?? '';
    $path = $parsed_url['path'] ?? '';
    $query = $parsed_url['query'] ?? '';

    // Parse existing query parameters
    parse_str($query, $query_params);

    // Remove any existing profile parameters
    unset($query_params['user']);
    unset($query_params['user_id']);
    unset($query_params['username']);
    unset($query_params['id']);

    // Determine the user identifier based on profile base
    $user_identifier = '';
    switch ($profile_base) {
        case 'user_id':
            $user_identifier = $user->ID;
            break;
        case 'username':
        case 'user_login':
        case 'user':
        default:
            $user_identifier = $user->user_login;
            break;
    }

    // Check if this is a shortcode-based directory
    $is_shortcode = false;

    // First check if explicitly passed in all_data (from templates)
    if ( ! empty( $all_data['is_shortcode'] ) ) {
        $is_shortcode = true;
    } else {
        // Check multiple ways to detect shortcode context

        // Method 1: Check global post for shortcode
        global $post;
        if ( $post && ( has_shortcode( $post->post_content, 'wpuf_user_listing' ) ||
                       has_shortcode( $post->post_content, 'wpuf_user_listing_id' ) ) ) {
            $is_shortcode = true;
        }

        // Method 2: Try to get page ID from URL and check for shortcode
        if ( ! $is_shortcode ) {
            // Get page ID from current URL
            $page_id = url_to_postid( $current_url );

            // If we have pagination, try removing it to get the base page
            if ( ! $page_id && preg_match( '#/page/\d+/#', $current_url ) ) {
                $base_url = preg_replace( '#/page/\d+/#', '/', $current_url );
                $page_id = url_to_postid( $base_url );
            }

            if ( $page_id ) {
                $page_content = get_post_field( 'post_content', $page_id );
                if ( $page_content && (
                    strpos( $page_content, '[wpuf_user_listing' ) !== false ||
                    strpos( $page_content, '[wpuf_user_listing_id' ) !== false
                )) {
                    $is_shortcode = true;
                }
            }
        }

        // Method 3: Check queried object
        if ( ! $is_shortcode ) {
            $queried_object = get_queried_object();
            if ( $queried_object && isset( $queried_object->post_content ) ) {
                if ( has_shortcode( $queried_object->post_content, 'wpuf_user_listing' ) ||
                     has_shortcode( $queried_object->post_content, 'wpuf_user_listing_id' ) ) {
                    $is_shortcode = true;
                }
            }
        }
    }

    // For shortcodes, ALWAYS use clean URL format - strictly no query parameters
    if ( $is_shortcode ) {
        // Generate clean URL: /directory/username or /directory/123
        $clean_base_url = strtok($current_url, '?');
        // Remove pagination from URL if present to get the base directory URL
        $clean_base_url = preg_replace( '#/page/\d+/?$#', '', $clean_base_url );
        $clean_base_url = rtrim($clean_base_url, '/');
        return $clean_base_url . '/' . $user_identifier;
    }

    // Generate pretty URL for username-based profiles if current page supports it (for blocks)
    if ( in_array( $profile_base, [ 'username', 'user_login', 'user' ] ) && \WPUF\UserDirectory\PrettyUrls::current_page_supports_pretty_urls() ) {
        // Clean up the current URL before passing it to generate_profile_url
        $clean_url = rtrim( $current_url, '/' );
        if ( strpos( $clean_url, '?' ) !== false ) {
            $clean_url = strtok( $clean_url, '?' );
        }
        return \WPUF\UserDirectory\PrettyUrls::generate_profile_url( $user_identifier, $clean_url );
    }

    // Fallback to query parameter approach only for blocks when page doesn't support pretty URLs
    $query_arg = '';
    switch ($profile_base) {
        case 'user_id':
            $query_arg = 'user_id';
            break;
        case 'username':
            $query_arg = 'username';
            break;
        case 'user_login':
        case 'user':
        default:
            $query_arg = 'user';
            break;
    }

    // Add the profile parameter
    $query_params[$query_arg] = $user_identifier;

    // Rebuild the URL
    $new_query = http_build_query($query_params);
    $url = $scheme . '://' . $host . $path;

    if (!empty($new_query)) {
        $url .= '?' . $new_query;
    }


    return esc_url($url);
}

/**
 * Get formatted user name based on selected format
 *
 * @param WP_User $user User object
 * @param string $name_format Format type (display_name, user_login, custom)
 * @param string $custom_format Custom format string with placeholders
 *
 * @return string Formatted user name
 *
 * @since 4.2.0
 */
function wpuf_ud_get_formatted_name( $user, $name_format, $custom_format ) {
    switch ( $name_format ) {
        case 'display_name':
            return $user->display_name ?: $user->user_login ?: __( 'Unknown User', 'wpuf-pro' );

        case 'first_last':
            $name = trim( ( $user->first_name ?: '' ) . ' ' . ( $user->last_name ?: '' ) );
            return $name ?: $user->display_name ?: $user->user_login ?: __( 'Unknown User', 'wpuf-pro' );

        case 'last_first':
            $last_name = $user->last_name ?: '';
            $first_name = $user->first_name ?: '';
            if ( $last_name && $first_name ) {
                return $last_name . ', ' . $first_name;
            }
            return $user->display_name ?: $user->user_login ?: __( 'Unknown User', 'wpuf-pro' );

        case 'first_only':
            return $user->first_name ?: $user->display_name ?: $user->user_login ?: __( 'Unknown User', 'wpuf-pro' );

        case 'username':
            return $user->user_login ?: $user->user_nicename ?: __( 'Unknown User', 'wpuf-pro' );

        case 'custom':
            // Replace tokens in custom format
            $formatted = $custom_format;
            $formatted = str_replace( '{first_name}', $user->first_name ?: '', $formatted );
            $formatted = str_replace( '{last_name}', $user->last_name ?: '', $formatted );
            $formatted = str_replace( '{display_name}', $user->display_name ?: '', $formatted );
            $formatted = str_replace( '{username}', $user->user_login ?: '', $formatted );
            $formatted = str_replace( '{nickname}', $user->nickname ?: '', $formatted );
            $formatted = trim( $formatted );
            return $formatted ?: $user->display_name ?: __( 'Unknown User', 'wpuf-pro' );

        default:
            return $user->display_name ?: $user->user_login ?: __( 'Unknown User', 'wpuf-pro' );
    }
}

/**
 * Get URL for user name link based on destination type
 *
 * @param string $destination Destination type (profile, edit, custom)
 * @param WP_User $user User object
 *
 * @return string URL for the user name link
 *
 * @since 4.2.0
 */
function wpuf_ud_get_name_link_url( $link_destination, $user ) {
    switch ( $link_destination ) {
        case 'profile_edit':
            return admin_url( 'profile.php' );
        case 'custom_url':
            // TODO: Implement custom URL with user tokens
            return '#';
        default:
            return '#';
    }
}

/**
 * Get block avatar URL with custom profile photo priority
 *
 * @param WP_User $user User object
 * @param int $size Size in pixels
 * @param string $fallback_type Fallback type (gravatar|initials)
 * @return array Avatar data with URL and type
 * @since 4.2.0
 */
function wpuf_ud_get_block_avatar_data( $user, $size, $fallback_type = 'gravatar' ) {
    // 1. First priority: Check for custom profile photo
    $custom_photo_url = wpuf_ud_get_custom_profile_photo_url( $user->ID, $size );

    if ( $custom_photo_url ) {
        return [
            'url' => $custom_photo_url,
            'type' => 'custom',
            'alt' => sprintf( __( 'Profile photo of %s', 'wpuf-pro' ), $user->display_name )
        ];
    }

    // 2. Second priority: Use fallback type setting
    if ( $fallback_type === 'gravatar' ) {
        // Check if user has a real Gravatar using the same logic as wpuf_ud_get_avatar_url
        $email_hash = md5( strtolower( trim( $user->user_email ) ) );
        $gravatar_check_url = "https://www.gravatar.com/avatar/{$email_hash}?d=404&s={$size}";
        $response = wp_remote_head( $gravatar_check_url, [ 'timeout' => 2 ] );

        if ( ! is_wp_error( $response ) && wp_remote_retrieve_response_code( $response ) === 200 ) {
            // User has a real Gravatar
            $gravatar_url = "https://www.gravatar.com/avatar/{$email_hash}?s={$size}";
            return [
                'url' => $gravatar_url,
                'type' => 'gravatar',
                'alt' => sprintf( __( 'Avatar of %s', 'wpuf-pro' ), $user->display_name )
            ];
        }

        // No real Gravatar found, return none to trigger initials fallback
        return [
            'url' => false,
            'type' => 'none',
            'alt' => sprintf( __( 'Avatar of %s', 'wpuf-pro' ), $user->display_name )
        ];
    }

    // 3. Fallback to initials
    return [
        'url' => false,
        'type' => 'initials',
        'alt' => sprintf( __( 'Avatar of %s', 'wpuf-pro' ), $user->display_name )
    ];
}

/**
 * Get custom profile photo URL from usermeta
 *
 * @param int $user_id User ID
 * @param int $size Requested size (kept for backwards compatibility but not used)
 * @return string|false Custom photo URL or false if not found
 * @since 4.2.0
 */
function wpuf_ud_get_custom_profile_photo_url( $user_id, $size = 0 ) {
    $attachment_id = get_user_meta( $user_id, 'wpuf_profile_photo', true );

    if ( ! $attachment_id || ! is_numeric( $attachment_id ) ) {
        return false;
    }

    // Use wp_get_attachment_url() for direct URL (same as directory listing)
    // This ensures consistent behavior between directory and profile pages
    // Note: We use full size URL and let browser handle scaling for better quality
    $photo_url = wp_get_attachment_url( $attachment_id );

    if ( ! $photo_url ) {
        return false;
    }

    return $photo_url;
}

/**
 * Validate profile photo data structure
 *
 * @param mixed $photo_data Photo data from usermeta (single attachment ID)
 * @return bool Whether data structure is valid
 * @since 4.2.0
 */
function wpuf_ud_validate_profile_photo_data( $photo_data ) {
    // Must be a numeric attachment ID
    if ( ! $photo_data || ! is_numeric( $photo_data ) ) {
        return false;
    }

    // Check if attachment exists and is valid
    $attachment = get_post( $photo_data );
    if ( ! $attachment || 'attachment' !== $attachment->post_type ) {
        return false;
    }

    // Use the existing validation function if available
    if ( function_exists( 'wpuf_validate_profile_photo_file' ) ) {
        $file_path = get_attached_file( $photo_data );
        if ( $file_path && file_exists( $file_path ) ) {
            $validation_result = wpuf_validate_profile_photo_file( $file_path, basename( $file_path ) );
            return $validation_result !== false;
        }
    }

    // Use the existing validation function if available
    if ( function_exists( 'wpuf_validate_profile_photo_file' ) ) {
        $file_path = get_attached_file( $photo_data );
        if ( $file_path && file_exists( $file_path ) ) {
            $validation_result = wpuf_validate_profile_photo_file( $file_path, basename( $file_path ) );
            return $validation_result !== false;
        }
    }

    return true;
}

/**
 * Validate image URL and format
 *
 * @param string $url Image URL
 * @return bool Whether URL is valid
 * @since 4.2.0
 */
function wpuf_ud_validate_image_url( $url ) {
    if ( empty( $url ) || ! is_string( $url ) ) {
        return false;
    }

    // Check if URL is valid
    if ( ! filter_var( $url, FILTER_VALIDATE_URL ) ) {
        return false;
    }

    // Check file extension
    $path = parse_url( $url, PHP_URL_PATH );
    $extension = strtolower( pathinfo( $path, PATHINFO_EXTENSION ) );

    $allowed_extensions = [ 'jpg', 'jpeg', 'png', 'webp', 'gif' ];

    return in_array( $extension, $allowed_extensions, true );
}

/**
 * Check if image file size is reasonable for avatar
 *
 * @param string $url Image URL
 * @return bool Whether file size is acceptable
 * @since 4.2.0
 */
function wpuf_ud_validate_image_file_size( $url ) {
    // Get file size (with timeout to avoid hanging)
    $context = stream_context_create( [
        'http' => [
            'timeout' => 5,
            'method' => 'HEAD'
        ]
    ] );

    $headers = get_headers( $url, 1, $context );

    if ( ! $headers || ! isset( $headers['Content-Length'] ) ) {
        return true; // Assume OK if we can't check
    }

    $file_size = (int) $headers['Content-Length'];
    $max_size = 5 * 1024 * 1024; // 5MB max

    return $file_size <= $max_size;
}

/**
 * Validate image dimensions for avatar
 *
 * @param string $url Image URL
 * @return bool Whether dimensions are acceptable
 * @since 4.2.0
 */
function wpuf_ud_validate_image_dimensions( $url ) {
    // Get image info
    $image_info = wpuf_ud_get_image_info( $url );

    if ( ! $image_info ) {
        return true; // Assume OK if we can't check
    }

    // Minimum dimensions
    $min_width = 32;
    $min_height = 32;

    // Maximum dimensions
    $max_width = 2048;
    $max_height = 2048;

    return $image_info['width'] >= $min_width &&
           $image_info['height'] >= $min_height &&
           $image_info['width'] <= $max_width &&
           $image_info['height'] <= $max_height;
}

/**
 * Get basic image information
 *
 * @param string $url Image URL
 * @return array|false Image info or false on failure
 * @since 4.2.0
 */
function wpuf_ud_get_image_info( $url ) {
    // Try to get image info
    $image_data = wp_remote_get( $url, [
        'timeout' => 5,
        'stream' => true
    ] );

    if ( is_wp_error( $image_data ) ) {
        return false;
    }

    $image_path = $image_data['filename'] ?? null;
    if ( ! $image_path || ! file_exists( $image_path ) ) {
        return false;
    }

    $image_info = getimagesize( $image_path );
    if ( ! $image_info ) {
        return false;
    }

    return [
        'width' => $image_info[0],
        'height' => $image_info[1],
        'type' => $image_info[2],
        'mime' => $image_info['mime']
    ];
}

/**
 * Create profile photo data from a single attachment ID
 *
 * @param int $attachment_id Attachment ID
 * @return int|false Attachment ID or false on failure
 * @since 4.2.0
 */
function wpuf_ud_create_profile_photo_data( $attachment_id ) {
    if ( ! $attachment_id || ! is_numeric( $attachment_id ) ) {
        return false;
    }

    // Check if attachment exists
    $attachment = get_post( $attachment_id );
    if ( ! $attachment || 'attachment' !== $attachment->post_type ) {
        return false;
    }

    return $attachment_id;
}

/**
 * Get profile photo data for a user
 *
 * @param int $user_id User ID
 * @return int|false Attachment ID or false if not found
 * @since 4.2.0
 */
function wpuf_ud_get_profile_photo_data( $user_id ) {
    $attachment_id = get_user_meta( $user_id, 'wpuf_profile_photo', true );

    if ( wpuf_ud_validate_profile_photo_data( $attachment_id ) ) {
        return $attachment_id;
    }

    return false;
}

/**
 * Get color scheme for profile layout pagination
 *
 * @param string $layout Profile layout identifier (layout-1, layout-2, etc.)
 * @return array Color configuration for the profile layout
 * @since 4.2.0
 */
function wpuf_ud_get_profile_layout_colors( $layout ) {
    $color_schemes = [
        'layout-1' => [
            'primary' => 'gray',
            'primary_500' => 'wpuf-bg-gray-800',
            'primary_600' => 'wpuf-bg-gray-800',
            'primary_700' => 'wpuf-bg-gray-700',
            'text_primary_600' => 'wpuf-text-gray-800',
            'text_primary_700' => 'wpuf-text-gray-700',
            'border_primary_600' => 'wpuf-border-gray-800',
            'border_primary_700' => 'wpuf-border-gray-700',
            'ring_primary_500' => 'wpuf-ring-gray-800',
            'hover_primary_600' => 'hover:wpuf-text-gray-800',
            'hover_primary_700' => 'hover:wpuf-bg-gray-700',
            'hover_border_primary_600' => 'hover:wpuf-border-gray-800',
        ],
        'layout-2' => [
            'primary' => 'green',
            'primary_500' => 'wpuf-bg-green-500',
            'primary_600' => 'wpuf-bg-green-600',
            'primary_700' => 'wpuf-bg-green-700',
            'text_primary_600' => 'wpuf-text-green-600',
            'text_primary_700' => 'wpuf-text-green-700',
            'border_primary_600' => 'wpuf-border-green-600',
            'border_primary_700' => 'wpuf-border-green-700',
            'ring_primary_500' => 'wpuf-ring-green-500',
            'hover_primary_600' => 'hover:wpuf-text-green-600',
            'hover_primary_700' => 'hover:wpuf-bg-green-700',
            'hover_border_primary_600' => 'hover:wpuf-border-green-600',
            'focus_ring_primary_500' => 'focus:!wpuf-ring-green-500',
        ],
        'layout-3' => [
            'primary' => 'blue',
            'primary_500' => 'wpuf-bg-blue-500',
            'primary_600' => 'wpuf-bg-blue-600',
            'primary_700' => 'wpuf-bg-blue-700',
            'text_primary_600' => 'wpuf-text-blue-600',
            'text_primary_700' => 'wpuf-text-blue-700',
            'border_primary_600' => 'wpuf-border-blue-600',
            'border_primary_700' => 'wpuf-border-blue-700',
            'ring_primary_500' => 'wpuf-ring-blue-500',
            'hover_primary_600' => 'hover:wpuf-text-blue-600',
            'hover_primary_700' => 'hover:wpuf-bg-blue-700',
            'hover_border_primary_600' => 'hover:wpuf-border-blue-600',
        ],
    ];

    // Default to blue if layout not found
    return isset( $color_schemes[$layout] ) ? $color_schemes[$layout] : $color_schemes['layout-1'];
}

/**
 * Get color scheme for layout
 *
 * @param string $layout Layout identifier (layout-1, layout-2, etc.)
 * @return array Color configuration for the layout
 * @since 4.2.0
 */
function wpuf_ud_get_layout_colors( $layout ) {
    $color_schemes = [
        'layout-1' => [
            'primary' => 'blue',
            'primary_500' => 'wpuf-bg-blue-500',
            'primary_600' => 'wpuf-bg-blue-600',
            'primary_700' => 'wpuf-bg-blue-700',
            'text_primary_600' => 'wpuf-text-blue-600',
            'text_primary_700' => 'wpuf-text-blue-700',
            'border_primary_600' => 'wpuf-border-blue-600',
            'border_primary_700' => 'wpuf-border-blue-700',
            'ring_primary_500' => 'wpuf-ring-blue-500',
            'hover_primary_600' => 'hover:wpuf-text-blue-600',
            'hover_primary_700' => 'hover:wpuf-bg-blue-700',
            'hover_border_primary_600' => 'hover:wpuf-border-blue-600',
            'focus_ring_primary_500' => 'focus:!wpuf-ring-blue-500',
        ],
        'layout-2' => [
            'primary' => 'green',
            'primary_500' => 'wpuf-bg-green-500',
            'primary_600' => 'wpuf-bg-green-600',
            'primary_700' => 'wpuf-bg-green-700',
            'text_primary_600' => 'wpuf-text-green-600',
            'text_primary_700' => 'wpuf-text-green-700',
            'border_primary_600' => 'wpuf-border-green-600',
            'border_primary_700' => 'wpuf-border-green-700',
            'ring_primary_500' => 'wpuf-ring-green-500',
            'hover_primary_600' => 'hover:wpuf-text-green-600',
            'hover_primary_700' => 'hover:wpuf-bg-green-700',
            'hover_border_primary_600' => 'hover:wpuf-border-green-600',
            'focus_ring_primary_500' => 'focus:!wpuf-ring-green-500',
        ],
        'layout-3' => [
            'primary' => 'purple',
            'primary_500' => 'wpuf-bg-purple-500',
            'primary_600' => 'wpuf-bg-purple-600',
            'primary_700' => 'wpuf-bg-purple-700',
            'text_primary_600' => 'wpuf-text-purple-600',
            'text_primary_700' => 'wpuf-text-purple-700',
            'border_primary_600' => 'wpuf-border-purple-600',
            'border_primary_700' => 'wpuf-border-purple-700',
            'ring_primary_500' => 'wpuf-ring-purple-500',
            'hover_primary_600' => 'hover:wpuf-text-purple-600',
            'hover_primary_700' => 'hover:wpuf-bg-purple-700',
            'hover_border_primary_600' => 'hover:wpuf-border-purple-600',
            'focus_ring_primary_500' => 'focus:!wpuf-ring-purple-500',
        ],
        'layout-4' => [
            'primary' => 'gray',
            'primary_500' => 'wpuf-bg-gray-800',
            'primary_600' => 'wpuf-bg-gray-800',
            'primary_700' => 'wpuf-bg-gray-700',
            'text_primary_600' => 'wpuf-text-gray-800',
            'text_primary_700' => 'wpuf-text-gray-700',
            'border_primary_600' => 'wpuf-border-gray-800',
            'border_primary_700' => 'wpuf-border-gray-700',
            'ring_primary_500' => 'wpuf-ring-gray-800',
            'hover_primary_600' => 'hover:wpuf-text-gray-800',
            'hover_primary_700' => 'hover:wpuf-bg-gray-700',
            'hover_border_primary_600' => 'hover:wpuf-border-gray-800',
            'focus_ring_primary_500' => 'focus:!wpuf-ring-gray-800',
        ],
        'layout-5' => [
            'primary' => 'purple',
            'primary_500' => 'wpuf-bg-purple-600',
            'primary_600' => 'wpuf-bg-purple-600',
            'primary_700' => 'wpuf-bg-purple-700',
            'text_primary_600' => 'wpuf-text-purple-600',
            'text_primary_700' => 'wpuf-text-purple-700',
            'border_primary_600' => 'wpuf-border-purple-600',
            'border_primary_700' => 'wpuf-border-purple-700',
            'ring_primary_500' => 'wpuf-ring-purple-600',
            'hover_primary_600' => 'hover:wpuf-text-purple-600',
            'hover_primary_700' => 'hover:wpuf-bg-purple-700',
            'hover_border_primary_600' => 'hover:wpuf-border-purple-600',
            'focus_ring_primary_500' => 'focus:!wpuf-ring-purple-600',
        ],
        'layout-6' => [
            'primary' => 'gray',
            'primary_500' => 'wpuf-bg-gray-800',
            'primary_600' => 'wpuf-bg-gray-800',
            'primary_700' => 'wpuf-bg-gray-700',
            'text_primary_600' => 'wpuf-text-gray-800',
            'text_primary_700' => 'wpuf-text-gray-700',
            'border_primary_600' => 'wpuf-border-gray-800',
            'border_primary_700' => 'wpuf-border-gray-700',
            'ring_primary_500' => 'wpuf-ring-gray-800',
            'hover_primary_600' => 'hover:wpuf-text-gray-800',
            'hover_primary_700' => 'hover:wpuf-bg-gray-700',
            'hover_border_primary_600' => 'hover:wpuf-border-gray-800',
            'focus_ring_primary_500' => 'focus:!wpuf-ring-gray-800',
        ],
    ];

    // Return colors for the requested layout, fallback to layout-1 (blue) if not found
    return isset( $color_schemes[$layout] ) ? $color_schemes[$layout] : $color_schemes['layout-1'];
}

/**
 * Get social media fields configuration
 *
 * @return array Social media fields with labels
 *
 * @since 4.2.0
 */
function wpuf_ud_get_social_fields() {
    return [
        'wpuf_social_twitter' => __( 'X', 'wpuf-pro' ),
        'wpuf_social_facebook' => __( 'Facebook', 'wpuf-pro' ),
        'wpuf_social_linkedin' => __( 'LinkedIn', 'wpuf-pro' ),
        'wpuf_social_instagram' => __( 'Instagram', 'wpuf-pro' ),
    ];
}

/**
 * Get social media icons SVG
 *
 * @param string $icon_class Optional CSS class for icons
 * @return array Social media field keys with SVG icons
 *
 * @since 4.2.0
 */
function wpuf_ud_get_social_icons( $icon_class = '!wpuf-w-3 !wpuf-h-3' ) {
    return [
        'wpuf_social_twitter' => '<svg class="' . esc_attr( $icon_class ) . '" viewBox="0 0 20 20" fill="currentColor"><path d="M11.905 8.505L19.34 0h-1.764l-6.453 7.395L5.829 0H0l7.802 11.345L0 20h1.764l6.815-7.807L14.171 20H20L11.905 8.505zm-2.412 2.764l-.79-1.13L2.4 1.3h2.706l5.082 7.268.79 1.13 6.597 9.436h-2.706l-5.376-7.686v-.179z"/></svg>',
        'wpuf_social_facebook' => '<svg class="' . esc_attr( $icon_class ) . '" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M20 10c0-5.523-4.477-10-10-10S0 4.477 0 10c0 4.991 3.657 9.128 8.438 9.878v-6.987h-2.54V10h2.54V7.797c0-2.506 1.492-3.89 3.777-3.89 1.094 0 2.238.195 2.238.195v2.46h-1.26c-1.243 0-1.63.771-1.63 1.562V10h2.773l-.443 2.89h-2.33v6.988C16.343 19.128 20 14.991 20 10z" clip-rule="evenodd"></path></svg>',
        'wpuf_social_instagram' => '<svg class="' . esc_attr( $icon_class ) . '" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M10 0C7.284 0 6.944.012 5.877.06c-1.064.049-1.791.218-2.427.465a4.902 4.902 0 00-1.772 1.153A4.902 4.902 0 00.525 3.45C.278 4.086.109 4.813.06 5.877.012 6.944 0 7.284 0 10s.012 3.056.06 4.123c.049 1.064.218 1.791.465 2.427a4.902 4.902 0 001.153 1.772 4.902 4.902 0 001.772 1.153c.636.247 1.363.416 2.427.465C6.944 19.988 7.284 20 10 20s3.056-.012 4.123-.06c1.064-.049 1.791-.218 2.427-.465a4.902 4.902 0 001.772-1.153 4.902 4.902 0 001.153-1.772c.247-.636.416-1.363.465-2.427.048-1.067.06-1.407.06-4.123s-.012-3.056-.06-4.123c-.049-1.064-.218-1.791-.465-2.427a4.902 4.902 0 00-1.153-1.772A4.902 4.902 0 0016.55.525C15.914.278 15.187.109 14.123.06 13.056.012 12.716 0 10 0zm0 1.802c2.67 0 2.986.01 4.04.058.976.045 1.505.207 1.858.344.466.182.8.399 1.15.748.35.35.566.684.748 1.15.137.353.3.882.344 1.857.048 1.055.058 1.37.058 4.041 0 2.67-.01 2.986-.058 4.04-.045.976-.207 1.505-.344 1.858a3.097 3.097 0 01-.748 1.15 3.098 3.098 0 01-1.15.748c-.353.137-.882.3-1.857.344-1.054.048-1.37.058-4.041.058-2.67 0-2.987-.01-4.04-.058-.976-.045-1.505-.207-1.858-.344a3.098 3.098 0 01-1.15-.748 3.098 3.098 0 01-.748-1.15c-.137-.353-.3-.882-.344-1.857-.048-1.055-.058-1.37-.058-4.041 0-2.67.01-2.986.058-4.04.045-.976.207-1.505.344-1.858.182-.466.399-.8.748-1.15.35-.35.684-.566 1.15-.748.353-.137.882-.3 1.857-.344 1.055-.048 1.37-.058 4.041-.058z" clip-rule="evenodd"></path><path fill-rule="evenodd" d="M10 13.333a3.333 3.333 0 110-6.666 3.333 3.333 0 010 6.666zm0-8.468a5.135 5.135 0 100 10.27 5.135 5.135 0 000-10.27z" clip-rule="evenodd"></path><circle cx="15.338" cy="4.662" r="1.2"></circle></svg>',
        'wpuf_social_linkedin' => '<svg class="' . esc_attr( $icon_class ) . '" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M16.338 16.338H13.67V12.16c0-.995-.017-2.277-1.387-2.277-1.39 0-1.601 1.086-1.601 2.207v4.248H8.014v-8.59h2.559v1.174h.037c.356-.675 1.227-1.387 2.526-1.387 2.703 0 3.203 1.778 3.203 4.092v4.711zM5.005 6.575a1.548 1.548 0 11-.003-3.096 1.548 1.548 0 01.003 3.096zm-1.337 9.763H6.34v-8.59H3.667v8.59zM17.668 1H2.328C1.595 1 1 1.581 1 2.298v15.403C1 18.418 1.595 19 2.328 19h15.34c.734 0 1.332-.582 1.332-1.299V2.298C19 1.581 18.402 1 17.668 1z" clip-rule="evenodd"></path></svg>',
    ];
}

/**
 * Get user social media links
 *
 * @param WP_User|int $user User object or user ID
 * @return array Array of social media field keys with user URLs
 *
 * @since 4.2.0
 */
function wpuf_ud_get_user_social_links( $user ) {
    // Get user ID
    if ( is_object( $user ) ) {
        $user_id = $user->ID;
    } else {
        $user_id = intval( $user );
    }

    $social_fields = wpuf_ud_get_social_fields();
    $user_social_links = [];

    foreach ( $social_fields as $field_key => $field_label ) {
        $value = get_user_meta( $user_id, $field_key, true );
        if ( ! empty( $value ) ) {
            $user_social_links[ $field_key ] = esc_url( $value );
        }
    }

    return $user_social_links;
}

/**
 * Get user files for About tab rendering
 *
 * @param int $user_id User ID
 * @param string $meta_key Optional meta key to check for specific files
 * @return array Array of file IDs
 *
 * @since 4.2.0
 */
function wpuf_ud_get_user_files( $user_id, $meta_key = '' ) {
    $files = [];

    if ( ! empty( $meta_key ) ) {
        $attachment_ids = get_user_meta( $user_id, $meta_key );

        if ( ! empty( $attachment_ids ) ) {
            foreach ( $attachment_ids as $attachment_id ) {
                $files[] = $attachment_id;
            }
        }
    }

    // Also check for general user attachments if no specific files found
    if ( empty( $files ) ) {
        $attachments = get_posts([
            'post_type'      => 'attachment',
            'author'         => $user_id,
            'posts_per_page' => 10,
            'post_status'    => 'inherit',
            'meta_query'     => [
                [
                    'key'     => '_wp_attachment_metadata',
                    'compare' => 'EXISTS'
                ]
            ]
        ]);

        foreach ( $attachments as $attachment ) {
            $files[] = $attachment->ID;
        }
    }

    return $files;
}

/**
 * Check if user has files for About tab content detection
 *
 * @param int $user_id User ID
 * @param string $meta_key Optional meta key to check for specific files
 * @return bool True if user has files, false otherwise
 *
 * @since 4.2.0
 */
function wpuf_ud_user_has_files( $user_id, $meta_key = '' ) {
    $files = wpuf_ud_get_user_files( $user_id, $meta_key );
    return ! empty( $files );
}

/**
 * Get meta field value for a user
 *
 * @param WP_User $user User object
 * @param int $user_id User ID
 * @param string $meta_key Meta key to retrieve
 * @return string|array Meta field value
 *
 * @since 4.2.0
 */
function wpuf_ud_get_meta_field_value( $user, $user_id, $meta_key ) {
    $value = '';

    if ( empty( $meta_key ) ) {
        return $value;
    }

    // Handle special meta keys first
    if ( $meta_key === 'user_login' ) {
        $value = $user->user_login;
    } elseif ( $meta_key === 'user_email' ) {
        $value = $user->user_email;
    } elseif ( $meta_key === 'display_name' ) {
        $value = $user->display_name;
    } elseif ( $meta_key === 'user_url' ) {
        $value = $user->user_url;
    } elseif ( $meta_key === 'description' ) {
        $value = get_user_meta( $user_id, 'description', true );
    } else {
        // Check user meta
        $meta_value = get_user_meta( $user_id, $meta_key, true );

        // Check user data object
        if ( empty( $meta_value ) && ! empty( $user->data->$meta_key ) ) {
            $value = $user->data->$meta_key;
        } else {
            $value = $meta_value;
        }
    }

    // Handle array values
    if ( is_array( $value ) ) {
        $value = implode( ', ', $value );
    }

    return $value;
}

/**
 * Render meta field for About tab templates
 *
 * @param array $field Field configuration
 * @param WP_User $user User object
 * @param int $user_id User ID
 * @param string $template_style Template style (1, 2, 3)
 * @return void
 *
 * @since 4.2.0
 */
function wpuf_ud_render_meta_field( $field, $user, $user_id, $template_style = '1' ) {
    $meta_key = $field['meta_key'] ?? '';
    $value = wpuf_ud_get_meta_field_value( $user, $user_id, $meta_key );

    if ( empty( $value ) || $value === '-1' ) {
        return;
    }

    // Special rendering for Biography field (description) in templates 2 and 3
    if ( $meta_key === 'description' && in_array( $template_style, ['2', '3'] ) ) {
        $heading_size = $template_style === '2' ? '!wpuf-text-xl' : '!wpuf-text-lg';
        $margin_bottom = $template_style === '2' ? '!wpuf-mb-10' : '!wpuf-mb-8';
        ?>
        <div class="wpuf-profile-section wpuf-biography-section <?php echo esc_attr( $margin_bottom ); ?>">
            <h1 class="profile-section-heading <?php echo esc_attr( $heading_size ); ?> !wpuf-font-bold !wpuf-text-gray-900 !wpuf-mb-4">
                <?php echo esc_html( $field['label'] ); ?>
            </h1>
            <div class="biography-content !wpuf-text-gray-600 !wpuf-leading-relaxed !wpuf-text-base">
                <p><?php echo esc_html( $value ); ?></p>
            </div>
        </div>
        <?php
    } else {
        // Standard meta field rendering
        ?>
        <div class="wpuf-profile-value !wpuf-mb-4">
            <?php if ( ! empty( $field['label'] ) ) : ?>
                <label class="wpuf-ud-profile-label !wpuf-font-medium !wpuf-text-gray-700 !wpuf-mb-1 !wpuf-inline-block">
                    <?php echo esc_html( $field['label'] ); ?>:
                </label>
            <?php endif; ?>
            <span class="!wpuf-text-gray-600 <?php echo ! empty( $field['label'] ) ? '!wpuf-ml-2' : ''; ?>">
                <?php echo links_add_target( make_clickable( wp_kses_post( $value ) ) ); ?>
            </span>
        </div>
        <?php
    }
}

/**
 * Get file icon SVG path based on file type (matches existing file tab categories)
 *
 * @param int $file_id Attachment ID
 * @return string SVG path for the file icon
 *
 * @since 4.2.0
 */
function wpuf_ud_get_file_icon_svg( $file_id ) {
    $file_type = get_post_mime_type( $file_id );

    // Images - Font Awesome image icon path
    if ( strpos( $file_type, 'image/' ) === 0 ) {
        return 'M64 32C28.7 32 0 60.7 0 96L0 416c0 35.3 28.7 64 64 64l320 0c35.3 0 64-28.7 64-64l0-320c0-35.3-28.7-64-64-64L64 32zm64 80a48 48 0 1 1 0 96 48 48 0 1 1 0-96zM272 224c8.4 0 16.1 4.4 20.5 11.5l88 144c4.5 7.4 4.7 16.7 .5 24.3S368.7 416 360 416L88 416c-8.9 0-17.2-5-21.3-12.9s-3.5-17.5 1.6-24.8l56-80c4.5-6.4 11.8-10.2 19.7-10.2s15.2 3.8 19.7 10.2l26.4 37.8 61.4-100.5c4.4-7.1 12.1-11.5 20.5-11.5z';
    }

    // Documents - Font Awesome document icon path
    if ( in_array( $file_type, ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'text/plain'] ) ) {
        return 'M64 0C28.7 0 0 28.7 0 64L0 448c0 35.3 28.7 64 64 64l256 0c35.3 0 64-28.7 64-64l0-277.5c0-17-6.7-33.3-18.7-45.3L258.7 18.7C246.7 6.7 230.5 0 213.5 0L64 0zM325.5 176L232 176c-13.3 0-24-10.7-24-24L208 58.5 325.5 176z';
    }

    // Videos - Font Awesome video icon path
    if ( strpos( $file_type, 'video/' ) === 0 ) {
        return 'M0 256a256 256 0 1 1 512 0 256 256 0 1 1 -512 0zM188.3 147.1c-7.6 4.2-12.3 12.3-12.3 20.9l0 176c0 8.7 4.7 16.7 12.3 20.9s16.8 4.1 24.3-.5l144-88c7.1-4.4 11.5-12.1 11.5-20.5s-4.4-16.1-11.5-20.5l-144-88c-7.4-4.5-16.7-4.7-24.3-.5z';
    }

    // Audio - Font Awesome audio icon path
    if ( strpos( $file_type, 'audio/' ) === 0 ) {
        return 'M533.6 32.5c-10.3-8.4-25.4-6.8-33.8 3.5s-6.8 25.4 3.5 33.8C557.5 113.8 592 180.8 592 256s-34.5 142.2-88.7 186.3c-10.3 8.4-11.8 23.5-3.5 33.8s23.5 11.8 33.8 3.5C598.5 426.7 640 346.2 640 256S598.5 85.2 533.6 32.5zM473.1 107c-10.3-8.4-25.4-6.8-33.8 3.5s-6.8 25.4 3.5 33.8C475.3 170.7 496 210.9 496 256s-20.7 85.3-53.2 111.8c-10.3 8.4-11.8 23.5-3.5 33.8s23.5 11.8 33.8 3.5c43.2-35.2 70.9-88.9 70.9-149s-27.7-113.8-70.9-149zm-60.5 74.5c-10.3-8.4-25.4-6.8-33.8 3.5s-6.8 25.4 3.5 33.8C393.1 227.6 400 241 400 256s-6.9 28.4-17.7 37.3c-10.3 8.4-11.8 23.5-3.5 33.8s23.5 11.8 33.8 3.5C434.1 312.9 448 286.1 448 256s-13.9-56.9-35.4-74.5zM80 352l48 0 134.1 119.2c6.4 5.7 14.6 8.8 23.1 8.8 19.2 0 34.8-15.6 34.8-34.8l0-378.4c0-19.2-15.6-34.8-34.8-34.8-8.5 0-16.7 3.1-23.1 8.8L128 160 80 160c-26.5 0-48 21.5-48 48l0 96c0 26.5 21.5 48 48 48z';
    }

    // Archives - Font Awesome folder icon path
    if ( in_array( $file_type, ['application/zip', 'application/x-rar-compressed', 'application/x-7z-compressed', 'application/x-tar', 'application/gzip'] ) ) {
        return 'M56 225.6L32.4 296.2 32.4 96c0-35.3 28.7-64 64-64l138.7 0c13.8 0 27.3 4.5 38.4 12.8l38.4 28.8c5.5 4.2 12.3 6.4 19.2 6.4l117.3 0c35.3 0 64 28.7 64 64l0 16-365.4 0c-41.3 0-78 26.4-91.1 65.6zM477.8 448L99 448c-32.8 0-55.9-32.1-45.5-63.2l48-144C108 221.2 126.4 208 147 208l378.8 0c32.8 0 55.9 32.1 45.5 63.2l-48 144c-6.5 19.6-24.9 32.8-45.5 32.8z';
    }

    // Others - Font Awesome folder icon path (same as archives)
    return 'M56 225.6L32.4 296.2 32.4 96c0-35.3 28.7-64 64-64l138.7 0c13.8 0 27.3 4.5 38.4 12.8l38.4 28.8c5.5 4.2 12.3 6.4 19.2 6.4l117.3 0c35.3 0 64 28.7 64 64l0 16-365.4 0c-41.3 0-78 26.4-91.1 65.6zM477.8 448L99 448c-32.8 0-55.9-32.1-45.5-63.2l48-144C108 221.2 126.4 208 147 208l378.8 0c32.8 0 55.9 32.1 45.5 63.2l-48 144c-6.5 19.6-24.9 32.8-45.5 32.8z';
}

/**
 * Get file icon viewBox based on file type (for Font Awesome icons)
 *
 * @param int $file_id Attachment ID
 * @return string ViewBox for the SVG icon
 *
 * @since 4.2.0
 */
function wpuf_ud_get_file_icon_viewbox( $file_id ) {
    $file_type = get_post_mime_type( $file_id );

    // Images - viewBox="0 0 448 512"
    if ( strpos( $file_type, 'image/' ) === 0 ) {
        return '0 0 448 512';
    }

    // Documents - viewBox="0 0 384 512"
    if ( in_array( $file_type, ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'text/plain'] ) ) {
        return '0 0 384 512';
    }

    // Videos - viewBox="0 0 512 512"
    if ( strpos( $file_type, 'video/' ) === 0 ) {
        return '0 0 512 512';
    }

    // Audio - viewBox="0 0 640 512"
    if ( strpos( $file_type, 'audio/' ) === 0 ) {
        return '0 0 640 512';
    }

    // Archives & Others - viewBox="0 0 576 512"
    return '0 0 576 512';
}

/**
 * Render user posts table for About tab templates
 *
 * @param array $field Field configuration
 * @param int $user_id User ID
 * @param string $template_style Template style (1, 2, 3)
 * @return void
 *
 * @since 4.2.0
 */
function wpuf_ud_render_posts_table( $field, $user_id, $template_style = '1' ) {
    $post_type = $field['post_type'] ?? 'post';
    $count = $field['count'] ?? 5;

    $post_args = [
        'author'         => $user_id,
        'post_type'      => $post_type,
        'post_status'    => 'publish',
        'posts_per_page' => $count,
        'orderby'        => 'date',
        'order'          => 'DESC'
    ];

    $user_posts = new WP_Query( $post_args );

    if ( ! $user_posts->have_posts() ) {
        return;
    }

    // Template-specific styling
    $styles = wpuf_ud_get_posts_table_styles( $template_style );

    ?>
    <div class="wpuf-profile-section wpuf-posts-section <?php echo esc_attr( $styles['section_margin'] ); ?>">

        <h1 class="!wpuf-text-2xl !wpuf-font-bold !wpuf-text-gray-700 !wpuf-mb-3">
            <?php echo esc_html( $field['label'] ); ?>
        </h1>


        <div class="posts-table <?php echo esc_attr( $styles['table_bg'] ); ?> <?php echo esc_attr( $styles['table_rounded'] ); ?> !wpuf-border !wpuf-border-gray-200 !wpuf-overflow-hidden">
            <!-- Table Header -->
            <div class="table-header <?php echo esc_attr( $styles['header_bg'] ); ?> !wpuf-border-b !wpuf-border-gray-200 <?php echo esc_attr( $styles['header_height'] ); ?> !wpuf-flex !wpuf-items-center">
                <div class="<?php echo esc_attr( $styles['grid_class'] ); ?> !wpuf-px-6 !wpuf-items-center !wpuf-w-full">
                    <div class="<?php echo esc_attr( $styles['title_col'] ); ?> !wpuf-text-base !wpuf-font-normal <?php echo esc_attr( $styles['header_text_color'] ); ?> !wpuf-leading-none">
                        <?php esc_html_e( 'Post Title', 'wpuf-pro' ); ?>
                    </div>
                    <div class="<?php echo esc_attr( $styles['date_col'] ); ?> !wpuf-text-base !wpuf-font-normal <?php echo esc_attr( $styles['header_text_color'] ); ?> !wpuf-leading-none">
                        <?php esc_html_e( 'Publish Date', 'wpuf-pro' ); ?>
                    </div>
                    <?php if ( in_array( $template_style, ['1', '2', '3'] ) ) : ?>
                    <div class="!wpuf-col-span-3 !wpuf-text-base !wpuf-font-normal <?php echo esc_attr( $styles['header_text_color'] ); ?> !wpuf-text-right !wpuf-leading-none">
                        <?php esc_html_e( 'Action', 'wpuf-pro' ); ?>
                    </div>
                    <?php endif; ?>
                </div>
            </div>

            <!-- Table Body -->
            <div class="table-body !wpuf-bg-white">
                <?php while ( $user_posts->have_posts() ) : $user_posts->the_post(); ?>
                <div class="table-row !wpuf-border-b !wpuf-border-gray-100 last:!wpuf-border-b-0 <?php echo esc_attr( $styles['row_hover'] ); ?> !wpuf-transition-colors !wpuf-duration-150 <?php echo esc_attr( $styles['row_height'] ); ?> !wpuf-flex !wpuf-items-center">
                    <div class="<?php echo esc_attr( $styles['grid_class'] ); ?> !wpuf-px-6 !wpuf-items-center !wpuf-w-full">
                        <div class="<?php echo esc_attr( $styles['title_col'] ); ?>">
                            <div class="!wpuf-text-base !wpuf-font-normal !wpuf-text-gray-900 !wpuf-leading-none">
                                <?php echo wp_trim_words( get_the_title(), 10 ); ?>
                            </div>
                        </div>
                        <div class="<?php echo esc_attr( $styles['date_col'] ); ?>">
                            <div class="!wpuf-text-base !wpuf-font-normal !wpuf-text-gray-600 !wpuf-leading-none">
                                <?php echo esc_html( get_the_date( 'M j, Y' ) ); ?>
                            </div>
                        </div>
                        <?php if ( in_array( $template_style, ['1', '2', '3'] ) ) : ?>
                        <div class="!wpuf-col-span-3 !wpuf-text-right">
                            <a href="<?php echo get_permalink(); ?>"
                               target="_blank"
                               class="!wpuf-inline-flex !wpuf-items-center !wpuf-gap-1 !wpuf-text-base !wpuf-font-normal !wpuf-text-gray-700 <?php echo esc_attr( $styles['link_hover'] ); ?> !wpuf-transition-colors !wpuf-no-underline">
                                <?php esc_html_e( 'Post Link', 'wpuf-pro' ); ?>
                                <svg class="!wpuf-w-3 !wpuf-h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
                                </svg>
                            </a>
                        </div>
                        <?php endif; ?>
                    </div>
                </div>
                <?php endwhile; ?>
            </div>
        </div>
    </div>
    <?php

    wp_reset_postdata();
}

/**
 * Get posts table styling based on template style
 *
 * @param string $template_style Template style (1, 2, 3)
 * @return array Styling classes
 *
 * @since 4.2.0
 */
function wpuf_ud_get_posts_table_styles( $template_style ) {
    switch ( $template_style ) {
        case '2':
            return [
                'section_margin' => '!wpuf-mb-10',
                'heading_size' => '!wpuf-text-xl',
                'table_bg' => '!wpuf-bg-gray-50',
                'table_rounded' => '!wpuf-rounded-xl',
                'header_bg' => '!wpuf-bg-white',
                'header_height' => '!wpuf-h-[50px]',
                'header_text_color' => '!wpuf-text-emerald-600',
                'grid_class' => '!wpuf-grid !wpuf-grid-cols-12 !wpuf-gap-4',
                'title_col' => '!wpuf-col-span-6',
                'date_col' => '!wpuf-col-span-3',
                'row_hover' => 'hover:!wpuf-bg-emerald-50',
                'row_height' => '!wpuf-h-[58px]',
                'link_hover' => 'hover:!wpuf-text-emerald-600'
            ];

        case '3':
            return [
                'section_margin' => '!wpuf-mb-8',
                'heading_size' => '!wpuf-text-xl',
                'table_bg' => '!wpuf-bg-gray-50',
                'table_rounded' => '!wpuf-rounded-xl',
                'header_bg' => '!wpuf-bg-white',
                'header_height' => '!wpuf-h-[50px]',
                'header_text_color' => '!wpuf-text-blue-500',
                'grid_class' => '!wpuf-grid !wpuf-grid-cols-12 !wpuf-gap-4',
                'title_col' => '!wpuf-col-span-6',
                'date_col' => '!wpuf-col-span-3',
                'row_hover' => 'hover:!wpuf-bg-blue-50',
                'row_height' => '!wpuf-h-[58px]',
                'link_hover' => 'hover:!wpuf-text-blue-500'
            ];

        default: // Template 1
            return [
                'section_margin' => '!wpuf-mb-6',
                'heading_size' => '',
                'table_bg' => '!wpuf-bg-white',
                'table_rounded' => '!wpuf-rounded-lg',
                'header_bg' => '!wpuf-bg-gray-50',
                'header_height' => '!wpuf-py-3',
                'header_text_color' => '!wpuf-text-gray-700',
                'grid_class' => '!wpuf-grid !wpuf-grid-cols-12 !wpuf-gap-4',
                'title_col' => '!wpuf-col-span-6',
                'date_col' => '!wpuf-col-span-3',
                'row_hover' => 'hover:!wpuf-bg-gray-50',
                'row_height' => '!wpuf-py-3',
                'link_hover' => 'hover:!wpuf-text-gray-700'
            ];
    }
}

/**
 * Render user files grid for About tab templates
 *
 * @param array $field Field configuration
 * @param int $user_id User ID
 * @param array $template_data Template data for image sizing
 * @param string $theme_color Theme color for icons (gray, emerald, blue)
 * @return void
 *
 * @since 4.2.0
 */
function wpuf_ud_render_files_grid( $field, $user_id, $template_data = [], $theme_color = 'gray' ) {
    $meta_key = $field['meta_key'] ?? '';
    $files = wpuf_ud_get_user_files( $user_id, $meta_key );

    if ( empty( $files ) ) {
        return;
    }

    // Color mapping for different themes
    $theme_colors = [
        'gray' => 'wpuf-text-gray-400',
        'emerald' => 'wpuf-text-emerald-400',
        'blue' => 'wpuf-text-blue-400'
    ];

    $hover_colors = [
        'gray' => 'hover:!wpuf-border-gray-300 hover:!wpuf-shadow-md',
        'emerald' => 'hover:!wpuf-border-emerald-300 hover:!wpuf-shadow-lg',
        'blue' => 'hover:!wpuf-border-blue-300 hover:!wpuf-shadow-md'
    ];

    $icon_color = $theme_colors[$theme_color] ?? $theme_colors['gray'];
    $hover_class = $hover_colors[$theme_color] ?? '';

    ?>
    <div class="wpuf-profile-section wpuf-files-section !wpuf-mb-16">
        <h1 class="!wpuf-text-2xl !wpuf-text-gray-700 !wpuf-font-bold !wpuf-mb-4">
            <?php echo esc_html( $field['label'] ); ?>
        </h1>
        <div class="files-grid !wpuf-grid !wpuf-grid-cols-2 sm:!wpuf-grid-cols-3 md:!wpuf-grid-cols-4 !wpuf-gap-3">
            <?php foreach ( array_slice( $files, 0, 8 ) as $file_id ) :
                $file_url = wp_get_attachment_url( $file_id );
                $file_title = get_the_title( $file_id );
                $is_image = wp_attachment_is_image( $file_id );
                ?>
                <a href="<?php echo esc_url( $file_url ); ?>" target="_blank" class="!wpuf-block !wpuf-no-underline">
                    <div class="!wpuf-border !wpuf-border-gray-200 !wpuf-rounded-lg !wpuf-overflow-hidden <?php echo esc_attr( $hover_class ); ?> !wpuf-transition-all !wpuf-duration-200 !wpuf-p-3">
                        <?php if ( $is_image ) :
                            // Show image normally
                            $image_size = 'thumbnail';
                            if ( ! empty( $template_data['gallery_img_size'] ) ) {
                                $available_sizes = get_intermediate_image_sizes();
                                $available_sizes[] = 'full';

                                if ( in_array( $template_data['gallery_img_size'], $available_sizes ) ) {
                                    $image_size = $template_data['gallery_img_size'];
                                } elseif ( is_numeric( $template_data['gallery_img_size'] ) ) {
                                    $size_value = intval( $template_data['gallery_img_size'] );
                                    $image_size = array( $size_value, $size_value );
                                }
                            }
                            $image_thumb = wp_get_attachment_image_src( $file_id, $image_size );
                            ?>
                            <img src="<?php echo esc_url( $image_thumb[0] ); ?>" alt="<?php echo esc_attr( $file_title ); ?>" class="!wpuf-w-full !wpuf-object-cover">
                        <?php else :
                            // Show file type specific icon for non-image files
                            $icon_path = wpuf_ud_get_file_icon_svg( $file_id );
                            $icon_viewbox = wpuf_ud_get_file_icon_viewbox( $file_id );
                            ?>
                            <div class="!wpuf-flex !wpuf-flex-col !wpuf-items-center !wpuf-justify-center !wpuf-py-4">
                                <svg class="!wpuf-w-12 !wpuf-h-12 <?php echo esc_attr( $icon_color ); ?> !wpuf-mb-2" fill="currentColor" viewBox="<?php echo esc_attr( $icon_viewbox ); ?>">
                                    <path d="<?php echo esc_attr( $icon_path ); ?>"></path>
                                </svg>
                                <span class="!wpuf-text-xs !wpuf-text-gray-600 !wpuf-text-center"><?php echo esc_html( wp_trim_words( $file_title, 3 ) ); ?></span>
                            </div>
                        <?php endif; ?>
                    </div>
                </a>
            <?php endforeach; ?>
        </div>
    </div>
    <?php
}

/**
 * Render user files grid grouped by file type for About tab templates
 *
 * @param array $field Field configuration
 * @param int $user_id User ID
 * @param array $template_data Template data for image sizing
 * @param string $theme_color Theme color for tabs (gray, emerald, blue)
 * @return void
 *
 * @since 4.2.0
 */
function wpuf_ud_render_files_grouped_by_type( $field, $user_id, $template_data = [], $theme_color = 'gray' ) {
    $meta_key = $field['meta_key'] ?? '';
    $files = wpuf_ud_get_user_files( $user_id, $meta_key );

    if ( empty( $files ) ) {
        return;
    }

    // Get file objects from file IDs
    $file_objects = [];
    foreach ( $files as $file_id ) {
        $file_obj = get_post( $file_id );
        if ( $file_obj && 'attachment' === $file_obj->post_type ) {
            $file_objects[] = $file_obj;
        }
    }

    if ( empty( $file_objects ) ) {
        return;
    }

    // Group files by type
    $grouped_files = [
        'images' => [],
        'documents' => [],
        'videos' => [],
        'audio' => [],
        'archives' => [],
        'others' => []
    ];

    foreach ( $file_objects as $file ) {
        $file_type = get_post_mime_type( $file->ID );

        if ( strpos( $file_type, 'image/' ) === 0 ) {
            $grouped_files['images'][] = $file;
        } elseif ( in_array( $file_type, ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'text/plain'] ) ) {
            $grouped_files['documents'][] = $file;
        } elseif ( strpos( $file_type, 'video/' ) === 0 ) {
            $grouped_files['videos'][] = $file;
        } elseif ( strpos( $file_type, 'audio/' ) === 0 ) {
            $grouped_files['audio'][] = $file;
        } elseif ( in_array( $file_type, ['application/zip', 'application/x-rar-compressed', 'application/x-7z-compressed', 'application/x-tar', 'application/gzip'] ) ) {
            $grouped_files['archives'][] = $file;
        } else {
            $grouped_files['others'][] = $file;
        }
    }

    // Remove empty groups
    $grouped_files = array_filter( $grouped_files );

    if ( empty( $grouped_files ) ) {
        return;
    }

    // File type labels
    $type_labels = [
        'images' => __( 'Images', 'wpuf-pro' ),
        'documents' => __( 'Documents', 'wpuf-pro' ),
        'videos' => __( 'Videos', 'wpuf-pro' ),
        'audio' => __( 'Audio', 'wpuf-pro' ),
        'archives' => __( 'Archives', 'wpuf-pro' ),
        'others' => __( 'Others', 'wpuf-pro' )
    ];

    // File type icons (SVG)
    $type_icons = [
        'images' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" class="!wpuf-w-8 !wpuf-h-8" fill="currentColor"><path d="M64 32C28.7 32 0 60.7 0 96L0 416c0 35.3 28.7 64 64 64l320 0c35.3 0 64-28.7 64-64l0-320c0-35.3-28.7-64-64-64L64 32zm64 80a48 48 0 1 1 0 96 48 48 0 1 1 0-96zM272 224c8.4 0 16.1 4.4 20.5 11.5l88 144c4.5 7.4 4.7 16.7 .5 24.3S368.7 416 360 416L88 416c-8.9 0-17.2-5-21.3-12.9s-3.5-17.5 1.6-24.8l56-80c4.5-6.4 11.8-10.2 19.7-10.2s15.2 3.8 19.7 10.2l26.4 37.8 61.4-100.5c4.4-7.1 12.1-11.5 20.5-11.5z"/></svg>',
        'documents' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512" class="!wpuf-w-8 !wpuf-h-8" fill="currentColor"><path d="M64 0C28.7 0 0 28.7 0 64L0 448c0 35.3 28.7 64 64 64l256 0c35.3 0 64-28.7 64-64l0-277.5c0-17-6.7-33.3-18.7-45.3L258.7 18.7C246.7 6.7 230.5 0 213.5 0L64 0zM325.5 176L232 176c-13.3 0-24-10.7-24-24L208 58.5 325.5 176z"/></svg>',
        'videos' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="!wpuf-w-8 !wpuf-h-8" fill="currentColor"><path d="M0 256a256 256 0 1 1 512 0 256 256 0 1 1 -512 0zM188.3 147.1c-7.6 4.2-12.3 12.3-12.3 20.9l0 176c0 8.7 4.7 16.7 12.3 20.9s16.8 4.1 24.3-.5l144-88c7.1-4.4 11.5-12.1 11.5-20.5s-4.4-16.1-11.5-20.5l-144-88c-7.4-4.5-16.7-4.7-24.3-.5z"/></svg>',
        'audio' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512" class="!wpuf-w-8 !wpuf-h-8" fill="currentColor"><path d="M533.6 32.5c-10.3-8.4-25.4-6.8-33.8 3.5s-6.8 25.4 3.5 33.8C557.5 113.8 592 180.8 592 256s-34.5 142.2-88.7 186.3c-10.3 8.4-11.8 23.5-3.5 33.8s23.5 11.8 33.8 3.5C598.5 426.7 640 346.2 640 256S598.5 85.2 533.6 32.5zM473.1 107c-10.3-8.4-25.4-6.8-33.8 3.5s-6.8 25.4 3.5 33.8C475.3 170.7 496 210.9 496 256s-20.7 85.3-53.2 111.8c-10.3 8.4-11.8 23.5-3.5 33.8s23.5 11.8 33.8 3.5c43.2-35.2 70.9-88.9 70.9-149s-27.7-113.8-70.9-149zm-60.5 74.5c-10.3-8.4-25.4-6.8-33.8 3.5s-6.8 25.4 3.5 33.8C393.1 227.6 400 241 400 256s-6.9 28.4-17.7 37.3c-10.3 8.4-11.8 23.5-3.5 33.8s23.5 11.8 33.8 3.5C434.1 312.9 448 286.1 448 256s-13.9-56.9-35.4-74.5zM80 352l48 0 134.1 119.2c6.4 5.7 14.6 8.8 23.1 8.8 19.2 0 34.8-15.6 34.8-34.8l0-378.4c0-19.2-15.6-34.8-34.8-34.8-8.5 0-16.7 3.1-23.1 8.8L128 160 80 160c-26.5 0-48 21.5-48 48l0 96c0 26.5 21.5 48 48 48z"/></svg>',
        'archives' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" class="!wpuf-w-8 !wpuf-h-8" fill="currentColor"><path d="M56 225.6L32.4 296.2 32.4 96c0-35.3 28.7-64 64-64l138.7 0c13.8 0 27.3 4.5 38.4 12.8l38.4 28.8c5.5 4.2 12.3 6.4 19.2 6.4l117.3 0c35.3 0 64 28.7 64 64l0 16-365.4 0c-41.3 0-78 26.4-91.1 65.6zM477.8 448L99 448c-32.8 0-55.9-32.1-45.5-63.2l48-144C108 221.2 126.4 208 147 208l378.8 0c32.8 0 55.9 32.1 45.5 63.2l-48 144c-6.5 19.6-24.9 32.8-45.5 32.8z"/></svg>',
        'others' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" class="!wpuf-w-8 !wpuf-h-8" fill="currentColor"><path d="M56 225.6L32.4 296.2 32.4 96c0-35.3 28.7-64 64-64l138.7 0c13.8 0 27.3 4.5 38.4 12.8l38.4 28.8c5.5 4.2 12.3 6.4 19.2 6.4l117.3 0c35.3 0 64 28.7 64 64l0 16-365.4 0c-41.3 0-78 26.4-91.1 65.6zM477.8 448L99 448c-32.8 0-55.9-32.1-45.5-63.2l48-144C108 221.2 126.4 208 147 208l378.8 0c32.8 0 55.9 32.1 45.5 63.2l-48 144c-6.5 19.6-24.9 32.8-45.5 32.8z"/></svg>'
    ];

    // Simple gray styling for tabs
    $badge_bg = '!wpuf-bg-gray-100';

    ?>
    <div class="wpuf-profile-section wpuf-files-section !wpuf-mb-16">
        <!-- File Type Tabs -->
        <div class="wpuf-file-tabs !wpuf-mb-6">
            <div class="wpuf-tab-nav !wpuf-flex !wpuf-flex-wrap !wpuf-gap-3 !wpuf-border-b !wpuf-border-gray-200">
                <?php
                $first_tab = true;
                foreach ( $grouped_files as $type => $type_files ) :
                    $count = count( $type_files );
                ?>
                    <button class="wpuf-file-tab-btn !wpuf-flex !wpuf-items-center !wpuf-gap-2 !wpuf-px-3 !wpuf-py-2 !wpuf-text-sm !wpuf-font-medium !wpuf-border-b-2 !wpuf-transition-all !wpuf-bg-transparent !wpuf-cursor-pointer <?php echo $first_tab ? 'wpuf-file-tab-active' : ''; ?>"
                            data-tab="<?php echo esc_attr( $type ); ?>"
                            <?php echo $first_tab ? 'data-active="true"' : ''; ?>>
                        <span class="!wpuf-flex-shrink-0"><?php echo str_replace('!wpuf-w-8 !wpuf-h-8', '!wpuf-w-4 !wpuf-h-4', $type_icons[$type]); ?></span>
                        <span class="!wpuf-flex-shrink-0"><?php echo esc_html( $type_labels[$type] ); ?></span>
                        <span class="!wpuf-px-1.5 !wpuf-py-0.5 <?php echo esc_attr( $badge_bg ); ?> !wpuf-rounded-full !wpuf-text-xs !wpuf-leading-none">
                            <?php echo esc_html( $count ); ?>
                        </span>
                    </button>
                <?php
                    $first_tab = false;
                endforeach;
                ?>
            </div>
        </div>

        <!-- File Groups -->
        <?php
        $first_group = true;
        foreach ( $grouped_files as $type => $type_files ) :
        ?>
            <div class="wpuf-file-group" data-type="<?php echo esc_attr( $type ); ?>"
                 style="<?php echo ! $first_group ? 'display: none;' : ''; ?>">

                <div class="files-grid !wpuf-grid !wpuf-grid-cols-2 sm:!wpuf-grid-cols-3 md:!wpuf-grid-cols-4 lg:!wpuf-grid-cols-5 xl:!wpuf-grid-cols-6 !wpuf-gap-4">
                    <?php foreach ( $type_files as $file ) : ?>
                        <?php
                        $file_url = wp_get_attachment_url( $file->ID );
                        $file_type = get_post_mime_type( $file->ID );
                        $file_extension = strtoupper( pathinfo( $file_url, PATHINFO_EXTENSION ) );
                        $is_image = strpos( $file_type, 'image/' ) === 0;
                        $is_pdf = $file_type === 'application/pdf';

                        // Get appropriate icon/label for the file type
                        $display_icon = $type_icons[$type];
                        $display_label = $file_extension ?: strtoupper( $type );

                        if ( $is_image ) {
                            $display_label = 'IMAGE';
                        } elseif ( $is_pdf ) {
                            $display_label = 'PDF';
                        }
                        ?>

                        <div class="file-item !wpuf-relative !wpuf-group">
                            <a href="<?php echo esc_url( $file_url ); ?>" target="_blank" class="!wpuf-block">
                                <?php if ( $is_image ) : ?>
                                    <?php
                                    // For images, show actual thumbnail using dynamic gallery image size
                                    $image_size = 'thumbnail'; // Default
                                    if ( ! empty( $template_data['gallery_img_size'] ) ) {
                                        // Check if it's a valid WordPress image size
                                        $available_sizes = get_intermediate_image_sizes();
                                        $available_sizes[] = 'full';

                                        if ( in_array( $template_data['gallery_img_size'], $available_sizes ) ) {
                                            $image_size = $template_data['gallery_img_size'];
                                        } elseif ( is_numeric( $template_data['gallery_img_size'] ) ) {
                                            // If it's a number, use it as custom size array
                                            $size_value = intval( $template_data['gallery_img_size'] );
                                            $image_size = array( $size_value, $size_value );
                                        }
                                    }
                                    $image_thumb = wp_get_attachment_image_src( $file->ID, $image_size );
                                    ?>
                                    <div class="file-preview !wpuf-w-full !wpuf-rounded-lg !wpuf-overflow-hidden !wpuf-transition-all !wpuf-duration-200 group-hover:!wpuf-scale-105">
                                        <?php if ( $image_thumb ) : ?>
                                            <img src="<?php echo esc_url( $image_thumb[0] ); ?>" alt="<?php echo esc_attr( $file->post_title ); ?>" class="!wpuf-w-full !wpuf-object-cover">
                                        <?php else : ?>
                                            <!-- Fallback to icon if image thumb fails -->
                                            <div class="!wpuf-w-full !wpuf-h-28 !wpuf-bg-gray-700 !wpuf-rounded-lg !wpuf-flex !wpuf-flex-col !wpuf-items-center !wpuf-justify-center !wpuf-text-white !wpuf-font-bold !wpuf-text-sm hover:!wpuf-bg-gray-500">
                                                <div class="!wpuf-text-2xl !wpuf-mb-1"><?php echo $display_icon; ?></div>
                                                <span><?php echo esc_html( $display_label ); ?></span>
                                            </div>
                                        <?php endif; ?>
                                    </div>
                                <?php else : ?>
                                    <!-- For non-images, show icon as before -->
                                    <div class="file-preview !wpuf-w-full !wpuf-h-28 !wpuf-bg-gray-700 !wpuf-rounded-lg !wpuf-flex !wpuf-flex-col !wpuf-items-center !wpuf-justify-center !wpuf-text-white !wpuf-font-bold !wpuf-text-sm hover:!wpuf-bg-gray-500 !wpuf-transition-all !wpuf-duration-200 group-hover:!wpuf-scale-105">
                                        <div class="!wpuf-text-2xl !wpuf-mb-1"><?php echo $display_icon; ?></div>
                                        <span><?php echo esc_html( $display_label ); ?></span>
                                    </div>
                                <?php endif; ?>
                                <div class="file-info !wpuf-mt-2">
                                    <div class="file-name !wpuf-text-xs !wpuf-text-gray-700 !wpuf-text-center !wpuf-truncate !wpuf-font-medium">
                                        <?php
                                            // Get the proper filename with extension from the attachment
                                            $file_name = basename( $file_url );
                                            if ( empty( $file_name ) ) {
                                                $file_name = $file->post_title ?: 'Untitled';
                                            }
                                            echo esc_html( \WPUF\UserDirectory\FileHelper::format_filename_with_extension( $file_name ) );
                                        ?>
                                    </div>
                                </div>
                            </a>
                        </div>
                    <?php endforeach; ?>
                </div>
            </div>
        <?php
            $first_group = false;
        endforeach;
        ?>
    </div>


    <?php
}

/**
 * Validate uploaded file for avatar upload
 *
 * @since 4.2.3
 *
 * @param array $file Uploaded file array
 * @return array Validation result with 'valid' boolean and 'message' string
 */
function wpuf_ud_validate_uploaded_file( $file ) {
    // Use the unified validation function
    if ( function_exists( 'wpuf_validate_uploaded_profile_photo' ) ) {
        return wpuf_validate_uploaded_profile_photo( $file, 5 * 1024 * 1024 ); // 5MB for user directory
    }

    // Fallback to original validation if the function doesn't exist
    // Check file size (5MB max)
    $max_size = 5 * 1024 * 1024; // 5MB
    if ( $file['size'] > $max_size ) {
        return [
            'valid' => false,
            'message' => __( 'File size must be less than 5MB.', 'wpuf-pro' )
        ];
    }

    // Check file type using the existing function
    $file_type = wp_check_filetype( $file['name'] );

    // Use the existing allowed extensions function if available
    if ( function_exists( 'wpuf_field_profile_photo_allowed_extensions' ) ) {
        $allowed_extensions = wpuf_field_profile_photo_allowed_extensions();

        /**
         * Filter the allowed file extensions for user directory avatar uploads
         *
         * @since 4.2.3
         *
         * @param array $allowed_extensions Array of allowed file extensions
         * @param array $file Uploaded file data
         */
        $allowed_extensions = apply_filters( 'wpuf_ud_avatar_allowed_extensions', $allowed_extensions, $file );

        $file_extension = strtolower( pathinfo( $file['name'], PATHINFO_EXTENSION ) );

        if ( ! in_array( $file_extension, array_keys( $allowed_extensions ), true ) ) {
            return [
                'valid' => false,
                'message' => __( 'File type not allowed.', 'wpuf-pro' )
            ];
        }
    } else {
        // Fallback to basic validation
        $allowed_types = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp'];

        if ( ! in_array( $file_type['type'], $allowed_types, true ) ) {
            return [
                'valid' => false,
                'message' => __( 'Only JPG, PNG, GIF, and WebP images are allowed.', 'wpuf-pro' )
            ];
        }
    }

    // Additional security check using getimagesize
    $image_info = getimagesize( $file['tmp_name'] );
    if ( ! $image_info ) {
        return [
            'valid' => false,
            'message' => __( 'Invalid image file.', 'wpuf-pro' )
        ];
    }

    return ['valid' => true];
}

/**
 * Process avatar upload and create WordPress attachment
 *
 * @since 4.2.3
 *
 * @param array $file Uploaded file array
 * @param int $user_id User ID
 * @return array|WP_Error Upload result with attachment_id and avatar_url
 */
function wpuf_ud_process_avatar_upload( $file, $user_id ) {
    // Handle WordPress upload
    $upload = wp_handle_upload( $file, [
        'test_form' => false,
        'test_size' => false, // We already validated size
        'test_type' => false, // We already validated type
    ] );

    if ( isset( $upload['error'] ) ) {
        return new \WP_Error( 'upload_error', $upload['error'] );
    }

    // Create attachment
    $attachment_id = wpuf_ud_create_avatar_attachment( $upload, $user_id );

    if ( is_wp_error( $attachment_id ) ) {
        return $attachment_id;
    }

    // Generate multiple sizes
    // wpuf_ud_generate_avatar_sizes( $attachment_id );

    // Remove old avatar before setting new one
    wpuf_ud_remove_old_avatar( $user_id );

    // Use the unified profile photo processing function
    if ( function_exists( 'wpuf_process_profile_photo_attachment' ) ) {
        $result = wpuf_process_profile_photo_attachment( $attachment_id, $user_id, 'wpuf_profile_photo', 5 * 1024 * 1024 ); // 5MB for user directory

        if ( ! $result['success'] ) {
            return new \WP_Error( 'processing_error', $result['message'] );
        }
    } else {
        // Fallback to direct user meta update
        update_user_meta( $user_id, 'wpuf_profile_photo', $attachment_id );
    }

    // Get avatar URL
    $avatar_url = wp_get_attachment_url( $attachment_id );

    return [
        'attachment_id' => $attachment_id,
        'avatar_url'    => $avatar_url,
    ];
}

/**
 * Create WordPress attachment for avatar
 *
 * @since 4.2.3
 *
 * @param array $upload Upload data
 * @param int $user_id User ID
 * @return int|WP_Error Attachment ID or error
 */
function wpuf_ud_create_avatar_attachment( $upload, $user_id ) {
    // Detect MIME type if not provided by wp_handle_upload
    $mime_type = $upload['type'];
    if ( empty( $mime_type ) ) {
        $file_type = wp_check_filetype( $upload['file'] );
        $mime_type = $file_type['type'];
    }

    // Prepare attachment data
    $attachment_data = [
        'post_mime_type' => $mime_type,
        'post_title' => sprintf( __( 'Profile Photo for %s', 'wpuf-pro' ), get_userdata( $user_id )->display_name ),
        'post_content' => '',
        'post_status' => 'inherit',
        'post_author' => $user_id,
        'post_parent' => 0,
    ];

    // Insert attachment
    $attachment_id = wp_insert_attachment( $attachment_data, $upload['file'] );

    if ( is_wp_error( $attachment_id ) ) {
        return $attachment_id;
    }

    // Generate attachment metadata
    require_once( ABSPATH . 'wp-admin/includes/image.php' );
    $attachment_metadata = wp_generate_attachment_metadata( $attachment_id, $upload['file'] );
    wp_update_attachment_metadata( $attachment_id, $attachment_metadata );

    return $attachment_id;
}

/**
 * Generate avatar-specific image sizes
 *
 * @since 4.2.3
 *
 * @param int $attachment_id Attachment ID
 */
function wpuf_ud_generate_avatar_sizes( $attachment_id ) {
    $file_path = get_attached_file( $attachment_id );
    if ( ! $file_path || ! file_exists( $file_path ) ) {
        return;
    }

    // Define avatar sizes
    $avatar_sizes = [
        'wpuf-avatar-thumbnail' => [32, 32, true],
        'wpuf-avatar-small' => [64, 64, true],
        'wpuf-avatar-medium' => [150, 150, true],
        'wpuf-avatar-large' => [300, 300, true],
    ];

    // Add avatar sizes to WordPress
    foreach ( $avatar_sizes as $size_name => $size_data ) {
        add_image_size( $size_name, $size_data[0], $size_data[1], $size_data[2] );
    }

    // Regenerate thumbnails for avatar sizes
    wpuf_ud_regenerate_avatar_thumbnails( $attachment_id, $file_path, $avatar_sizes );
}

/**
 * Regenerate thumbnails for avatar sizes
 *
 * @since 4.2.3
 *
 * @param int $attachment_id Attachment ID
 * @param string $file_path File path
 * @param array $avatar_sizes Avatar sizes
 */
function wpuf_ud_regenerate_avatar_thumbnails( $attachment_id, $file_path, $avatar_sizes ) {
    $editor = wp_get_image_editor( $file_path );
    if ( is_wp_error( $editor ) ) {
        return;
    }

    $metadata = wp_get_attachment_metadata( $attachment_id );
    if ( ! $metadata ) {
        $metadata = [];
    }

    if ( ! isset( $metadata['sizes'] ) ) {
        $metadata['sizes'] = [];
    }

    foreach ( $avatar_sizes as $size_name => $size_data ) {
        $resized = $editor->resize( $size_data[0], $size_data[1], $size_data[2] );
        if ( ! is_wp_error( $resized ) ) {
            $saved = $editor->save();
            if ( ! is_wp_error( $saved ) ) {
                $metadata['sizes'][$size_name] = [
                    'file' => basename( $saved['path'] ),
                    'width' => $saved['width'],
                    'height' => $saved['height'],
                    'mime-type' => $saved['mime-type']
                ];
            }
        }
    }

    wp_update_attachment_metadata( $attachment_id, $metadata );
}

/**
 * Remove old avatar when new one is uploaded
 *
 * @since 4.2.3
 *
 * @param int $user_id User ID
 */
function wpuf_ud_remove_old_avatar( $user_id ) {
    $old_attachment_id = get_user_meta( $user_id, 'wpuf_profile_photo', true );

    if ( $old_attachment_id && is_numeric( $old_attachment_id ) ) {
        // Check if attachment exists and belongs to this user
        $attachment = get_post( $old_attachment_id );
        if ( $attachment && $attachment->post_author == $user_id ) {
            wp_delete_attachment( $old_attachment_id, true );
        }
    }
}

/**
 * Get custom cover photo URL from usermeta
 *
 * @param int $user_id User ID
 * @param int $size Requested size (width for cover photos)
 * @return string|false Custom cover photo URL or false if not found
 * @since 4.2.0
 */
function wpuf_ud_get_custom_cover_photo_url( $user_id, $size = 800 ) {
    $attachment_id = get_user_meta( $user_id, 'wpuf_cover_photo', true );

    if ( ! $attachment_id || ! is_numeric( $attachment_id ) ) {
        return false;
    }

    // Check if attachment exists
    $attachment = get_post( $attachment_id );
    if ( ! $attachment || 'attachment' !== $attachment->post_type ) {
        return false;
    }

    // Get the image URL directly
    $image_url = wp_get_attachment_image_url( $attachment_id, 'full' );
    if ( ! $image_url ) {
        return false;
    }

    // For cover photos, we typically use the full size or large size
    // But we can try to get an appropriate size if needed
    if ( $size && $size !== 'full' ) {
        // Get attachment metadata to find available sizes
        $metadata = wp_get_attachment_metadata( $attachment_id );
        if ( $metadata && isset( $metadata['sizes'] ) && is_array( $metadata['sizes'] ) ) {
            // Find the best size for cover photos (prefer larger sizes)
            $best_size = null;
            $best_width = 0;

            // Priority sizes for cover photos
            $priority_sizes = ['large', 'medium_large', 'medium', 'thumbnail'];

            // First try priority sizes
            foreach ( $priority_sizes as $size_name ) {
                if ( isset( $metadata['sizes'][$size_name] ) ) {
                    $size_data = $metadata['sizes'][$size_name];
                    if ( $size_data['width'] >= $size || $size_data['width'] > $best_width ) {
                        $best_size = $size_name;
                        $best_width = $size_data['width'];
                    }
                }
            }

            // If no priority size fits, find the closest larger size
            if ( ! $best_size ) {
                foreach ( $metadata['sizes'] as $size_name => $size_data ) {
                    if ( $size_data['width'] >= $size && $size_data['width'] > $best_width ) {
                        $best_size = $size_name;
                        $best_width = $size_data['width'];
                    }
                }
            }

            // If still no size found, use the largest available
            if ( ! $best_size ) {
                foreach ( $metadata['sizes'] as $size_name => $size_data ) {
                    if ( $size_data['width'] > $best_width ) {
                        $best_size = $size_name;
                        $best_width = $size_data['width'];
                    }
                }
            }

            if ( $best_size ) {
                $sized_url = wp_get_attachment_image_url( $attachment_id, $best_size );
                if ( $sized_url ) {
                    return $sized_url;
                }
            }
        }
    }

    return $image_url;
}

/**
 * Get block cover photo data
 *
 * @param WP_User $user User object
 * @param int $width Width in pixels
 * @return array Cover photo data with URL and metadata
 * @since 4.2.0
 */
function wpuf_ud_get_block_cover_photo_data( $user, $width = 800 ) {
    // Get custom cover photo URL
    $cover_photo_url = wpuf_ud_get_custom_cover_photo_url( $user->ID, $width );

    if ( $cover_photo_url ) {
        return [
            'url' => $cover_photo_url,
            'has_cover_photo' => true,
            'alt' => sprintf( __( 'Cover photo of %s', 'wpuf-pro' ), $user->display_name ),
            'type' => 'custom'
        ];
    }

    // No cover photo found
    return [
        'url' => false,
        'has_cover_photo' => false,
        'alt' => sprintf( __( 'Cover photo of %s', 'wpuf-pro' ), $user->display_name ),
        'type' => 'none'
    ];
}

/**
 * Process cover photo upload
 *
 * @since 4.2.3
 *
 * @param array $file Uploaded file data
 * @param int $user_id User ID
 * @param array $config Optional configuration
 * @return array|WP_Error Upload result or error
 */
function wpuf_ud_process_cover_photo_upload( $file, $user_id, $config = [] ) {
	// Handle WordPress upload
	$upload = wp_handle_upload(
		$file,
		[
			'test_form' => false,
			'test_size' => false, // We already validated size
			'test_type' => false, // We already validated type
		]
	);

	if ( isset( $upload['error'] ) ) {
		return new \WP_Error( 'upload_error', $upload['error'] );
	}

	// Create attachment
	$attachment_id = wpuf_ud_create_cover_photo_attachment( $upload, $user_id );

	if ( is_wp_error( $attachment_id ) ) {
		return $attachment_id;
	}

	// Remove old cover photo before setting new one
	wpuf_ud_remove_old_cover_photo( $user_id );

	// Use the unified profile photo processing function if available
	if ( function_exists( 'wpuf_process_profile_photo_attachment' ) ) {
		$result = wpuf_process_profile_photo_attachment( $attachment_id, $user_id, 'wpuf_cover_photo', 10 * 1024 * 1024 ); // 10MB for cover photos

		if ( ! $result['success'] ) {
			return new \WP_Error( 'processing_error', $result['message'] );
		}
	} else {
		// Fallback to direct user meta update
		update_user_meta( $user_id, 'wpuf_cover_photo', $attachment_id );
	}

	// Get cover photo URL
	$cover_photo_url = wp_get_attachment_url( $attachment_id );

	return [
		'attachment_id' => $attachment_id,
		'image_url'     => $cover_photo_url,
	];
}

/**
 * Create WordPress attachment for cover photo
 *
 * @since 4.2.3
 *
 * @param array $upload Upload data
 * @param int $user_id User ID
 * @return int|WP_Error Attachment ID or error
 */
function wpuf_ud_create_cover_photo_attachment( $upload, $user_id ) {
	// Validate user exists
	$user = get_userdata( $user_id );
	if ( ! $user ) {
		return new \WP_Error( 'invalid_user', __( 'Invalid user ID.', 'wpuf-pro' ) );
	}

	// Detect MIME type if not provided by wp_handle_upload
	$mime_type = $upload['type'];
	if ( empty( $mime_type ) ) {
		$file_type = wp_check_filetype( $upload['file'] );
		$mime_type = $file_type['type'];
	}

	// Prepare attachment data
	$attachment_data = [
		'post_mime_type' => $mime_type,
		'post_title'     => sprintf( __( 'Cover Photo for %s', 'wpuf-pro' ), $user->display_name ),
		'post_content'   => '',
		'post_status'    => 'inherit',
		'post_author'    => $user_id,
		'post_parent'    => 0,
	];

	// Insert attachment
	$attachment_id = wp_insert_attachment( $attachment_data, $upload['file'] );

	if ( is_wp_error( $attachment_id ) ) {
		return $attachment_id;
	}

	// Generate attachment metadata
	require_once( ABSPATH . 'wp-admin/includes/image.php' );
	$attachment_metadata = wp_generate_attachment_metadata( $attachment_id, $upload['file'] );
	wp_update_attachment_metadata( $attachment_id, $attachment_metadata );

	return $attachment_id;
}

/**
 * Remove old cover photo attachment
 *
 * @since 4.2.3
 *
 * @param int $user_id User ID
 */
function wpuf_ud_remove_old_cover_photo( $user_id ) {
	$old_attachment_id = get_user_meta( $user_id, 'wpuf_cover_photo', true );

	if ( $old_attachment_id && is_numeric( $old_attachment_id ) ) {
		wp_delete_attachment( $old_attachment_id, true );
	}

	delete_user_meta( $user_id, 'wpuf_cover_photo' );
}
