<?php
/**
 * File Path: includes/admin/tabs/authors-series/class-mbs-tab-series-render.php
 *
 * Series Tab — Render Class
 *
 * @package    My_Book_Showroom
 * @subpackage Includes/Admin/Tabs/Authors-Series
 * @since      1.0.0
 */

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

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

	/**
	 * Render the Series tab.
	 *
	 * Outputs the tab wrapper, the success notice (when redirected after save),
	 * and one <form>-wrapped <details> card per series term. The card whose
	 * term_id matches the 'saved' query arg auto-expands via the 'open'
	 * attribute so the admin lands focused on the row they just edited.
	 *
	 * @return void
	 */
	public static function render(): void {
		$updated  = isset( $_GET['updated'] ) && '1' === $_GET['updated']; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$saved_id = isset( $_GET['saved'] ) ? absint( $_GET['saved'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended

		// F-SORT-2: Read per-user sort preference (default: name).
		$sort_pref = (string) get_user_meta( get_current_user_id(), 'mbs_sort_pref_series', true );
		if ( ! in_array( $sort_pref, array( 'name', 'name_sort' ), true ) ) {
			$sort_pref = 'name';
		}

		$series = get_terms( array(
			'taxonomy'   => MBS_TAX_SERIES,
			'hide_empty' => false,
			'orderby'    => 'name',
			'order'      => 'ASC',
		) );

		// F-SORT-2: When sort is name_sort, re-sort in PHP using mbs_sort_key.
		if ( ! is_wp_error( $series ) && ! empty( $series ) && 'name_sort' === $sort_pref ) {
			usort( $series, static function ( $a, $b ) {
				$ka = (string) get_term_meta( $a->term_id, 'mbs_sort_key', true );
				$kb = (string) get_term_meta( $b->term_id, 'mbs_sort_key', true );
				if ( '' === $ka ) {
					$ka = function_exists( 'mbs_compute_sort_key' ) ? mbs_compute_sort_key( $a->name ) : strtolower( $a->name );
				}
				if ( '' === $kb ) {
					$kb = function_exists( 'mbs_compute_sort_key' ) ? mbs_compute_sort_key( $b->name ) : strtolower( $b->name );
				}
				return strcmp( $ka, $kb );
			} );
		}

		// Group series by first letter; non-alpha names go under '#'.
		// When sort is name_sort, group by the first character of mbs_sort_key.
		$grouped = array();
		if ( ! is_wp_error( $series ) && ! empty( $series ) ) {
			foreach ( $series as $s ) {
				if ( 'name_sort' === $sort_pref ) {
					$sort_key = (string) get_term_meta( $s->term_id, 'mbs_sort_key', true );
					$source   = '' !== $sort_key ? $sort_key : $s->name;
				} else {
					$source = $s->name;
				}
				$first = function_exists( 'mb_strtoupper' )
					? mb_strtoupper( mb_substr( $source, 0, 1 ) )
					: strtoupper( substr( $source, 0, 1 ) );
				$key               = ctype_alpha( $first ) ? $first : '#';
				$grouped[ $key ][] = $s;
			}
			ksort( $grouped );
			// Move '#' to the end if present.
			if ( isset( $grouped['#'] ) ) {
				$hash = $grouped['#'];
				unset( $grouped['#'] );
				$grouped['#'] = $hash;
			}
		}
		?>
		<div class="mbs-tab-series">

			<?php MBS_Tab_Catalog_Subnav::render( 'series' ); // UX-NAV-001 ?>

			<h2><?php esc_html_e( 'Series', 'my-book-showroom' ); ?><?php mbs_help_tip(
				__( 'Series Position is the publisher\'s official release numbering (Book 1, Book 2, Book 3 — the order books were published). Reading Order is a separate sequence — the order you recommend readers experience the story, which may differ from publication order (for example, a prequel published fifth might have a Reading Order position of 0.5). \'Both\' displays both rows on series archive pages.', 'my-book-showroom' ),
				__( 'Series Order vs Reading Order', 'my-book-showroom' ),
				'mbs-help-tip--wide'
			); ?></h2>
			<p class="mbs-settings-subtitle">
				<?php esc_html_e( 'Extended fields and reading-order management for each series. Click a row to expand and edit.', 'my-book-showroom' ); ?>
			</p>

			<?php if ( $updated ) : ?>
				<div class="notice notice-success inline">
					<p><?php esc_html_e( 'Saved.', 'my-book-showroom' ); ?></p>
				</div>
			<?php endif; ?>

			<!-- Sprint RO-Display 4c-i: Global Series Archive Display Mode -->
			<form method="post" action="" class="mbs-series-global-form">
				<?php wp_nonce_field( 'mbs_series_global_save', 'mbs_series_global_nonce' ); ?>
				<div class="mbs-settings-card mbs-series-global-display-card">
					<h3><?php esc_html_e( 'Series Archive Display Mode', 'my-book-showroom' ); ?></h3>
					<p class="description"><?php esc_html_e( 'Controls how books are displayed on series archive pages (can be overridden per series below).', 'my-book-showroom' ); ?></p>
					<?php
					$_mbs_series_disp_global = get_option( 'mbs_setting_series_archive_display_mode', 'order' );
					$_mbs_series_ro_on       = '1' === get_option( 'mbs_setting_show_series_reading_order', '0' );
					$_mbs_series_note        = esc_html__( 'Enable Series Reading Order in Settings -> General -> Display Options to use these options.', 'my-book-showroom' );
					$_mbs_series_disp_opts   = array(
						'order'         => __( 'Series Order only', 'my-book-showroom' ),
						'reading_order' => __( 'Reading Order only', 'my-book-showroom' ),
						'both'          => __( 'Both (Series Order + Reading Order)', 'my-book-showroom' ),
					);
					?>
					<div class="mbs-display-mode-radio-group">
					<?php foreach ( $_mbs_series_disp_opts as $_mbs_dval => $_mbs_dlabel ) :
						$_mbs_is_dis = ( ! $_mbs_series_ro_on && 'order' !== $_mbs_dval );
					?>
					<label class="mbs-display-mode-radio<?php echo esc_attr( $_mbs_is_dis ? ' mbs-disabled' : '' ); ?>">
						<input type="radio"
						       name="mbs_setting_series_archive_display_mode"
						       value="<?php echo esc_attr( $_mbs_dval ); ?>"
						       <?php checked( $_mbs_series_disp_global, $_mbs_dval ); ?>
						       <?php disabled( $_mbs_is_dis, true ); ?>>
						<span class="mbs-display-mode-label"><?php echo esc_html( $_mbs_dlabel ); ?></span>
						<?php if ( $_mbs_is_dis ) : ?><span class="description"><?php echo esc_html( $_mbs_series_note ); ?></span><?php endif; ?>
					</label>
					<?php endforeach; ?>
					</div>
					<p class="mbs-settings-actions">
						<?php submit_button( __( 'Save Display Mode', 'my-book-showroom' ), 'secondary', 'submit', false ); ?>
					</p>
				</div>
			</form>

			<?php if ( empty( $grouped ) ) : ?>
				<div class="mbs-settings-card">
					<p><?php esc_html_e( 'No series found. Add books with series first.', 'my-book-showroom' ); ?></p>
				</div>
			<?php else : ?>

				<div class="mbs-list-toolbar">
					<input type="search"
					       class="mbs-list-filter-input"
					       placeholder="<?php esc_attr_e( 'Filter by name…', 'my-book-showroom' ); ?>"
					       aria-label="<?php esc_attr_e( 'Filter series', 'my-book-showroom' ); ?>">
					<p class="description mbs-list-filter-hint">
						<?php esc_html_e( 'Type to filter the list. Results update instantly.', 'my-book-showroom' ); ?>
					</p>
					<div class="mbs-sort-toggle" role="group" aria-label="<?php esc_attr_e( 'Sort order', 'my-book-showroom' ); ?>">
						<span class="mbs-sort-toggle-label"><?php esc_html_e( 'Sort by:', 'my-book-showroom' ); ?></span>
				<?php mbs_help_tip(
					__( '\'Ignoring articles\' sorts titles by the word after a leading a, an, or the — so \'The Hunger Games\' sorts under H, not T, and \'An Ember in the Ashes\' sorts under E. This matches standard library and bookstore alphabetization practice.', 'my-book-showroom' ),
					__( 'About article-ignoring sort', 'my-book-showroom' )
				); ?>
						<button type="button"
						        class="button<?php echo 'name' === $sort_pref ? ' button-primary' : ''; ?>"
						        data-sort-pref="name"
						        <?php echo 'name' === $sort_pref ? 'aria-pressed="true"' : 'aria-pressed="false"'; ?>>
							<?php esc_html_e( 'Name', 'my-book-showroom' ); ?>
						</button>
						<button type="button"
						        class="button<?php echo 'name_sort' === $sort_pref ? ' button-primary' : ''; ?>"
						        data-sort-pref="name_sort"
						        <?php echo 'name_sort' === $sort_pref ? 'aria-pressed="true"' : 'aria-pressed="false"'; ?>>
							<?php esc_html_e( 'Ignoring articles', 'my-book-showroom' ); ?>
						</button>
					</div>
					<div class="mbs-list-toolbar-actions">
						<a href="<?php echo esc_url( admin_url( 'edit-tags.php?taxonomy=' . MBS_TAX_SERIES . '&post_type=' . MBS_POST_TYPE ) ); ?>" class="button">
							<?php esc_html_e( 'Add / remove series →', 'my-book-showroom' ); ?>
						</a>
						<button type="button" class="button mbs-expand-all">
							<?php esc_html_e( 'Expand all', 'my-book-showroom' ); ?>
						</button>
						<button type="button" class="button mbs-collapse-all">
							<?php esc_html_e( 'Collapse all', 'my-book-showroom' ); ?>
						</button>
					</div>
				</div>

				<div class="mbs-series-card-list">
					<?php foreach ( $grouped as $letter => $letter_series ) :
						// A letter group stays open by default.
					?>
						<details class="mbs-letter-group" open>
							<summary class="mbs-letter-group-summary">
								<span class="mbs-letter-group-label"><?php echo esc_html( $letter ); ?></span>
								<span class="mbs-letter-group-count">
									<?php /* translators: %d: number of series entries in this letter group */ printf(
										esc_html( _n( '%d series', '%d series', count( $letter_series ), 'my-book-showroom' ) ),
										count( $letter_series )
									); ?>
								</span>
							</summary>
							<div class="mbs-letter-group-body">
								<?php foreach ( $letter_series as $s ) :
									self::render_series_card( $s, $saved_id );
								endforeach; ?>
							</div>
						</details>
					<?php endforeach; ?>

					<p class="mbs-filter-no-results" hidden>
						<?php esc_html_e( 'No series match your search.', 'my-book-showroom' ); ?>
					</p>
				</div>

			<?php endif; ?>

		</div>
		<?php
	}

	/**
	 * Render a single series card via template.
	 *
	 * Prepares variables and delegates all HTML output to
	 * templates/admin/series-card.php.
	 *
	 * @param WP_Term $series   The series term.
	 * @param int     $saved_id The term_id from the 'saved' query arg (auto-expand target).
	 * @return void
	 */
	public static function render_series_card( $series, int $saved_id ): void {
		$term_id      = (int) $series->term_id;
		$book_count   = (int) $series->count;
		$description  = (string) $series->description;
		$series_display_mode = (string) get_term_meta( $term_id, 'mbs_series_archive_display_mode', true );
		$complete  = '1' === (string) get_term_meta( $term_id, 'mbs_series_complete', true );
		$is_open   = ( $term_id === $saved_id );
		$edit_url  = admin_url( 'edit-tags.php?action=edit&taxonomy=' . MBS_TAX_SERIES . '&tag_ID=' . $term_id . '&post_type=' . MBS_POST_TYPE );

		$banner_id  = (int) get_term_meta( $term_id, 'mbs_series_banner_id', true );
		$banner_url = $banner_id ? (string) wp_get_attachment_image_url( $banner_id, 'medium' ) : ''; // R5-exempt: admin series UI

		$book_ids         = MBS_Series_Reading_Order_DAO::get_ordered_book_ids( $term_id );
		$book_display_map = MBS_Series_Reading_Order_DAO::get_book_display_map( $book_ids, $term_id );
		$has_persisted    = MBS_Series_Reading_Order_DAO::has_persisted_order( $term_id );

		$meta_parts   = array();
		$meta_parts[] = sprintf(
			/* translators: %d: number of books */
			_n( '%d book', '%d books', $book_count, 'my-book-showroom' ),
			$book_count
		);
		$meta_parts[] = $complete
			? __( 'Complete', 'my-book-showroom' )
			: __( 'Ongoing', 'my-book-showroom' );
		$meta_line = implode( ' · ', $meta_parts );

		$term_layout = (string) get_term_meta( $term_id, 'mbs_term_layout', true );

		mbs_get_template_part( 'admin/series-card', array(
			'series'           => $series,
			'term_id'          => $term_id,
			'book_count'       => $book_count,
			'description'      => $description,
			'banner_id'        => $banner_id,
			'banner_url'       => $banner_url,
			'series_display_mode' => $series_display_mode,
			'complete'         => $complete,
			'is_open'          => $is_open,
			'edit_url'         => $edit_url,
			'book_ids'         => $book_ids,
			'book_display_map' => $book_display_map,
			'has_persisted'    => $has_persisted,
			'meta_line'        => $meta_line,
			'term_layout'      => $term_layout,
		) );
	}
}
