<?php
/**
 * File Path: includes/post-types/class-mbs-book-post-type.php
 *
 * Book Custom Post Type
 *
 * Registers the mbs_book CPT.
 *
 * @package MyBookShowroom
 * @since   1.0.0
 */

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

/**
 * MBS_Book_Post_Type class.
 */
class MBS_Book_Post_Type {

	/**
	 * Register the CPT.
	 */
	public static function register(): void {
		$labels = array(
			'name'               => __( 'Books', 'my-book-showroom' ),
			'singular_name'      => __( 'Book', 'my-book-showroom' ),
			'menu_name'          => __( 'Books', 'my-book-showroom' ),
			'name_admin_bar'     => __( 'Book', 'my-book-showroom' ),
			'all_items'          => __( 'All Books', 'my-book-showroom' ),
			'add_new'            => __( 'Add New Book', 'my-book-showroom' ),
			'add_new_item'       => __( 'Add New Book', 'my-book-showroom' ),
			'edit_item'          => __( 'Edit Book', 'my-book-showroom' ),
			'new_item'           => __( 'New Book', 'my-book-showroom' ),
			'view_item'          => __( 'View Book', 'my-book-showroom' ),
			'search_items'       => __( 'Search Books', 'my-book-showroom' ),
			'not_found'          => __( 'No books found', 'my-book-showroom' ),
			'not_found_in_trash' => __( 'No books found in Trash', 'my-book-showroom' ),
		);

		$args = array(
			'labels'             => $labels,
			'public'             => true,
			'has_archive'        => 'books', // V6-C-008: explicit slug sync.
			'rewrite'            => array( 'slug' => 'books' ),
			// 'editor' intentionally omitted — book data lives entirely in custom metaboxes.
			// Including 'editor' + show_in_rest:true would load the Gutenberg canvas on every
			// book edit screen, producing a large blank void above the metaboxes (C2-001).
			// show_in_rest remains true so blocks-editor.js can query books via getEntityRecords().
			'supports'           => array( 'title', 'thumbnail', 'revisions' ),
			// MENU-01: Full manual control — all menu items are registered in MBS_Admin::add_menu().
			// show_in_menu => false prevents WordPress from auto-attaching this CPT to any menu
			// and avoids the orphaned-taxonomy-items problem (where taxonomy items auto-attach to
			// edit.php?post_type=mbs_book as parent, which has no registered menu entry).
			'show_in_menu'       => false,
			'show_in_rest'       => true,
			'publicly_queryable' => true,
			// Explicit capability mapping so site owners can create restricted "Book Manager" roles
			// without granting full post capabilities to Editors or lower roles.
			'capability_type'    => 'mbs_book',
			'map_meta_cap'       => true,
		);

		register_post_type( MBS_POST_TYPE, $args );

		// Explicitly disable the block editor for mbs_book. Removing 'editor' from supports
		// is not sufficient on its own — WordPress will still load Gutenberg when show_in_rest
		// is true unless this filter returns false. The REST API remains available for block
		// dropdowns (Featured Book, Buy Links selectors in blocks-editor.js).
		add_filter( 'use_block_editor_for_post_type', static function ( bool $use, string $post_type ): bool {
			return MBS_POST_TYPE === $post_type ? false : $use;
		}, 10, 2 );

		// C2-003: Remove the WordPress core slugdiv metabox from the book editor.
		// WordPress registers slugdiv automatically in classic editor mode. It has no
		// function in the MBS workflow — the post slug is managed via the WP title field.
		// Priority 99 ensures this runs after WP has finished registering default metaboxes.
		add_action( 'add_meta_boxes', static function (): void {
			remove_meta_box( 'slugdiv', MBS_POST_TYPE, 'normal' );
		}, 99 );
	}

	/**
	 * Register book lifecycle hooks.
	 *
	 * @return void
	 * @since 1.3.5
	 */
	public static function register_hooks(): void {
		add_action( 'delete_attachment', array( __CLASS__, 'on_delete_attachment' ) );
		add_action( 'before_delete_post', array( __CLASS__, 'on_delete_book' ) );
	}

	/**
	 * Clean up all MBS attachment-ID references when a WP attachment is
	 * permanently deleted from the media library.
	 *
	 * Covers every place the plugin stores a WP attachment ID:
	 *
	 *   Postmeta (book posts):
	 *     · mbs_spinning_video_id  — book-level fallback spinning video
	 *     · mbs_trailer_video_id   — book trailer video
	 *
	 *   mbs_format_rows table columns (per-format):
	 *     · spinning_video_id      — per-format spinning video
	 *     · cover_image_id         — per-format cover image
	 *     · audio_sample_id        — per-format audio sample
	 *
	 *   Term meta:
	 *     · mbs_series_banner_id         (mbs_series taxonomy)
	 *     · mbs_author_photo_id          (mbs_author taxonomy)
	 *     · mbs_collection_banner_id     (mbs_collection taxonomy)
	 *     · mbs_universe_banner_id       (mbs_universe taxonomy)
	 *
	 * WordPress core already cleans up _thumbnail_id on attachment delete;
	 * this method covers only MBS-owned custom fields.
	 *
	 * Uses delete_metadata() with $delete_all = true so that a single call
	 * removes the matching value from every object without needing a
	 * preceding query to enumerate affected IDs.
	 *
	 */
	public static function on_delete_attachment( int $attachment_id ): void {
		if ( $attachment_id <= 0 ) {
			return;
		}

		// ── Postmeta (book posts) ─────────────────────────────────────────────
		delete_metadata( 'post', 0, 'mbs_spinning_video_id', $attachment_id, true );
		delete_metadata( 'post', 0, 'mbs_trailer_video_id',  $attachment_id, true );

		// ── Term meta ─────────────────────────────────────────────────────────
		delete_metadata( 'term', 0, 'mbs_series_banner_id',      $attachment_id, true );
		delete_metadata( 'term', 0, 'mbs_author_photo_id',        $attachment_id, true );
		delete_metadata( 'term', 0, 'mbs_collection_banner_id',   $attachment_id, true );
		delete_metadata( 'term', 0, 'mbs_universe_banner_id',     $attachment_id, true );

		// ── mbs_format_rows table ─────────────────────────────────────────────
		MBS_Format_Row_DAO::zero_attachment_columns( $attachment_id );
	}

	/**
	 * Clean up all custom table rows when an mbs_book post is permanently deleted.
	 *
	 * Hooked onto before_delete_post so custom rows are removed before WordPress
	 * removes the post row itself. Only fires for the mbs_book post type.
	 *
	 * Deletion order: tables that JOIN against other MBS tables are cleared first
	 * (mbs_pos_inventory references mbs_format_rows; mbs_buy_link_clicks is covered
	 * inside MBS_Buy_Link_DAO::hard_delete_for_post()) so no FK-like orphan rows
	 * remain after book deletion.
	 *
	 * @param int $post_id The post ID being permanently deleted.
	 * @return void
	 */
	public static function on_delete_book( int $post_id ): void {
		if ( get_post_type( $post_id ) !== MBS_POST_TYPE ) {
			return;
		}

		// ── Step 1: tables that reference format rows or buy link IDs first ──────
		MBS_POS_Inventory_DAO::delete_for_post( $post_id );       // JOIN on format_row_id
		MBS_Buy_Link_DAO::hard_delete_for_post( $post_id );       // clicks → links
		MBS_Format_Row_DAO::hard_delete_for_post( $post_id );

		// ── Step 2: remaining per-book tables (all keyed by post_id) ─────────────
		MBS_Endorsement_DAO::delete_for_post( $post_id );
		MBS_Section_Order_DAO::delete_for_post( $post_id );
		MBS_Arc_Recipient_DAO::delete_all_for_book( $post_id );   // recipients + campaigns
		MBS_Arc_Applicant_DAO::delete_all_for_book( $post_id );
		MBS_Contributor_Book_DAO::hard_delete_for_post( $post_id );
		MBS_Book_Meta_DAO::delete( $post_id );
		MBS_Book_Stats_DAO::delete( $post_id );
		MBS_Classification_DAO::delete_all_for_post( $post_id );
		MBS_Book_Awards_DAO::delete_all( $post_id );
		MBS_Book_Territorial_Rights_DAO::delete( $post_id );
		MBS_Book_Collection_Position_DAO::delete_all_for_book( $post_id );
		MBS_Book_Club_DAO::delete_all_for_book( $post_id );
		MBS_Related_Products_DAO::delete_for_post( $post_id );
	}
}
