<?php
/**
 * File Path: includes/metaboxes/class-mbs-metabox-categorization.php
 *
 * Tags & Themes Metabox
 *
 * Provides a single tabbed sidebar metabox on the mbs_book editor covering
 * the two free-form categorization vocabularies:
 *   - Tags (mbs_tag)          — free-form, FREE tier
 *   - Themes / Tropes (mbs_theme) — curated + extensible, FREE tier
 *
 * All vocabularies are FREE; no PRO gate applies here (F-019).
 *
 * Suppresses the default WP tag-style sidebar widgets for mbs_tag and
 * mbs_theme so the only assignment UI is this metabox.
 *
 * Content Warnings, Audience, Age Range, Grade Range, and Bowker codes
 * are owned by MBS_Metabox_Classification (CLASS-6).
 *
 * Nonce: mbs_categorization_nonce / mbs_save_categorization
 *
 * @package    My_Book_Showroom
 * @subpackage Includes/Metaboxes
 * @since      1.0.0
 */

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

// phpcs:disable WordPress.Security.NonceVerification -- nonce verified in parent class verify_save() / check_admin_referer() before $_POST access; PHPCS cannot trace cross-method nonce verification
class MBS_Metabox_Categorization extends MBS_Metabox_Base { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound -- mbs_/MBS_ prefix is correct; scanner not configured with plugin prefix

	public function __construct() {
	}



	/**
	 * Render the tabbed Tags & Themes metabox.
	 *
	 * @param WP_Post $post Current post object.
	 */
	public function render( WP_Post $post ): void {
		$genre_terms = get_terms( array( 'taxonomy' => MBS_TAX_GENRE, 'hide_empty' => false ) );
		$tag_terms   = get_terms( array( 'taxonomy' => MBS_TAX_TAG,   'hide_empty' => false ) );
		$theme_terms = get_terms( array( 'taxonomy' => MBS_TAX_THEME, 'hide_empty' => false ) );

		$assigned_genres = wp_get_post_terms( $post->ID, MBS_TAX_GENRE, array( 'fields' => 'ids' ) );
		$assigned_tags   = wp_get_post_terms( $post->ID, MBS_TAX_TAG,   array( 'fields' => 'ids' ) );
		$assigned_themes = wp_get_post_terms( $post->ID, MBS_TAX_THEME, array( 'fields' => 'ids' ) );

		$assigned_genres = is_wp_error( $assigned_genres ) ? array() : $assigned_genres;
		$assigned_tags   = is_wp_error( $assigned_tags )   ? array() : $assigned_tags;
		$assigned_themes = is_wp_error( $assigned_themes ) ? array() : $assigned_themes;

		$tabs = array(
			array(
				'id'       => 'genre',
				'label'    => __( 'Genre', 'my-book-showroom' ),
				'terms'    => is_wp_error( $genre_terms ) ? array() : $genre_terms,
				'assigned' => $assigned_genres,
				'field'    => 'mbs_cat_genres',
				'taxonomy' => MBS_TAX_GENRE,
				'empty'    => __( 'No genres yet. Add genres via Books → Genres.', 'my-book-showroom' ),
			),
			array(
				'id'       => 'tags',
				'label'    => __( 'Tags/Keywords', 'my-book-showroom' ),
				'terms'    => is_wp_error( $tag_terms )   ? array() : $tag_terms,
				'assigned' => $assigned_tags,
				'field'    => 'mbs_cat_tags',
				'taxonomy' => MBS_TAX_TAG,
				'empty'    => __( 'No tags yet. Add tags via Books → Tags.', 'my-book-showroom' ),
			),
			array(
				'id'       => 'themes',
				'label'    => __( 'Themes', 'my-book-showroom' ),
				'terms'    => is_wp_error( $theme_terms ) ? array() : $theme_terms,
				'assigned' => $assigned_themes,
				'field'    => 'mbs_cat_themes',
				'taxonomy' => MBS_TAX_THEME,
				'empty'    => __( 'No themes yet. Add themes via Books → Themes.', 'my-book-showroom' ),
			),
		);

		mbs_get_template_part( 'admin/metabox-categorization', compact( 'tabs' ) );
	}

	/**
	 * Save Tags and Themes term assignments.
	 *
	 * Content Warnings, Bowker, Audience, Age Range, and Grade Range are
	 * saved by MBS_Metabox_Classification (CLASS-6).
	 *
	 * @param int     $post_id Post ID.
	 * @param WP_Post $post    Post object.
	 */
	public function save( int $post_id, WP_Post $post ): void {
		if ( ! $this->verify_save( $post_id, 'mbs_categorization_nonce', 'mbs_save_categorization' ) ) {
			return;
		}

		// Genre (reader-facing taxonomy — distinct from ONIX/BISAC industry classification).
		$genre_ids = array();
		if ( isset( $_POST['mbs_cat_genres'] ) && is_array( $_POST['mbs_cat_genres'] ) ) {
			$genre_ids = array_map( 'absint', wp_unslash( $_POST['mbs_cat_genres'] ) );
		}
		wp_set_object_terms( $post_id, $genre_ids, MBS_TAX_GENRE );

		// Tags.
		$tag_ids = array();
		if ( isset( $_POST['mbs_cat_tags'] ) && is_array( $_POST['mbs_cat_tags'] ) ) {
			$tag_ids = array_map( 'absint', wp_unslash( $_POST['mbs_cat_tags'] ) );
		}
		wp_set_object_terms( $post_id, $tag_ids, MBS_TAX_TAG );

		// Themes / Tropes.
		$theme_ids = array();
		if ( isset( $_POST['mbs_cat_themes'] ) && is_array( $_POST['mbs_cat_themes'] ) ) {
			$theme_ids = array_map( 'absint', wp_unslash( $_POST['mbs_cat_themes'] ) );
		}
		wp_set_object_terms( $post_id, $theme_ids, MBS_TAX_THEME );
	}

	/**
	 * Render one editor section within the unified book editor shell.
	 *
	 * Passthrough — single-section handler (Sprint 169).
	 *
	 * @since  1.0.0
	 * @param  string  $section_key  Section key (ignored for single-section handlers).
	 * @param  WP_Post $post         Current post object.
	 * @return void
	 */
	public function render_section( string $section_key, WP_Post $post ): void {
		$this->render( $post );
	}

	/**
	 * Save one editor section within the unified book editor shell.
	 *
	 * Passthrough — single-section handler (Sprint 169).
	 *
	 * @since  1.0.0
	 * @param  string  $section_key  Section key (ignored for single-section handlers).
	 * @param  int     $post_id      Post ID.
	 * @param  WP_Post $post         Post object.
	 * @return void
	 */
	public function save_section( string $section_key, int $post_id, WP_Post $post ): void {
		$this->save( $post_id, $post );
	}

}
