<?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Shortcode: [stakmv-browse-listings]
 * Public-facing product browsing with filters and AJAX.
 */
function stakmv_render_browse_listings_shortcode() {
		ob_start();

		$browse_args = stakmv_get_browse_query_args_from_request();
		$browse_heading = (string) get_option( 'stakmv_browse_heading', 'Browse Listing' );
		$browse_subheading = (string) get_option( 'stakmv_browse_subheading', 'choose from several items' );
		$browse_heading = '' !== trim( $browse_heading ) ? $browse_heading : 'Browse Listing';
		$browse_subheading = '' !== trim( $browse_subheading ) ? $browse_subheading : 'choose from several items';
		$request_get  = stakmv_get_sanitized_browse_request_query();
		$current_view = isset( $request_get['view'] ) ? sanitize_key( (string) $request_get['view'] ) : 'grid';
		if ( ! in_array( $current_view, array( 'grid', 'list' ), true ) ) {
			$current_view = 'grid';
		}
		$current_search = isset( $request_get['search'] ) ? sanitize_text_field( (string) $request_get['search'] ) : '';
		$current_cat    = isset( $request_get['cat'] ) ? (int) $request_get['cat'] : 0;
		$current_types  = array();
		if ( isset( $request_get['type'] ) && is_array( $request_get['type'] ) ) {
			$current_types = array_map( 'sanitize_key', $request_get['type'] );
		}
		$current_mobile_type = isset( $request_get['mobile_type'] ) ? sanitize_key( (string) $request_get['mobile_type'] ) : '';
		if ( ! in_array( $current_mobile_type, array( 'all', 'auction', 'buy_now' ), true ) ) {
			$current_mobile_type = '';
		}
		if ( 'auction' === $current_mobile_type ) {
			$current_types = array( 'auction' );
		} elseif ( 'buy_now' === $current_mobile_type ) {
			$current_types = array( 'buy_now' );
		} elseif ( 'all' === $current_mobile_type ) {
			$current_types = array();
		}
		$current_min_price = isset( $request_get['min_price'] ) ? sanitize_text_field( (string) $request_get['min_price'] ) : '';
		$current_max_price = isset( $request_get['max_price'] ) ? sanitize_text_field( (string) $request_get['max_price'] ) : '';

	?>




<div id="wcmv-browse-root" class="wcmv-browse-page">

  <!-- Header -->
  <header class="wcmv-header">
    <h1 class="carnival-text"><?php echo esc_html( $browse_heading ); ?></h1>
    <p><?php echo esc_html( $browse_subheading ); ?></p>
  </header>

  <!-- Search & Filters Card -->
  <div class="wcmv-search-card">
    <form id="wcmv-filter-form" method="get">
      <input type="hidden" name="paged" id="wcmv-paged" value="1">
	      <input type="hidden" name="view" id="wcmv-view" value="<?php echo esc_attr( $current_view ); ?>">
      <input type="hidden" name="mobile_type" id="wcmv-mobile-type" value="<?php echo esc_attr( $current_mobile_type ); ?>">

      <!-- Search Row -->
      <div class="wcmv-search-row">
        <div class="wcmv-search-input">
          <span class="icon">🔍</span>
	          <input type="text" name="search" placeholder="Search for items..." value="<?php echo esc_attr( $current_search ); ?>">
        </div>
        <button type="submit" class="wcmv-search-btn">Search</button>
		<?php do_action( 'stakmv_browse_search_actions' ); ?>
      </div>

      <div class="wcmv-mobile-toolbar">
        <div class="wcmv-mobile-type-tabs" role="tablist" aria-label="<?php esc_attr_e( 'Listing type', 'stak-multivendor' ); ?>">
          <?php
          $mobile_mode = 'all';
          if ( '' !== $current_mobile_type ) {
            $mobile_mode = $current_mobile_type;
          } elseif ( in_array( 'buy_now', $current_types, true ) && ! in_array( 'auction', $current_types, true ) ) {
            $mobile_mode = 'buy_now';
          } elseif ( in_array( 'auction', $current_types, true ) && ! in_array( 'buy_now', $current_types, true ) ) {
            $mobile_mode = 'auction';
          }
          ?>
          <button type="button" class="wcmv-mobile-type-tab<?php echo 'all' === $mobile_mode ? ' is-active' : ''; ?>" data-mobile-type="all">All</button>
          <button type="button" class="wcmv-mobile-type-tab<?php echo 'auction' === $mobile_mode ? ' is-active' : ''; ?>" data-mobile-type="auction">Auction</button>
          <button type="button" class="wcmv-mobile-type-tab<?php echo 'buy_now' === $mobile_mode ? ' is-active' : ''; ?>" data-mobile-type="buy_now">Buy it now</button>
        </div>
        <button type="button" class="wcmv-mobile-filter-toggle" aria-expanded="false">Filter</button>
      </div>

      <!-- Filters Row -->
      <div class="wcmv-filters-row">

        <!-- Category -->
        <div class="wcmv-filter-group">
          <span class="icon">⚲</span>
          <select name="cat">
            <option value="">All Categories</option>
            <?php foreach ( get_terms(['taxonomy'=>'product_cat','hide_empty'=>true]) as $cat ) : ?>
	              <option value="<?php echo esc_attr($cat->term_id); ?>" <?php selected( $current_cat, (int) $cat->term_id ); ?>>
                <?php echo esc_html($cat->name); ?>
              </option>
            <?php endforeach; ?>
          </select>
        </div>

        <!-- Buy Now -->
        <label class="wcmv-checkbox">
	          <input type="checkbox" name="type[]" value="buy_now" <?php checked( in_array( 'buy_now', $current_types, true ) ); ?>>
          <span>Buy Now Only</span>
        </label>
        <input type="checkbox" name="type[]" value="auction" class="wcmv-auction-only-toggle" <?php checked( in_array( 'auction', $current_types, true ) ); ?> hidden>

        <!-- View Toggle -->
	        <?php $view_mode = $current_view; ?>
        <div class="wcmv-view-toggle">
          <button type="button" data-view="grid" class="<?php echo $view_mode === 'grid' ? 'active' : ''; ?>">▦</button>
          <button type="button" data-view="list" class="<?php echo $view_mode === 'list' ? 'active' : ''; ?>">☰</button>
        </div>

       <div class="wcmv-filter-group wcmv-filter-price">
  <label class="wcmv-filter-price-label">Price</label>

  <div class="wcmv-price-fields">
    <input
      type="number"
      name="min_price"
      id="min_price"
      placeholder="Min"
      min="0"
	      value="<?php echo esc_attr( $current_min_price ); ?>"
     
    />

    <input
      type="number"
      name="max_price"
      id="max_price"
      placeholder="Max"
      min="0"
	      value="<?php echo esc_attr( $current_max_price ); ?>"
     
    />
  </div>
</div>

      <?php do_action( 'stakmv_browse_filter_actions' ); ?>


    </form>
  </div>

  <!-- Results Count -->
  <div class="wcmv-results-meta">
    <span class="wcmv-count"></span>
  </div>

  <!-- Results -->
  <section class="wcmv-results">
    <?php echo wp_kses_post( stakmv_render_products( $browse_args ) ); ?>
  </section>

</div>
<?php
return ob_get_clean();

	}

add_shortcode('stakmv-browse-listings', 'stakmv_render_browse_listings_shortcode');

/**
 * Render sidebar filters.
 */
function stakmv_render_filters() {
	$cats = get_terms(
		array(
			'taxonomy'   => 'product_cat',
			'hide_empty' => true,
		)
	);
	?>
	<form id="wcmv-filter-form">
		<?php wp_nonce_field( 'stakmv_filter', 'stakmv_filter_nonce' ); ?>
		<h4><?php esc_html_e( 'Listing Type', 'stak-multivendor' ); ?></h4>
		<label><input type="checkbox" name="type[]" value="auction"> <?php esc_html_e( 'Auction', 'stak-multivendor' ); ?></label>
		<label><input type="checkbox" name="type[]" value="buy_now"> <?php esc_html_e( 'Buy Now', 'stak-multivendor' ); ?></label>

		<h4><?php esc_html_e( 'Price', 'stak-multivendor' ); ?></h4>
		<div id="wcmv-price-slider"></div>
		<div class="wcmv-price-values">
			<span><?php esc_html_e( 'Min:', 'stak-multivendor' ); ?> <strong id="wcmv-min-price">0</strong></span>
			<span><?php esc_html_e( 'Max:', 'stak-multivendor' ); ?> <strong id="wcmv-max-price">500,000</strong></span>
		</div>
		<input type="hidden" name="min_price" id="min_price">
		<input type="hidden" name="max_price" id="max_price">

		<?php if ( ! is_wp_error( $cats ) && ! empty( $cats ) ) : ?>
			<h4><?php esc_html_e( 'Categories', 'stak-multivendor' ); ?></h4>
			<?php foreach ( $cats as $cat ) : ?>
				<label>
					<input type="checkbox" name="cat[]" value="<?php echo esc_attr( $cat->term_id ); ?>">
					<?php echo esc_html( $cat->name ); ?>
				</label>
			<?php endforeach; ?>
		<?php endif; ?>

		<?php
		// Build attribute filters. If on a product category archive and a category mapping exists,
		// restrict filters to the mapped attributes for that category. Otherwise, show all attributes.
		$taxonomies         = wc_get_attribute_taxonomies();
		$allowed_taxonomies = array();
		if ( is_tax( 'product_cat' ) ) {
			$current_cat_id     = get_queried_object_id();
			$allowed_taxonomies = (array) get_term_meta( $current_cat_id, 'stakmv_cat_attrs', true );
		}

		if ( ! empty( $taxonomies ) ) {
			foreach ( $taxonomies as $attr ) {
				$tax = 'pa_' . $attr->attribute_name;

				// If a mapping exists, skip attributes not in the allowed list.
				if ( ! empty( $allowed_taxonomies ) && ! in_array( $tax, $allowed_taxonomies, true ) ) {
					continue;
				}

				$terms = get_terms(
					array(
						'taxonomy'   => $tax,
						'hide_empty' => true,
					)
				);
				if ( is_wp_error( $terms ) || empty( $terms ) ) {
					continue;
				}

				echo '<h4>' . esc_html( $attr->attribute_label ) . '</h4>';
				foreach ( $terms as $t ) {
					echo '<label>
						<input type="checkbox" name="attr[' . esc_attr( $tax ) . '][]" value="' . esc_attr( $t->slug ) . '">
						' . esc_html( $t->name ) . '
					</label>';
				}
			}
		}
		?>

		<button type="submit" class="button button-primary"><?php esc_html_e( 'Apply Filters', 'stak-multivendor' ); ?></button>
	</form>
	<?php
}

/**
 * Resolve browse shipping destination.
 *
 * Priority:
 * 1) Logged-in buyer account shipping/billing fields.
 * 2) WooCommerce customer session fields.
 * 3) IP geolocation (WooCommerce geolocation).
 *
 * @return array {
 *   @type string address_1
 *   @type string address_2
 *   @type string city
 *   @type string state
 *   @type string postcode
 *   @type string country
 *   @type string source account|session|ip|unknown
 * }
 */
function stakmv_browse_get_destination_context() {
	$dest = array(
		'address_1' => '',
		'address_2' => '',
		'city'      => '',
		'state'     => '',
		'postcode'  => '',
		'country'   => '',
		'source'    => 'unknown',
	);

	if ( is_user_logged_in() ) {
		$user_id = get_current_user_id();

		$dest['address_1'] = trim( (string) get_user_meta( $user_id, 'shipping_address_1', true ) );
		$dest['address_2'] = trim( (string) get_user_meta( $user_id, 'shipping_address_2', true ) );
		$dest['city']      = trim( (string) get_user_meta( $user_id, 'shipping_city', true ) );
		$dest['state']     = trim( (string) get_user_meta( $user_id, 'shipping_state', true ) );
		$dest['postcode']  = trim( (string) get_user_meta( $user_id, 'shipping_postcode', true ) );
		$dest['country']   = strtoupper( trim( (string) get_user_meta( $user_id, 'shipping_country', true ) ) );

		// Fill blanks from billing profile fields.
		if ( '' === $dest['address_1'] ) {
			$dest['address_1'] = trim( (string) get_user_meta( $user_id, 'billing_address_1', true ) );
		}
		if ( '' === $dest['address_2'] ) {
			$dest['address_2'] = trim( (string) get_user_meta( $user_id, 'billing_address_2', true ) );
		}
		if ( '' === $dest['city'] ) {
			$dest['city'] = trim( (string) get_user_meta( $user_id, 'billing_city', true ) );
		}
		if ( '' === $dest['state'] ) {
			$dest['state'] = trim( (string) get_user_meta( $user_id, 'billing_state', true ) );
		}
		if ( '' === $dest['postcode'] ) {
			$dest['postcode'] = trim( (string) get_user_meta( $user_id, 'billing_postcode', true ) );
		}
		if ( '' === $dest['country'] ) {
			$dest['country'] = strtoupper( trim( (string) get_user_meta( $user_id, 'billing_country', true ) ) );
		}

		if ( '' !== $dest['country'] && '' !== $dest['postcode'] ) {
			$dest['source'] = 'account';
			return $dest;
		}
	}

	// Fill from WooCommerce customer runtime/session if available.
	if ( function_exists( 'WC' ) && WC() && WC()->customer ) {
		$customer = WC()->customer;

		$session_fields = array(
			'address_1' => array( 'get_shipping_address_1', 'get_billing_address_1' ),
			'address_2' => array( 'get_shipping_address_2', 'get_billing_address_2' ),
			'city'      => array( 'get_shipping_city', 'get_billing_city' ),
			'state'     => array( 'get_shipping_state', 'get_billing_state' ),
			'postcode'  => array( 'get_shipping_postcode', 'get_billing_postcode' ),
			'country'   => array( 'get_shipping_country', 'get_billing_country' ),
		);

		foreach ( $session_fields as $dest_key => $getters ) {
			if ( '' !== $dest[ $dest_key ] ) {
				continue;
			}

			foreach ( $getters as $getter ) {
				if ( is_callable( array( $customer, $getter ) ) ) {
					$value = trim( (string) $customer->{$getter}() );
					if ( '' !== $value ) {
						$dest[ $dest_key ] = ( 'country' === $dest_key ) ? strtoupper( $value ) : $value;
						break;
					}
				}
			}
		}

		if ( '' !== $dest['country'] && '' !== $dest['postcode'] ) {
			$dest['source'] = 'session';
			return $dest;
		}
	}

	// IP-based fallback.
	if ( class_exists( 'WC_Geolocation' ) ) {
		$geo = WC_Geolocation::geolocate_ip( '', true, false );
		if ( ! is_array( $geo ) || ( empty( $geo['country'] ) && empty( $geo['country_code'] ) ) ) {
			$geo = WC_Geolocation::geolocate_ip();
		}

		if ( is_array( $geo ) ) {
			if ( '' === $dest['city'] ) {
				$dest['city'] = trim( (string) ( $geo['city'] ?? '' ) );
			}
			if ( '' === $dest['state'] ) {
				$dest['state'] = trim( (string) ( $geo['state'] ?? '' ) );
			}
			if ( '' === $dest['postcode'] ) {
				$dest['postcode'] = trim( (string) ( $geo['postcode'] ?? '' ) );
			}
			if ( '' === $dest['country'] ) {
				$dest['country'] = strtoupper(
					trim(
						(string) ( $geo['country'] ?? ( $geo['country_code'] ?? '' ) )
					)
				);
			}
		}
	}

	// As a final fallback, take default customer location country/state from Woo settings.
	if ( ( '' === $dest['country'] || '' === $dest['state'] ) && function_exists( 'wc_get_customer_default_location' ) ) {
		$default_loc = wc_get_customer_default_location();
		if ( is_array( $default_loc ) ) {
			if ( '' === $dest['country'] && ! empty( $default_loc['country'] ) ) {
				$dest['country'] = strtoupper( sanitize_text_field( $default_loc['country'] ) );
			}
			if ( '' === $dest['state'] && ! empty( $default_loc['state'] ) ) {
				$dest['state'] = sanitize_text_field( $default_loc['state'] );
			}
		}
	}

	if ( '' !== $dest['country'] ) {
		$dest['source'] = ( '' !== $dest['postcode'] ) ? 'ip' : 'unknown';
	}

	return $dest;
}

/**
 * Build a browse card shipping summary for a single listing.
 *
 * @param int   $listing_id Listing product ID.
 * @param array $destination Destination context from stakmv_browse_get_destination_context().
 * @return array
 */
function stakmv_browse_get_listing_shipping_summary( $listing_id, $destination ) {
	$listing_id = (int) $listing_id;
	$default = array(
		'type'      => 'calculated',
		'amount'    => esc_html__( 'Calculated at checkout', 'stak-multivendor' ),
		'detail'    => '',
		'estimated' => false,
		'from_label' => false,
	);

	if ( $listing_id <= 0 ) {
		return $default;
	}

	$shipping_mode = function_exists( 'stakmv_get_listing_shipping_mode' )
		? stakmv_get_listing_shipping_mode( $listing_id )
		: 'calculated';

	if ( 'pickup_only' === $shipping_mode ) {
		return array(
			'type'      => 'pickup',
			'amount'    => esc_html__( 'Pickup only', 'stak-multivendor' ),
			'detail'    => esc_html__( 'No delivery fee', 'stak-multivendor' ),
			'estimated' => false,
			'from_label' => false,
		);
	}

	if ( 'free' === $shipping_mode ) {
		return array(
			'type'      => 'free',
			'amount'    => esc_html__( 'Free', 'stak-multivendor' ),
			'detail'    => esc_html__( 'Free shipping', 'stak-multivendor' ),
			'estimated' => false,
			'from_label' => false,
		);
	}

	if ( 'flat' === $shipping_mode ) {
		$flat_cost = (float) get_post_meta( $listing_id, '_stakmv_auction_shipping_cost', true );
		return array(
			'type'      => 'flat',
			'amount'    => $flat_cost > 0 ? wc_price( $flat_cost ) : esc_html__( 'Free', 'stak-multivendor' ),
			'detail'    => esc_html__( 'Flat shipping', 'stak-multivendor' ),
			'estimated' => false,
			'from_label' => $flat_cost > 0,
		);
	}

	// Calculated mode.
	if ( get_option( 'stakmv_live_shipping_enabled', 'no' ) !== 'yes' ) {
		return $default;
	}

	$postcode = trim( (string) ( $destination['postcode'] ?? '' ) );
	$country  = strtoupper( trim( (string) ( $destination['country'] ?? '' ) ) );
	if ( '' === $postcode || '' === $country ) {
		return array(
			'type'      => 'hidden',
			'amount'    => '',
			'detail'    => '',
			'estimated' => false,
			'from_label' => false,
		);
	}

	if (
		! function_exists( 'stakmv_live_shipping_fetch_rates' ) ||
		! function_exists( 'stakmv_live_shipping_get_provider' ) ||
		! function_exists( 'stakmv_live_shipping_get_allowed_carriers_for_package' ) ||
		! function_exists( 'stakmv_live_shipping_build_package_profile' )
	) {
		return $default;
	}

	$product = wc_get_product( $listing_id );
	if ( ! $product ) {
		return $default;
	}

	$package = array(
		'contents'    => array(
			array(
				'product_id' => $listing_id,
				'data'       => $product,
				'quantity'   => 1,
			),
		),
		'destination' => array(
			'address_1' => (string) ( $destination['address_1'] ?? '' ),
			'address_2' => (string) ( $destination['address_2'] ?? '' ),
			'city'      => (string) ( $destination['city'] ?? '' ),
			'state'     => (string) ( $destination['state'] ?? '' ),
			'postcode'  => $postcode,
			'country'   => $country,
		),
	);

	$profile = stakmv_live_shipping_build_package_profile( $package );
	if ( empty( $profile['eligible'] ) ) {
		return $default;
	}
	if ( ! empty( $profile['pickup_only'] ) ) {
		return array(
			'type'      => 'pickup',
			'amount'    => esc_html__( 'Pickup only', 'stak-multivendor' ),
			'detail'    => esc_html__( 'No delivery fee', 'stak-multivendor' ),
			'estimated' => false,
			'from_label' => false,
		);
	}

	$provider = stakmv_live_shipping_get_provider();
	$allowed  = stakmv_live_shipping_get_allowed_carriers_for_package( $profile );
	$rates    = stakmv_live_shipping_fetch_rates( $provider, $package, $allowed );
	if ( is_wp_error( $rates ) || empty( $rates ) || ! is_array( $rates ) ) {
		return $default;
	}

	usort(
		$rates,
		function ( $a, $b ) {
			$a_amount = isset( $a['amount'] ) ? (float) $a['amount'] : PHP_FLOAT_MAX;
			$b_amount = isset( $b['amount'] ) ? (float) $b['amount'] : PHP_FLOAT_MAX;
			return $a_amount <=> $b_amount;
		}
	);

	$best = $rates[0];
	$amount = isset( $best['amount'] ) ? (float) $best['amount'] : 0.0;
	$carrier = sanitize_text_field( (string) ( $best['carrier'] ?? '' ) );
	$service = sanitize_text_field( (string) ( $best['service'] ?? '' ) );
	$days    = isset( $best['delivery_days'] ) ? (int) $best['delivery_days'] : 0;

	$detail_parts = array();
	if ( '' !== $carrier || '' !== $service ) {
		$detail_parts[] = trim( $carrier . ( '' !== $service ? ' ' . $service : '' ) );
	}
		if ( $days > 0 ) {
			/* translators: %d is the estimated number of shipping days. */
			$detail_parts[] = sprintf( _n( '%d day', '%d days', $days, 'stak-multivendor' ), $days );
		}
	$detail = implode( ' • ', array_filter( $detail_parts ) );
	if ( 'ip' === ( $destination['source'] ?? '' ) ) {
		$detail = trim( $detail . ( '' !== $detail ? ' • ' : '' ) . esc_html__( 'Based on your area', 'stak-multivendor' ) );
	}

	return array(
		'type'      => 'calculated',
		'amount'    => wc_price( $amount ),
		'detail'    => $detail,
		'estimated' => true,
		'from_label' => true,
	);
}

/**
 * Render products grid.
 *
 * @param array $args WP_Query args overrides.
 * @return string
 */
function stakmv_render_products( $args = array() ) {
	$defaults = array(
		'post_type'      => 'product',
		'post_status'    => 'publish',
		'posts_per_page' => 12,
	);
	$q_args   = array_merge( $defaults, $args );

	// Ensure paged is respected (from args, URL or default to 1)
	if ( empty( $q_args['paged'] ) ) {
		$q_args['paged'] = max( 1, (int) ( get_query_var( 'paged' ) ?: 1 ) );
	}


	// Exclude expired auctions in initial load as well (align with AJAX filter).
	$now         = current_time( 'timestamp' );
	$expire_cond = array(
		'relation' => 'OR',
		array(
			'key'     => '_stakmv_auction_end_time',
			'value'   => $now,
			'compare' => '>=',
			'type'    => 'NUMERIC',
		),
		array(
			'key'     => '_stakmv_auction_end_time',
			'compare' => 'NOT EXISTS',
		),
	);

	if ( empty( $q_args['meta_query'] ) ) {
		// phpcs:disable WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Frontend browse query must exclude expired auctions by end-time meta.
		$q_args['meta_query'] = array( $expire_cond );
	} else {
		$q_args['meta_query'][] = $expire_cond;
	}
	// phpcs:enable WordPress.DB.SlowDBQuery.slow_db_query_meta_query

	$query = new WP_Query( $q_args );

	if ( ! $query->have_posts() ) {
		return '<p>' . esc_html__( 'No listings found.', 'stak-multivendor' ) . '</p>';
	}

	ob_start();
		$browse_request = stakmv_get_sanitized_browse_request_query();
		$view_mode      = isset( $browse_request['view'] ) ? sanitize_key( (string) $browse_request['view'] ) : 'grid';
		$grid_class = $view_mode === 'list' ? 'wcmv-grid list' : 'wcmv-grid';
	$browse_destination = stakmv_browse_get_destination_context();
	echo '<div class="' . esc_attr( $grid_class ) . '">';

	while ( $query->have_posts() ) {
		$query->the_post();
		$product = wc_get_product( get_the_ID() );
		?>
		<div class="wcmv-card">
		    <?php
$cats = wp_get_post_terms(get_the_ID(), 'product_cat');
if (!empty($cats)) :
?>
<div class="wcmv-badges">
  <?php foreach ($cats as $cat) : ?>
    <span class="wcmv-badge"><?php echo esc_html($cat->name); ?></span>
  <?php endforeach; ?>
</div>
<?php endif; ?>
<?php do_action( 'stakmv_browse_listing_card_actions', get_the_ID() ); ?>
					<a href="<?php the_permalink(); ?>" class="wcmv-thumb">
					<?php
					$thumb_html = $product ? $product->get_image( 'woocommerce_thumbnail' ) : get_the_post_thumbnail( get_the_ID(), 'woocommerce_thumbnail' );
					echo wp_kses_post( $thumb_html );
					?>
				</a>
<h4 class="wcmv-title">
  <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
</h4>

<?php
  $listing_type  = get_post_meta( get_the_ID(), '_stakmv_auction_listing_type', true );
  if ( '' === $listing_type ) {
    $sale_mode = get_post_meta( get_the_ID(), '_stakmv_auction_sale_mode', true );
    if ( 'buy_now' === $sale_mode ) {
      $listing_type = 'buy_now_only';
    } elseif ( 'both' === $sale_mode ) {
      $listing_type = 'auction_buy_now';
    } else {
      $listing_type = 'auction_only';
    }
  }
  $current_bid   = get_post_meta( get_the_ID(), '_stakmv_auction_current_bid', true );
  $start_price   = get_post_meta( get_the_ID(), '_stakmv_auction_start_price', true );
  $buy_now_price = get_post_meta( get_the_ID(), '_stakmv_auction_buy_now_price', true );
  $is_buy_now_only = ( 'buy_now_only' === $listing_type );
  $has_buy_now = ! empty( $buy_now_price );
  $display_price = $current_bid ? $current_bid : $start_price;
?>

<?php if ( ! $is_buy_now_only ) : ?>
  <!-- STARTING PRICE -->
  <div class="wcmv-price-row">
    <span class="label">Price</span>
    <span class="price">
	      <?php echo wp_kses_post( wc_price( (float) $display_price ) ); ?>
    </span>
  </div>
<?php endif; ?>

<?php if ( $is_buy_now_only || ( $has_buy_now && 'auction_buy_now' === $listing_type ) ) : ?>
  <!-- BUY NOW PRICE -->
  <div class="wcmv-price-row wcmv-price-row-buy-now">
    <span class="label">Buy Now</span>
    <span class="price">
	      <?php echo wp_kses_post( wc_price( (float) $buy_now_price ) ); ?>
    </span>
  </div>
<?php endif; ?>

<?php
  $shipping_summary = stakmv_browse_get_listing_shipping_summary( get_the_ID(), $browse_destination );
  if ( ! is_array( $shipping_summary ) ) {
    $shipping_summary = array(
      'type'       => 'calculated',
      'amount'     => esc_html__( 'Calculated at checkout', 'stak-multivendor' ),
      'detail'     => '',
      'from_label' => false,
    );
  }
  $shipping_type  = sanitize_html_class( (string) ( $shipping_summary['type'] ?? 'calculated' ) );
  $shipping_label = esc_html__( 'Shipping', 'stak-multivendor' );
  if ( ! empty( $shipping_summary['from_label'] ) ) {
    $shipping_label = esc_html__( 'Shipping from', 'stak-multivendor' );
  }
  $show_shipping_row = ! empty( $shipping_summary['amount'] );
  if ( 'calculated' === $shipping_type && empty( $shipping_summary['estimated'] ) ) {
    $show_shipping_row = false;
  }
?>
<?php if ( $show_shipping_row ) : ?>
<div class="wcmv-shipping-row wcmv-shipping-<?php echo esc_attr( $shipping_type ); ?>">
  <span class="label"><?php echo esc_html( $shipping_label ); ?></span>
  <span class="price"><?php echo wp_kses_post( $shipping_summary['amount'] ); ?></span>
</div>
<?php if ( ! empty( $shipping_summary['detail'] ) ) : ?>
  <div class="wcmv-shipping-sub"><?php echo esc_html( $shipping_summary['detail'] ); ?></div>
<?php endif; ?>
<?php endif; ?>

<!-- META -->
<?php
  $bids = (int) get_post_meta(get_the_ID(), '_stakmv_auction_bid_count', true);
  $end  = (int) get_post_meta(get_the_ID(), '_stakmv_auction_end_time', true);
  $left = $end ? human_time_diff(time(), $end) : '';
?>
<div class="wcmv-meta">
  <?php if ( ! $is_buy_now_only ) : ?>
	  <span class="wcmv-meta-item"><span class="wcmv-meta-icon" aria-hidden="true">&#9874;</span><?php echo esc_html( (string) $bids ); ?> bids</span>
  <?php endif; ?>
  <?php if ($left) : ?>
    <span class="wcmv-meta-item time"><span class="wcmv-meta-icon" aria-hidden="true">&#9201;</span><?php echo esc_html($left); ?> left</span>
  <?php endif; ?>
</div>

<?php
$author_id = (int) get_post_field('post_author', get_the_ID());
$author    = get_user_by('id', $author_id);
$rating_summary = function_exists('stakmv_get_vendor_rating_summary')
	? stakmv_get_vendor_rating_summary($author_id)
	: array('average' => 0.0, 'count' => 0);
$reputation_summary = function_exists('stakmv_get_vendor_reputation_summary')
	? stakmv_get_vendor_reputation_summary($author_id)
	: array();
?>

<div class="wcmv-vendor">
  by <?php echo esc_html($author ? $author->display_name : ''); ?>
</div>
<?php if (!empty($rating_summary['count'])) : ?>
  <div class="wcmv-vendor-rating">
    <?php
    echo esc_html(
      sprintf(
        /* translators: 1: average rating, 2: total ratings count. */
        __('Seller rating: %1$s/5 (%2$d)', 'stak-multivendor'),
        number_format_i18n((float) $rating_summary['average'], 1),
        (int) $rating_summary['count']
      )
    );
    ?>
  </div>
<?php endif; ?>
<?php if (!empty($reputation_summary['total_orders'])) : ?>
  <div class="wcmv-vendor-trust">
    <?php
    $trust_bits = array();

    $trust_bits[] = sprintf(
      /* translators: %s fulfillment rate percentage. */
      __('%s%% fulfilled', 'stak-multivendor'),
      number_format_i18n((float) ($reputation_summary['fulfillment_rate'] ?? 0), 1)
    );

    if (!empty($reputation_summary['avg_shipping_days'])) {
      $trust_bits[] = sprintf(
        /* translators: %s average shipping days. */
        __('Ships in %s days', 'stak-multivendor'),
        number_format_i18n((float) $reputation_summary['avg_shipping_days'], 1)
      );
    }

    if (!empty($reputation_summary['repeat_buyers_rate'])) {
      $trust_bits[] = sprintf(
        /* translators: %s repeat buyers percentage. */
        __('%s%% repeat buyers', 'stak-multivendor'),
        number_format_i18n((float) $reputation_summary['repeat_buyers_rate'], 1)
      );
    }

    echo esc_html(implode(' · ', $trust_bits));
    ?>
  </div>
<?php endif; ?>

			
		</div>
		<?php
	}

	echo '</div>';

	// PAGINATION
	$total_pages  = (int) $query->max_num_pages;
	$current_page = isset( $q_args['paged'] ) ? max( 1, (int) $q_args['paged'] ) : max( 1, (int) ( get_query_var( 'paged' ) ?: 1 ) );

	if ( $total_pages > 1 ) {
		$max_visible_pages = 10;
		$start_page = max( 1, $current_page - (int) floor( $max_visible_pages / 2 ) );
		$end_page   = $start_page + $max_visible_pages - 1;
		if ( $end_page > $total_pages ) {
			$end_page   = $total_pages;
			$start_page = max( 1, $end_page - $max_visible_pages + 1 );
		}

		echo '<nav class="wcmv-pagination" aria-label="Listings pagination">';

		if ( $current_page > 1 ) {
			$prev = $current_page - 1;
			echo '<a class="wcmv-page-link wcmv-page-nav wcmv-page-nav-prev" href="' . esc_url( stakmv_get_browse_page_link( $prev ) ) . '" data-page="' . esc_attr( $prev ) . '" aria-label="Previous page">&larr; Prev</a>';
		}

		for ( $i = $start_page; $i <= $end_page; $i++ ) {
			$active_class = $i === $current_page ? ' is-active' : '';
				echo '<a class="wcmv-page-link' . esc_attr( $active_class ) . '" href="' . esc_url( stakmv_get_browse_page_link( $i ) ) . '" data-page="' . esc_attr( $i ) . '"' . ( $i === $current_page ? ' aria-current="page"' : '' ) . '>' . esc_html( (string) $i ) . '</a>';
		}

		if ( $current_page < $total_pages ) {
			$next = $current_page + 1;
			echo '<a class="wcmv-page-link wcmv-page-nav wcmv-page-nav-next" href="' . esc_url( stakmv_get_browse_page_link( $next ) ) . '" data-page="' . esc_attr( $next ) . '" aria-label="Next page">Next &rarr;</a>';
		}

		echo '</nav>';
	}

	wp_reset_postdata();

	return ob_get_clean();
}

/**
 * Resolve browse listing type state from request inputs.
 *
 * @param array  $raw_types Raw type[] values.
 * @param string $mobile_mode Optional explicit mobile mode (all|auction|buy_now).
 * @return array
 */
function stakmv_browse_resolve_type_state( $raw_types, $mobile_mode = '' ) {
	$mobile_mode = sanitize_key( (string) $mobile_mode );
	if ( in_array( $mobile_mode, array( 'all', 'auction', 'buy_now' ), true ) ) {
		return array(
			'has_auction' => ( 'auction' === $mobile_mode ),
			'has_buy'     => ( 'buy_now' === $mobile_mode ),
		);
	}

	$types = array();
	foreach ( (array) $raw_types as $type_value ) {
		$type_value = sanitize_key( (string) $type_value );
		if ( '' !== $type_value ) {
			$types[] = $type_value;
		}
	}

	return array(
		'has_auction' => in_array( 'auction', $types, true ),
		'has_buy'     => in_array( 'buy_now', $types, true ),
	);
}

/**
 * Append listing-type constraints using plugin listing meta model.
 *
 * @param array $meta_query Existing meta query clauses.
 * @param bool  $has_auction Auction mode selected.
 * @param bool  $has_buy Buy-now mode selected.
 * @return array
 */
function stakmv_browse_append_listing_type_constraints( $meta_query, $has_auction, $has_buy ) {
	$meta_query = is_array( $meta_query ) ? $meta_query : array();
	$has_auction = (bool) $has_auction;
	$has_buy = (bool) $has_buy;

	// All mode (or invalid/mixed) should not constrain by listing type.
	if ( $has_auction === $has_buy ) {
		return $meta_query;
	}

	if ( $has_auction ) {
		$meta_query[] = array(
			'relation' => 'OR',
			array(
				'key'     => '_stakmv_auction_listing_type',
				'value'   => array( 'auction_only', 'auction_buy_now', 'auction', 'both' ),
				'compare' => 'IN',
			),
			array(
				'key'     => '_stakmv_auction_sale_mode',
				'value'   => array( 'auction', 'both' ),
				'compare' => 'IN',
			),
			array(
				'relation' => 'AND',
				array(
					'key'     => '_stakmv_auction_listing_type',
					'compare' => 'NOT EXISTS',
				),
				array(
					'key'     => '_stakmv_auction_sale_mode',
					'compare' => 'NOT EXISTS',
				),
			),
		);

		return $meta_query;
	}

	$meta_query[] = array(
		'relation' => 'OR',
		array(
			'key'     => '_stakmv_auction_listing_type',
			'value'   => array( 'buy_now_only', 'auction_buy_now', 'buy_now', 'both' ),
			'compare' => 'IN',
		),
		array(
			'key'     => '_stakmv_auction_sale_mode',
			'value'   => array( 'buy_now', 'both' ),
			'compare' => 'IN',
		),
		array(
			'key'     => '_stakmv_auction_buy_now_price',
			'value'   => 0,
			'compare' => '>',
			'type'    => 'NUMERIC',
		),
	);

	return $meta_query;
}

/**
 * AJAX handler for filters.
 */
add_action( 'wp_ajax_stakmv_filter', 'stakmv_ajax_filter' );
add_action( 'wp_ajax_nopriv_stakmv_filter', 'stakmv_ajax_filter' );

function stakmv_ajax_filter() {

	// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Reading the nonce value in order to verify it immediately.
	$nonce_raw = filter_input( INPUT_POST, 'stakmv_filter_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
	$nonce     = sanitize_text_field( (string) $nonce_raw );
	if ( ! wp_verify_nonce( $nonce, 'stakmv_filter' ) ) {
		wp_die( esc_html__( 'Invalid request.', 'stak-multivendor' ) );
	}

	$meta_query = array();
	$tax_query  = array();
	// phpcs:disable WordPress.Security.NonceVerification.Missing -- stakmv_filter nonce is verified above before reading AJAX filter payload.
	$post_input = isset( $_POST ) && is_array( $_POST )
		? map_deep( wp_unslash( $_POST ), 'sanitize_text_field' )
		: array();
	// phpcs:enable WordPress.Security.NonceVerification.Missing

	$raw_types   = isset( $post_input['type'] ) && is_array( $post_input['type'] ) ? (array) $post_input['type'] : array();
	$mobile_mode = isset( $post_input['mobile_type'] ) ? sanitize_key( (string) $post_input['mobile_type'] ) : '';
	$type_state = stakmv_browse_resolve_type_state( $raw_types, $mobile_mode );
	$meta_query = stakmv_browse_append_listing_type_constraints(
		$meta_query,
		! empty( $type_state['has_auction'] ),
		! empty( $type_state['has_buy'] )
	);

	// Price filter.
	$min_raw = isset( $post_input['min_price'] ) ? sanitize_text_field( (string) $post_input['min_price'] ) : '';
	$max_raw = isset( $post_input['max_price'] ) ? sanitize_text_field( (string) $post_input['max_price'] ) : '';
	$min     = '' !== $min_raw ? (float) $min_raw : null;
	$max     = '' !== $max_raw ? (float) $max_raw : null;

	if ( null !== $min || null !== $max ) {
		$range_clause = function ( $key ) use ( $min, $max ) {
			if ( null !== $min && null !== $max ) {
				return array(
					'key'     => $key,
					'value'   => array( $min, $max ),
					'compare' => 'BETWEEN',
					'type'    => 'NUMERIC',
				);
			}
			if ( null !== $min ) {
				return array(
					'key'     => $key,
					'value'   => $min,
					'compare' => '>=',
					'type'    => 'NUMERIC',
				);
			}
			return array(
				'key'     => $key,
				'value'   => $max,
				'compare' => '<=',
				'type'    => 'NUMERIC',
			);
		};

		$no_bid = array(
			'relation' => 'OR',
			array(
				'key'     => '_stakmv_auction_current_bid',
				'compare' => 'NOT EXISTS',
			),
			array(
				'key'     => '_stakmv_auction_current_bid',
				'value'   => '',
				'compare' => '=',
			),
			array(
				'key'     => '_stakmv_auction_current_bid',
				'value'   => 0,
				'compare' => '=',
				'type'    => 'NUMERIC',
			),
		);

		$meta_query[] = array(
			'relation' => 'OR',

			// Auctions WITH bids (filter by current bid).
			$range_clause( '_stakmv_auction_current_bid' ),

			// Auctions WITHOUT bids (filter by start price).
			array(
				'relation' => 'AND',
				$no_bid,
				$range_clause( '_stakmv_auction_start_price' ),
			),

			// Buy now price on auction listings.
			$range_clause( '_stakmv_auction_buy_now_price' ),

			// Standard WooCommerce price for non-auction products.
			$range_clause( '_price' ),
		);
	}

	// Categories.
	if ( ! empty( $post_input['cat'] ) && is_array( $post_input['cat'] ) ) {
		$tax_query[] = array(
			'taxonomy' => 'product_cat',
			'field'    => 'term_id',
			'terms'    => array_map( 'intval', (array) $post_input['cat'] ),
		);
	}

	// Attributes.
		$posted_attr = array();
		if ( isset( $post_input['attr'] ) && is_array( $post_input['attr'] ) ) {
			$posted_attr = $post_input['attr'];
		}
	if ( ! empty( $posted_attr ) ) {
		foreach ( $posted_attr as $tax => $slugs ) {
			$tax       = sanitize_key( (string) $tax );
			$raw_slugs = is_array( $slugs ) ? $slugs : array( $slugs );
			$terms     = array_filter(
				array_map(
					'sanitize_title',
					array_map( 'sanitize_text_field', $raw_slugs )
				)
			);
			if ( '' === $tax || empty( $terms ) ) {
				continue;
			}
			$tax_query[] = array(
				'taxonomy' => $tax,
				'field'    => 'slug',
				'terms'    => array_values( $terms ),
			);
		}
	}

	// Exclude expired auctions (if an auction end time meta is present and in the past).
	$now = current_time( 'timestamp' );
	$meta_query[] = array(
		'relation' => 'OR',
		array(
			'key'     => '_stakmv_auction_end_time',
			'value'   => $now,
			'compare' => '>=',
			'type'    => 'NUMERIC',
		),
		array(
			'key'     => '_stakmv_auction_end_time',
			'compare' => 'NOT EXISTS',
		),
	);

	$args = array();

	if ( ! empty( $meta_query ) ) {
		// phpcs:disable WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Filter UI composes product query constraints by selected meta fields.
		$args['meta_query'] = $meta_query;
	}
	// phpcs:enable WordPress.DB.SlowDBQuery.slow_db_query_meta_query

	if ( ! empty( $tax_query ) ) {
		// phpcs:disable WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Filter UI composes product query constraints by selected taxonomies.
		$args['tax_query'] = $tax_query;
	}
	// phpcs:enable WordPress.DB.SlowDBQuery.slow_db_query_tax_query

	// Respect pagination when filtering via AJAX.
	if ( isset( $post_input['paged'] ) ) {
		$args['paged'] = max( 1, (int) $post_input['paged'] );
	}

	echo wp_kses_post( stakmv_render_products( $args ) );

	wp_die();
}

/**
 * Return sanitized browse query parameters.
 *
 * Browse filters are read-only, so they intentionally do not require a nonce.
 *
 * @return array
 */
function stakmv_get_sanitized_browse_request_query() {
	$query = array();

	$scalar_filters = array(
		'search'      => FILTER_SANITIZE_FULL_SPECIAL_CHARS,
		'mobile_type' => FILTER_SANITIZE_FULL_SPECIAL_CHARS,
		'min_price'   => FILTER_SANITIZE_FULL_SPECIAL_CHARS,
		'max_price'   => FILTER_SANITIZE_FULL_SPECIAL_CHARS,
		'cat'         => FILTER_SANITIZE_NUMBER_INT,
		'paged'       => FILTER_SANITIZE_NUMBER_INT,
		'view'        => FILTER_SANITIZE_FULL_SPECIAL_CHARS,
	);

	foreach ( $scalar_filters as $key => $filter ) {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public browse filters are read-only and do not mutate state.
		$value = filter_input( INPUT_GET, $key, $filter );
		if ( null !== $value && false !== $value && '' !== $value ) {
			$query[ $key ] = sanitize_text_field( (string) $value );
		}
	}

	// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public browse filters are read-only and do not mutate state.
	$type = filter_input( INPUT_GET, 'type', FILTER_SANITIZE_FULL_SPECIAL_CHARS, FILTER_REQUIRE_ARRAY );
	if ( is_array( $type ) ) {
		$query['type'] = map_deep( $type, 'sanitize_text_field' );
	}

	// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public browse filters are read-only and do not mutate state.
	$attr = filter_input( INPUT_GET, 'attr', FILTER_SANITIZE_FULL_SPECIAL_CHARS, FILTER_REQUIRE_ARRAY );
	if ( is_array( $attr ) ) {
		$query['attr'] = map_deep( $attr, 'sanitize_text_field' );
	}

	return $query;
}

/**
 * Build browse listing query args from the current request (GET).
 *
 * @return array
 */
function stakmv_get_browse_query_args_from_request() {
	$args       = array();
	$meta_query = array();
	$tax_query  = array();
	$get_input  = stakmv_get_sanitized_browse_request_query();

	// Search.
	if ( isset( $get_input['search'] ) && '' !== $get_input['search'] ) {
		$args['s'] = sanitize_text_field( (string) $get_input['search'] );
	}

	$raw_types   = isset( $get_input['type'] ) && is_array( $get_input['type'] ) ? (array) $get_input['type'] : array();
	$mobile_mode = isset( $get_input['mobile_type'] ) ? sanitize_key( (string) $get_input['mobile_type'] ) : '';
	$type_state = stakmv_browse_resolve_type_state( $raw_types, $mobile_mode );
	$meta_query = stakmv_browse_append_listing_type_constraints(
		$meta_query,
		! empty( $type_state['has_auction'] ),
		! empty( $type_state['has_buy'] )
	);

	// Price filter.
	$min_raw = isset( $get_input['min_price'] ) ? sanitize_text_field( (string) $get_input['min_price'] ) : '';
	$max_raw = isset( $get_input['max_price'] ) ? sanitize_text_field( (string) $get_input['max_price'] ) : '';
	$min     = '' !== $min_raw ? (float) $min_raw : null;
	$max     = '' !== $max_raw ? (float) $max_raw : null;

	if ( null !== $min || null !== $max ) {
		$range_clause = function ( $key ) use ( $min, $max ) {
			if ( null !== $min && null !== $max ) {
				return array(
					'key'     => $key,
					'value'   => array( $min, $max ),
					'compare' => 'BETWEEN',
					'type'    => 'NUMERIC',
				);
			}
			if ( null !== $min ) {
				return array(
					'key'     => $key,
					'value'   => $min,
					'compare' => '>=',
					'type'    => 'NUMERIC',
				);
			}
			return array(
				'key'     => $key,
				'value'   => $max,
				'compare' => '<=',
				'type'    => 'NUMERIC',
			);
		};

		$no_bid = array(
			'relation' => 'OR',
			array(
				'key'     => '_stakmv_auction_current_bid',
				'compare' => 'NOT EXISTS',
			),
			array(
				'key'     => '_stakmv_auction_current_bid',
				'value'   => '',
				'compare' => '=',
			),
			array(
				'key'     => '_stakmv_auction_current_bid',
				'value'   => 0,
				'compare' => '=',
				'type'    => 'NUMERIC',
			),
		);

		$meta_query[] = array(
			'relation' => 'OR',
			$range_clause( '_stakmv_auction_current_bid' ),
			array(
				'relation' => 'AND',
				$no_bid,
				$range_clause( '_stakmv_auction_start_price' ),
			),
			$range_clause( '_stakmv_auction_buy_now_price' ),
			$range_clause( '_price' ),
		);
	}

	// Categories (single select).
	$category_filter = isset( $get_input['cat'] ) ? absint( $get_input['cat'] ) : 0;
	if ( $category_filter > 0 ) {
		$tax_query[] = array(
			'taxonomy' => 'product_cat',
			'field'    => 'term_id',
			'terms'    => array( $category_filter ),
		);
	}

	// Attributes (if present).
		$get_attr = array();
		if ( isset( $get_input['attr'] ) && is_array( $get_input['attr'] ) ) {
			$get_attr = $get_input['attr'];
		}
	if ( ! empty( $get_attr ) ) {
		foreach ( $get_attr as $tax => $slugs ) {
			$tax       = sanitize_key( (string) $tax );
			$raw_slugs = is_array( $slugs ) ? $slugs : array( $slugs );
			$terms     = array_filter(
				array_map(
					'sanitize_title',
					array_map( 'sanitize_text_field', $raw_slugs )
				)
			);
			if ( '' === $tax || empty( $terms ) ) {
				continue;
			}
			$tax_query[] = array(
				'taxonomy' => $tax,
				'field'    => 'slug',
				'terms'    => array_values( $terms ),
			);
		}
	}

	// Exclude expired auctions.
	$now         = current_time( 'timestamp' );
	$expire_cond = array(
		'relation' => 'OR',
		array(
			'key'     => '_stakmv_auction_end_time',
			'value'   => $now,
			'compare' => '>=',
			'type'    => 'NUMERIC',
		),
		array(
			'key'     => '_stakmv_auction_end_time',
			'compare' => 'NOT EXISTS',
		),
	);

	if ( empty( $meta_query ) ) {
		$meta_query = array( $expire_cond );
	} else {
		$meta_query[] = $expire_cond;
	}

	if ( ! empty( $meta_query ) ) {
		// phpcs:disable WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Filter UI composes product query constraints by selected meta fields.
		$args['meta_query'] = $meta_query;
	}
	// phpcs:enable WordPress.DB.SlowDBQuery.slow_db_query_meta_query

	if ( ! empty( $tax_query ) ) {
		// phpcs:disable WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Filter UI composes product query constraints by selected taxonomies.
		$args['tax_query'] = $tax_query;
	}
	// phpcs:enable WordPress.DB.SlowDBQuery.slow_db_query_tax_query

	if ( isset( $get_input['paged'] ) ) {
		$args['paged'] = max( 1, (int) $get_input['paged'] );
	}

	return $args;
}

/**
 * Build pagination links that preserve current browse filters.
 *
 * @param int $page Page number.
 * @return string
 */
function stakmv_get_browse_page_link( $page ) {
	$query_args = array();
	$get_input  = stakmv_get_sanitized_browse_request_query();

	foreach ( $get_input as $key => $value ) {
		$key = sanitize_key( (string) $key );
		if ( 'paged' === $key ) {
			continue;
		}
		$query_args[ $key ] = is_array( $value )
			? map_deep( $value, 'sanitize_text_field' )
			: sanitize_text_field( (string) $value );
	}

	$query_args['paged'] = max( 1, (int) $page );
	$base_url            = remove_query_arg( 'paged' );

	return add_query_arg( $query_args, $base_url );
}
