<?php
/**
 * File Path: includes/shortcodes/class-mbs-shortcode-bestseller.php
 *
 * [mbs_bestseller] Shortcode -- DISPLAY-2
 *
 * Renders a list of bestselling books (those whose best ASIN sales_rank
 * is <= the configured threshold). PRO-gated.
 *
 * Attributes:
 *   limit  (int, default 10)   -- max number of books to return.
 *   layout (string, default grid) -- layout registry slug.
 *
 * @package MyBookShowroom
 * @since   1.0.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class MBS_Shortcode_Bestseller
 *
 * @since 1.0.0
 */
class MBS_Shortcode_Bestseller { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound -- mbs_/MBS_ prefix is correct; scanner not configured with plugin prefix

	/**
	 * Render [mbs_bestseller] shortcode.
	 *
	 * @param array $atts Raw shortcode attributes.
	 * @return string Rendered HTML.
	 */
	public static function render( array $atts ): string {
		if ( ! mbs_is_pro() ) {
			return '<!-- MBS: mbs_bestseller requires PRO license -->';
		}

		$atts = shortcode_atts(
			array(
				'limit'  => 10,
				'layout' => 'grid',
			),
			$atts,
			'mbs_bestseller'
		);

		$limit     = max( 1, (int) $atts['limit'] );
		$layout    = sanitize_key( (string) $atts['layout'] );
		$threshold = (int) get_option( 'mbs_setting_bestseller_rank_threshold', 100 );

		// Fetch post IDs that qualify from pa_api_cache via format_rows join.
		$post_ids = self::get_qualifying_post_ids( $threshold, $limit );

		if ( empty( $post_ids ) ) {
			return '<!-- MBS: no bestselling books found -->';
		}

		$query = new WP_Query( array(
			'post_type'      => MBS_POST_TYPE,
			'posts_per_page' => count( $post_ids ),
			'post__in'       => $post_ids,
			'orderby'        => 'post__in',
			'post_status'    => 'publish',
		) );

		$layout_obj = MBS_Layout_Registry::get_layout( $layout );

		ob_start();
		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- layout class owns escaping.
		echo $layout_obj->render( $query );
		return ob_get_clean();
	}

	/**
	 * Return post IDs whose best ASIN sales_rank <= threshold, ordered ASC by rank.
	 *
	 * Joins mbs_format_rows -> mbs_pa_api_cache on ASIN.
	 * Groups by post_id so each book appears once (MIN rank across all formats).
	 *
	 * @param int $threshold Max qualifying rank (inclusive).
	 * @param int $limit     Max number of post IDs to return.
	 * @return int[]
	 */
	private static function get_qualifying_post_ids( int $threshold, int $limit ): array {
		return MBS_PA_API_Cache_DAO::get_post_ids_by_rank_threshold( $threshold, $limit );
	}
}
