<?php
/**
 * File Path: includes/admin/tabs/authors-series/class-mbs-tab-universes.php
 *
 * Universes Tab -- Save & Render
 *
 * Manages the Settings -> Universes tab: one collapsible <details>/<summary>
 * card per mbs_universe term, with description and a drag-and-drop
 * reading-order list.
 *
 * PRO-gated: save() silently returns when mbs_is_pro() is false.
 * Toggle-gated: the tab is only visible in Settings when
 * mbs_setting_advanced_universe_enabled is 1 (Advanced tab toggle).
 *
 * Mirrors MBS_Tab_Collections. Differences:
 *   - No "Collection Type" select -- universes have no type concept.
 *   - No per-book position postmeta -- default order falls back to
 *     alphabetical title order.
 *   - Reading order stored in mbs_universe_reading_order term_meta (JSON),
 *     managed via MBS_Universe_Reading_Order_DAO.
 *   - PRO gate on save: FREE installs cannot persist reading orders.
 *
 * Owned term_meta keys:
 *   - mbs_universe_reading_order  -- JSON array of book post IDs.
 *   - mbs_term_layout             -- Layout slug override. TLA-001.
 *                                    Saved before PRO gate so FREE users
 *                                    can set per-universe layout.
 *   - mbs_universe_banner_id      -- Attachment ID for the universe banner image.
 *                                    Saved before PRO gate so PUB users can save.
 *
 * Tab slug: 'universes'
 * Nonce:    mbs_universe_save / mbs_universe_nonce
 *
 * @package    My_Book_Showroom
 * @subpackage Includes/Admin/Tabs/Authors-Series
 * @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
// phpcs:disable WordPress.Security.ValidatedSanitizedInput -- input sanitized at point of use (sanitize_text_field, absint, wp_kses_post, etc.); false positives from PHPCS not tracing sanitization helpers called before this method
class MBS_Tab_Universes extends MBS_Tab_Base {

	public function __construct() {
		add_action( 'admin_init', array( $this, 'handle_save' ) );
		add_action( 'admin_init', array( $this, 'save_global_settings' ) );
	}

	// -------------------------------------------------------------------------
	// Save accessor overrides — DUP-005 (handle_save() now in MBS_Tab_Base)
	// -------------------------------------------------------------------------

	/** @return string */
	protected function save_nonce_field(): string { return 'mbs_universe_nonce'; }
	/** @return string */
	protected function save_nonce_action(): string { return 'mbs_universe_save'; }
	/** @return string */
	protected function save_tab_slug(): string { return 'universes'; }
	/** @return string */
	protected function save_post_id_field(): string { return 'mbs_save_universe_id'; }

	/**
	 * Save extended universe fields for a single mbs_universe term.
	 *
	 * PRO-gated: reading order and description are PRO features.
	 * Banner image save runs for PRO/PUB users (placed before the PRO gate).
	 * On FREE installs, save() returns early after the layout and banner saves.
	 *
	 * @param int $term_id Validated, absint-cast term ID.
	 * @return void
	 */
	public function save( int $term_id ): void {
		if ( ! $term_id || ! term_exists( $term_id, MBS_TAX_UNIVERSE ) ) {
			return;
		}


		// ── Book Grid Layout (TLA-001) — extracted to MBS_Tab_Base::save_layout_field()
		$this->save_layout_field( $term_id );

		// ── Archive display mode (per-universe override, Sprint RO-Display 4f) ──
		$u_allowed_disp  = array( '', 'order', 'reading_order', 'both' );
		$u_disp_mode_raw = isset( $_POST['mbs_universe_archive_display_mode'][ $term_id ] )
			? sanitize_key( wp_unslash( $_POST['mbs_universe_archive_display_mode'][ $term_id ] ) )
			: '';
		$u_disp_mode = in_array( $u_disp_mode_raw, $u_allowed_disp, true ) ? $u_disp_mode_raw : '';
		if ( '' === $u_disp_mode ) {
			delete_term_meta( $term_id, 'mbs_universe_archive_display_mode' );
		} else {
			update_term_meta( $term_id, 'mbs_universe_archive_display_mode', $u_disp_mode );
		}

		// Universe banner image (F-BNR-U) — DUP-006: delegate to MBS_Tab_Base
		// Placed before the PRO early return so PUB users (who see the picker) can save.
		if ( mbs_is_pro() || mbs_is_pub() ) {
			$this->save_banner_field( $term_id, 'mbs_universe_banner_id', 'mbs_universe_banner_id' );
		}

		// PRO gate: description and reading order remain PRO-only.
		if ( ! mbs_is_pro() ) {
			return;
		}

		// -- Description -- stored on the term itself (not term_meta) -----------
		$description = isset( $_POST['mbs_universe_description'][ $term_id ] )
			? sanitize_textarea_field( wp_unslash( $_POST['mbs_universe_description'][ $term_id ] ) )
			: '';
		wp_update_term( $term_id, MBS_TAX_UNIVERSE, array( 'description' => $description ) );

		// -- Reading order (JSON-encoded array of book post IDs) ----------------
		$raw_order = isset( $_POST['mbs_universe_reading_order'][ $term_id ] )
			? (string) wp_unslash( $_POST['mbs_universe_reading_order'][ $term_id ] )
			: '';
		if ( '' !== $raw_order ) {
			$decoded = json_decode( $raw_order, true );
			if ( is_array( $decoded ) ) {
				MBS_Universe_Reading_Order_DAO::save_reading_order( $term_id, $decoded );
			}
		}
	}

	/**
	 * Save global Universe archive display mode option.
	 *
	 * Handles the standalone global settings form on the Universes sub-tab.
	 * Hooked to admin_init; exits via wp_safe_redirect (PRG pattern).
	 *
	 * @return void
	 */
	public function save_global_settings(): void {
		if ( ! isset( $_POST['mbs_universe_global_nonce'] ) ) {
			return;
		}
		if ( ! wp_verify_nonce(
			sanitize_text_field( wp_unslash( $_POST['mbs_universe_global_nonce'] ) ),
			'mbs_universe_global_save'
		) ) {
			return;
		}
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		$allowed_modes      = array( 'order', 'reading_order', 'both' );
		$universe_disp_mode = isset( $_POST['mbs_setting_universe_archive_display_mode'] )
			? sanitize_key( wp_unslash( $_POST['mbs_setting_universe_archive_display_mode'] ) )
			: 'order';
		$universe_disp_mode = in_array( $universe_disp_mode, $allowed_modes, true ) ? $universe_disp_mode : 'order';
		update_option( 'mbs_setting_universe_archive_display_mode', $universe_disp_mode );
		wp_safe_redirect( add_query_arg( array(
			'page'    => 'my-book-showroom-settings',
			'tab'     => 'universes',
			'updated' => '1',
		), admin_url( 'admin.php' ) ) );
		exit;
	}

	// -------------------------------------------------------------------------
	// Enqueue
	// -------------------------------------------------------------------------

	/**
	 * Enqueue Universes tab assets when this tab is active.
	 *
	 * @param string $current_tab The active tab slug.
	 * @return void
	 */
	public function enqueue( string $current_tab ): void {
		if ( 'universes' !== $current_tab ) {
			return;
		}

		$this->enqueue_entity_base_assets();

		wp_enqueue_style(
			'mbs-admin-settings-universes',
			plugins_url( 'assets/css/mbs-admin-settings-universes.css', MBS_DIR . 'bookshowroom.php' ),
			array( 'mbs-admin-settings' ),
			MBS_VERSION
		);

		wp_enqueue_script(
			'mbs-admin-universes',
			plugins_url( 'assets/js/adminjs/admin-universes.js', MBS_DIR . 'bookshowroom.php' ),
			array( 'jquery', 'jquery-ui-sortable', 'mbs-admin-utils', 'wp-i18n' ),
			MBS_VERSION,
			true
		);
		wp_set_script_translations( 'mbs-admin-universes', 'my-book-showroom', MBS_DIR . 'languages' );

		// Live filter + A-Z collapse/expand (shared with Authors, Series, Collections).
		wp_enqueue_script(
			'mbs-admin-filter',
			plugins_url( 'assets/js/adminjs/mbs-admin-filter.js', MBS_DIR . 'bookshowroom.php' ),
			array(),
			MBS_VERSION,
			true
		);

		// F-SORT-2: Sort preference toggle.
		wp_enqueue_script(
			'mbs-admin-sort-pref',
			plugins_url( 'assets/js/adminjs/mbs-admin-sort-pref.js', MBS_DIR . 'bookshowroom.php' ),
			array(),
			MBS_VERSION,
			true
		);
		$this->localize_sort_pref( 'universes', array( 'name', 'name_sort' ), 'name' );
	}

	// -------------------------------------------------------------------------
	// Render
	// -------------------------------------------------------------------------

	/**
	 * Render the Universes tab.
	 *
	 * Delegates to MBS_Tab_Universes_Render::render().
	 *
	 * @return void
	 */
	public function render(): void {
		MBS_Tab_Universes_Render::render();
	}

}
