<?php
/**
 * File Path: includes/taxonomies/class-mbs-taxonomy-collection.php
 *
 * Collection Taxonomy — My Book Showroom
 *
 * Registers the mbs_collection taxonomy for grouping books into box sets,
 * bundles, anthologies, and other multi-book collections. Many-to-many:
 * a book may belong to multiple collections simultaneously. Distinct from
 * Series (exclusive, one per book). See BACKLOG F-016.
 *
 * @package    My_Book_Showroom
 * @subpackage Includes/Taxonomies
 * @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_Taxonomy_Collection {
	use MBS_Taxonomy_Layout_Field_Trait;

	/**
	 * Return the taxonomy constant for the layout field trait.
	 *
	 * @return string
	 */
	protected static function layout_taxonomy_key(): string {
		return MBS_TAX_COLLECTION;
	}

	/**
	 * Valid collection type slugs → display labels.
	 * Stored as term_meta key 'mbs_collection_type'.
	 *
	 * Returns a translated array. PHP constants cannot hold function-call
	 * return values, so this is a static method (V6-C-020).
	 */
	public static function get_types(): array {
		return array(
			''                       => __( '— Select type (optional) —', 'my-book-showroom' ),
			'anthology'              => __( 'Anthology', 'my-book-showroom' ),
			'author_collection'      => __( 'Author Collection', 'my-book-showroom' ),
			'award_winning'          => __( 'Award-Winning Collection', 'my-book-showroom' ),
			'book_club'              => __( 'Book Club / Reading Challenge', 'my-book-showroom' ),
			'box_set'                => __( 'Box Set', 'my-book-showroom' ),
			'bundle'                 => __( 'Bundle', 'my-book-showroom' ),
			'companion_set'          => __( 'Companion / Spin-off', 'my-book-showroom' ),
			'compendium'             => __( 'Compendium', 'my-book-showroom' ),
			'diversity'              => __( 'Diversity & Representation', 'my-book-showroom' ),
			'historical'             => __( 'Historical / Era Collection', 'my-book-showroom' ),
			'limited_series'         => __( 'Limited Series', 'my-book-showroom' ),
			'omnibus'                => __( 'Omnibus', 'my-book-showroom' ),
			'publishers_collection'  => __( "Publisher's Collection", 'my-book-showroom' ),
			'seasonal'               => __( 'Seasonal / Holiday', 'my-book-showroom' ),
			'series'                 => __( 'Series', 'my-book-showroom' ),
			'special_edition'        => __( 'Special Edition', 'my-book-showroom' ),
			'themed'                 => __( 'Themed Collection', 'my-book-showroom' ),
		);
	}

	public static function register(): void {
		$labels = array(
			'name'              => __( 'Collections', 'my-book-showroom' ),
			'singular_name'     => __( 'Collection', 'my-book-showroom' ),
			'menu_name'         => __( 'Collections', 'my-book-showroom' ),
			'all_items'         => __( 'All Collections', 'my-book-showroom' ),
			'add_new_item'      => __( 'Add New Collection', 'my-book-showroom' ),
			'new_item_name'     => __( 'New Collection Name', 'my-book-showroom' ),
			'edit_item'         => __( 'Edit Collection Slug', 'my-book-showroom' ),
			'update_item'       => __( 'Update Collection', 'my-book-showroom' ),
			'search_items'      => __( 'Search Collections', 'my-book-showroom' ),
			'not_found'         => __( 'No collections found.', 'my-book-showroom' ),
			'no_terms'          => __( 'No collections', 'my-book-showroom' ),
		);

		register_taxonomy(
			MBS_TAX_COLLECTION,
			MBS_POST_TYPE,
			array(
				'labels'                => $labels,
				'hierarchical'          => false,
				'public'                => true,
				'show_ui'               => true,
				'show_in_rest'          => true,
				'show_admin_column'     => true,
				// MENU-01: MBS_Admin::add_menu() registers the Collections submenu manually.
				'show_in_menu'          => false,
				// MBS_Admin_Native_Bulk_Edit renders a checkbox list instead of the
				// WP-generated comma-separated text input.
				'show_in_quick_edit'    => false,
				// Count drafts, private, and pending posts — not just published.
				// RF-013: Static callable replaces global function string.
				'update_count_callback' => array( __CLASS__, 'update_term_count_all' ),
			)
		);

		// F-016: Suppress the default tag-style sidebar widget on the book editor.
		// The Book Header metabox renders a custom checkbox picker with per-collection
		// position inputs instead, enforcing the correct multi-select + position UX.
		add_action( 'add_meta_boxes', array( __CLASS__, 'remove_default_meta_box' ), 99 );

		if ( is_admin() ) {
			// F-016: Collection Type field on the standard taxonomy add/edit screens.
			add_action( MBS_TAX_COLLECTION . '_add_form_fields',  array( __CLASS__, 'render_type_field_add' ) );
			add_action( MBS_TAX_COLLECTION . '_edit_form_fields', array( __CLASS__, 'render_type_field_edit' ) );
			add_action( 'created_' . MBS_TAX_COLLECTION, array( __CLASS__, 'save_type_field' ) );
			add_action( 'edited_'  . MBS_TAX_COLLECTION, array( __CLASS__, 'save_type_field' ) );
			add_action( MBS_TAX_COLLECTION . '_edit_form_fields', array( __CLASS__, 'render_settings_notice' ),  5, 2 );
			add_action( MBS_TAX_COLLECTION . '_edit_form_fields', array( __CLASS__, 'render_layout_field' ), 20, 2 );
			add_action( 'edited_' . MBS_TAX_COLLECTION,           array( __CLASS__, 'save_layout_field' ) );
			add_action( 'admin_enqueue_scripts',                   array( __CLASS__, 'enqueue_layout_scripts' ) );
		}
	}

	/**
	 * Render a navigation notice on the native WordPress Edit Term screen.
	 *
	 * Points editors to Settings → Collections for the full rich editing UI.
	 * Delegates HTML rendering to MBS_Taxonomy_Settings_Notice::render().
	 *
	 * @param WP_Term $term Current term object.
	 * @return void
	 * @since 1.0.0
	 */
	public static function render_settings_notice( WP_Term $term ): void {
		MBS_Taxonomy_Settings_Notice::render(
			$term,
			'collections',
			/* translators: Button label linking to the collections front-end page. */
			__( 'View Collection →', 'my-book-showroom' ),
			/* translators: %s: link to My Book Showroom → Settings → Collections */
			__( 'To edit the description, type, books, and other details, go to %s. This screen manages the slug only.', 'my-book-showroom' ),
			__( 'My Book Showroom → Settings → Collections', 'my-book-showroom' )
		);
	}
	public static function remove_default_meta_box(): void {
		remove_meta_box( 'tagsdiv-' . MBS_TAX_COLLECTION, MBS_POST_TYPE, 'side' );
	}

	/**
	 * Render the Collection Type field on the "Add New Collection" screen.
	 */
	public static function render_type_field_add(): void {
		?>
		<div class="form-field">
			<label for="mbs_collection_type"><?php esc_html_e( 'Collection Type', 'my-book-showroom' ); ?></label>
			<select id="mbs_collection_type" name="mbs_collection_type">
				<?php foreach ( self::get_types() as $value => $label ) : ?>
					<option value="<?php echo esc_attr( $value ); ?>"><?php echo esc_html( $label ); ?></option>
				<?php endforeach; ?>
			</select>
			<p><?php esc_html_e( 'Describes the kind of grouping (e.g. Box Set, Anthology, Bundle). Optional.', 'my-book-showroom' ); ?></p>
		</div>
		<?php
	}

	/**
	 * Render the Collection Type field on the "Edit Collection" screen.
	 *
	 * @param WP_Term $term The term being edited.
	 */
	public static function render_type_field_edit( WP_Term $term ): void {
		$current_type = get_term_meta( $term->term_id, 'mbs_collection_type', true );
		?>
		<tr class="form-field">
			<th scope="row">
				<label for="mbs_collection_type"><?php esc_html_e( 'Collection Type', 'my-book-showroom' ); ?></label>
			</th>
			<td>
				<select id="mbs_collection_type" name="mbs_collection_type">
					<?php foreach ( self::get_types() as $value => $label ) : ?>
						<option value="<?php echo esc_attr( $value ); ?>"<?php selected( $current_type, $value ); ?>>
							<?php echo esc_html( $label ); ?>
						</option>
					<?php endforeach; ?>
				</select>
				<p class="description"><?php esc_html_e( 'Describes the kind of grouping (e.g. Box Set, Anthology, Bundle). Optional.', 'my-book-showroom' ); ?></p>
			</td>
		</tr>
		<?php
	}

	/**
	 * Save the mbs_collection_type term_meta when a collection term is created or edited.
	 * WP core verifies the nonce and capabilities before firing these hooks in the admin.
	 *
	 * @param int $term_id The term ID being saved.
	 */
	public static function save_type_field( int $term_id ): void {
		if ( ! current_user_can( 'manage_categories' ) ) {
			return;
		}
		if ( ! isset( $_POST['mbs_collection_type'] ) ) {
			return;
		}
		$type = sanitize_key( wp_unslash( $_POST['mbs_collection_type'] ) );
		// Accept empty string (no type) or any key present in the TYPES registry.
		if ( '' === $type || array_key_exists( $type, self::get_types() ) ) {
			update_term_meta( $term_id, 'mbs_collection_type', $type );
		}
	}

	/**
	 * Return the display label for a collection type slug.
	 *
	 * Returns an empty string for the empty key (no type selected) so callers
	 * can do a simple truthiness check to decide whether to display a type badge.
	 *
	 * @param  string $type  A key from self::get_types(), or empty string.
	 * @return string        Human-readable label, or empty string when $type is ''.
	 */

	public static function get_type_label( string $type ): string {
		if ( '' === $type ) {
			return '';
		}
		return self::get_types()[ $type ] ?? '';
	}
	/**
	 * Term count callback: count all non-trashed post statuses.
	 *
	 * WordPress core's _update_post_term_count() only counts published posts.
	 * This callback counts every non-trashed status so term counts stay accurate
	 * during active editing (drafts, private, pending, future).
	 *
	 * Registered via 'update_count_callback' on all four MBS taxonomies
	 * (RF-013: fixes the latent bug where genre/series/universe showed 0 for
	 * non-published books).
	 *
	 * @param int[]       $terms    Array of term taxonomy IDs to update.
	 * @param WP_Taxonomy $taxonomy Taxonomy object (unused; required by WP).
	 * @return void
	 */
	public static function update_term_count_all( array $terms, WP_Taxonomy $taxonomy ): void {
		foreach ( $terms as $ttid ) {
			MBS_Taxonomy_Count_DAO::update_term_book_count( (int) $ttid );
		}
	}

}
