<?php
/**
 * File Path: includes/shortcodes/class-mbs-shortcode-author.php
 *
 * [mbs_author slug="x"] Shortcode -- SHC-5
 *
 * Renders a single author inline: PRO hero partial or FREE bio + social links,
 * followed by the author's book grid in the resolved layout. Primary use case:
 * "By Same Author" sections on book pages or custom author landing pages.
 *
 * Feature-for-feature equivalent of taxonomy-mbs-author.php (minus breadcrumbs,
 * which are not meaningful in shortcode context).
 *
 * Attributes:
 *   slug     (string, required) -- term slug for mbs_author
 *   per_page (int, default 20)  -- books per page; -1 = all.
 *
 * @package MyBookShowroom
 * @since   1.0.0
 */

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

class MBS_Shortcode_Author { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound -- mbs_/MBS_ prefix is correct; scanner not configured with plugin prefix

	/**
	 * Render [mbs_author] shortcode.
	 *
	 * @param array $atts Shortcode attributes from WordPress.
	 * @return string     Rendered HTML or HTML comment on error.
	 */
	public static function render( array $atts = array() ): string {
		if ( ! mbs_is_registered() ) {
			return '';
		}

		$atts = shortcode_atts(
			array(
				'slug'     => '',
				'per_page' => '20',
				'layout'   => '',   // When empty, resolved via MBS_Layout_Registry::resolve_for_term().
			),
			$atts,
			'mbs_author'
		);

		$slug        = sanitize_title( $atts['slug'] );
		$per_page    = (int) $atts['per_page'];
		$layout_attr = sanitize_key( $atts['layout'] );

		if ( '' === $slug ) {
			return '<!-- MBS: mbs_author: slug attribute required -->';
		}

		$term = get_term_by( 'slug', $slug, MBS_TAX_AUTHOR );
		if ( ! $term instanceof WP_Term ) {
			return '<!-- MBS: mbs_author: term not found -->';
		}

		$term_id = (int) $term->term_id;

		// Resolve layout: explicit attribute overrides per-term + global settings.
		// Block passes 'grid' by default; shortcode callers can pass layout='' to
		// preserve the existing resolved-from-term behavior.
		if ( '' !== $layout_attr ) {
			$layout_obj = MBS_Layout_Registry::get_layout( $layout_attr );
		} else {
			$layout_obj = MBS_Layout_Registry::resolve_for_term( $term_id );
		}

		ob_start();
		?>
		<div class="mbs-wrapper mbs-shortcode mbs-shortcode-author">

			<header class="mbs-shortcode-header">
				<h2 class="mbs-shortcode-title">
					<?php
					printf(
						/* translators: %s: author name */
						esc_html__( 'Books by %s', 'my-book-showroom' ),
						esc_html( $term->name )
					);
					?>
				</h2>
			</header>

			<?php
			// PRO: Author hero partial -- handles its own GP-UI-1 gating (renders
			// empty if the author has no photo, no bio, no website, no social URLs).
			// No breadcrumbs in shortcode context.
			if ( mbs_is_pro() ) :
				mbs_get_template_part(
					'partials/section-author-hero',
					array( 'author_term_id' => $term_id )
				);
			endif;
			?>

			<?php if ( ! mbs_is_pro() ) : ?>

				<?php
				// FREE: Author bio -- mbs_author_bio term meta.
				// GP-UI-1: render only when non-empty.
				$author_bio = (string) get_term_meta( $term_id, 'mbs_author_bio', true );
				?>
				<?php if ( '' !== $author_bio ) : ?>
					<div class="mbs-author-bio mbs-author-bio--free">
						<?php echo wp_kses_post( wpautop( $author_bio ) ); ?>
					</div>
				<?php endif; ?>

				<?php
				// FREE: Social links -- 7 platform keys + website_url.
				// GP-UI-1: skip entire block when no platform has a URL.
				// Mirrors the archive template pattern exactly.
				$social_platforms = array(
					'mbs_author_website_url'   => __( 'Website', 'my-book-showroom' ),
					'mbs_author_twitter_url'   => __( 'Twitter / X', 'my-book-showroom' ),
					'mbs_author_instagram_url' => __( 'Instagram', 'my-book-showroom' ),
					'mbs_author_facebook_url'  => __( 'Facebook', 'my-book-showroom' ),
					'mbs_author_tiktok_url'    => __( 'TikTok', 'my-book-showroom' ),
					'mbs_author_goodreads_url' => __( 'Goodreads', 'my-book-showroom' ),
					'mbs_author_bookbub_url'   => __( 'BookBub', 'my-book-showroom' ),
					'mbs_author_linkedin_url'  => __( 'LinkedIn', 'my-book-showroom' ),
				);
				$rendered_social = array();
				foreach ( $social_platforms as $meta_key => $label ) {
					$link_url = esc_url( (string) get_term_meta( $term_id, $meta_key, true ) );
					if ( '' === $link_url ) {
						continue;
					}
					$platform_slug     = str_replace( array( 'mbs_author_', '_url' ), '', $meta_key );
					$rendered_social[] = '<a href="' . $link_url
						. '" class="mbs-social-link mbs-social-link--' . esc_attr( $platform_slug )
						. '" target="_blank" rel="noopener noreferrer">'
						. esc_html( $label ) . '</a>';
				}
				?>
				<?php if ( ! empty( $rendered_social ) ) : ?>
					<div class="mbs-author-social mbs-author-social--free">
						<?php echo implode( ' ', $rendered_social ); // phpcs:ignore WordPress.Security.EscapeOutput -- each link already escaped above ?>
					</div>
				<?php endif; ?>

			<?php endif; // ! mbs_is_pro() ?>

			<?php
			// Book grid -- ALL tiers. Layout Registry renders via the resolved layout.
			$author_query = new WP_Query( array(
				'post_type'      => MBS_POST_TYPE,
				'posts_per_page' => $per_page,
				'post_status'    => 'publish',
				'orderby'        => 'date',
				'order'          => 'DESC',
				'no_found_rows'  => true,
				'tax_query'      => array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- standard WP query pattern; VIP rule does not apply to this plugin
					array(
						'taxonomy' => MBS_TAX_AUTHOR,
						'field'    => 'term_id',
						'terms'    => $term_id,
					),
				),
			) );
			// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
			echo $layout_obj->render( $author_query );
			?>

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