<?php
/**
 * File Path: includes/metaboxes/class-mbs-metabox-contributors.php
 *
 * My Book Showroom — Contributors Metabox
 *
 * F-020 Phase 5 refactor: uses mbs_contributor taxonomy terms +
 * mbs_book_contributors pivot table via MBS_Contributor_Book_DAO.
 * Replaces the old MBS_Contributor_DAO / mbs_contributors table.
 *
 * Roles: ONIX List 17 curated 21-role subset (via MBS_Contributor_Book_DAO).
 * Statement field: PUB-gated per-assignment override.
 *
 * @package MyBookShowroom
 * @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_Metabox_Contributors 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
	// -------------------------------------------------------------------------

	public function render( WP_Post $post ): void {
		wp_nonce_field( 'mbs_contributors_nonce', 'mbs_contributors_nonce' );

		$contributors = MBS_Contributor_Book_DAO::get_by_post( $post->ID );
		$role_options = MBS_Contributor_Book_DAO::get_role_options();
		$is_pub       = mbs_is_pub();
		?>
		<p class="description" style="margin-bottom:12px;">
			<?php esc_html_e( 'Use this section for Illustrators, Translators, Editors, Narrators, and other contributors. Author (ONIX role A01) is managed via the Author field in Book Header and is automatically included in ONIX exports — do not add it here.', 'my-book-showroom' ); ?>
		</p>
		<div class="mbs-repeater" id="mbs-contributors-repeater">

			<div class="mbs-repeater-rows" id="mbs-contributors-rows">
				<?php foreach ( $contributors as $row ) : ?>
					<?php $this->render_row( $row, $role_options, $is_pub ); ?>
				<?php endforeach; ?>
			</div>

			<div id="contributors-row-template" class="mbs-contributor-row-template" style="display:none;">
				<?php $this->render_row( null, $role_options, $is_pub ); ?>
			</div>

			<button type="button" class="button mbs-add-contributor-row" style="margin-top:12px;">
				<?php esc_html_e( '+ Add Contributor', 'my-book-showroom' ); ?>
			</button>

		</div>
		<?php
	}

	/**
	 * Render a single contributor row.
	 * $row is null when rendering the hidden template.
	 */
	private function render_row( ?object $row, array $role_options, bool $is_pub ): void {
		$is_template = ( null === $row );
		$id          = $is_template ? '' : (int) $row->id;
		$name        = $is_template ? '' : ( $row->contributor_name ?? '' );
		$role_code   = $is_template ? 'A01' : ( $row->onix_role_code ?? 'A01' );
		$role_label  = $is_template ? '' : ( $row->role_label ?? '' );
		$public      = $is_template ? 1   : (int) ( $row->public ?? 1 );
		$sort_order  = $is_template ? 0   : (int) ( $row->sort_order ?? 0 );
		$statement   = $is_template ? '' : ( $row->statement ?? '' );
		$row_attr    = $is_template ? '' : ' data-row-id="' . esc_attr( $id ) . '"';
		?>
		<div class="mbs-contributor-row" style="display:flex;align-items:flex-start;flex-wrap:wrap;gap:6px;margin-bottom:6px;"<?php echo $row_attr;  // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>

			<input type="hidden" name="mbs_contributor_id[]"   value="<?php echo esc_attr( $id ); ?>">
			<input type="hidden" name="mbs_contributor_sort[]" value="<?php echo esc_attr( $sort_order ); ?>" class="mbs-contributor-sort-input">

			<!-- ── Drag handle (primary) + ▲▼ fallback ───────────────────── -->
			<span class="mbs-drag-handle dashicons dashicons-menu"
			      style="cursor:move;color:#999;font-size:20px;margin-top:4px;flex-shrink:0;"
			      title="<?php esc_attr_e( 'Drag to reorder', 'my-book-showroom' ); ?>"
			      aria-hidden="true"></span>
			<span class="mbs-contributor-sort-controls" style="display:none;flex-shrink:0;margin-top:2px;">
				<button type="button" class="button button-small mbs-contributor-move-up"   title="<?php esc_attr_e( 'Move up', 'my-book-showroom' ); ?>" aria-label="<?php esc_attr_e( 'Move up', 'my-book-showroom' ); ?>">&#9650;</button>
				<button type="button" class="button button-small mbs-contributor-move-down" title="<?php esc_attr_e( 'Move down', 'my-book-showroom' ); ?>" aria-label="<?php esc_attr_e( 'Move down', 'my-book-showroom' ); ?>">&#9660;</button>
			</span>

			<div class="mbs-field" style="display:inline-block;margin-right:8px;">
				<input type="text" name="mbs_contributor_name[]"
					value="<?php echo esc_attr( $name ); ?>"
					class="regular-text"
					placeholder="<?php esc_attr_e( 'Contributor name', 'my-book-showroom' ); ?>">
			</div>

			<div class="mbs-field" style="display:inline-block;margin-right:8px;">
				<select name="mbs_contributor_role[]" class="mbs-contributor-role-select">
					<option value=""><?php esc_html_e( '— Role —', 'my-book-showroom' ); ?></option>
					<?php foreach ( $role_options as $code => $label ) : ?>
						<option value="<?php echo esc_attr( $code ); ?>" <?php selected( $role_code, $code ); ?>>
							<?php echo esc_html( $code . ' — ' . $label ); ?>
						</option>
					<?php endforeach; ?>
				</select>
			</div>

			<?php /* Role label — shown only when Z01 (Other) is selected */ ?>
			<div class="mbs-field" style="display:inline-block;margin-right:8px;">
				<input type="text" name="mbs_contributor_role_label[]"
					value="<?php echo esc_attr( $role_label ); ?>"
					class="mbs-contributor-custom-label regular-text"
					placeholder="<?php esc_attr_e( 'Custom role label', 'my-book-showroom' ); ?>"
					style="display:<?php echo esc_attr( 'Z01' === $role_code ? 'inline-block' : 'none' ); ?>;">
			</div>

			<label style="display:inline-block;margin-right:12px;">
				<input type="checkbox"
					name="mbs_contributor_public_<?php echo esc_attr( $is_template ? 'TMPL' : $id ); ?>"
					class="mbs-contributor-public-cb"
					value="1"
					<?php checked( $public, 1 ); ?>>
				<?php esc_html_e( 'Public', 'my-book-showroom' ); ?>
			</label>
			<input type="hidden" name="mbs_contributor_public[]" value="<?php echo esc_attr( $public ); ?>" class="mbs-contributor-public-hidden">

			<?php if ( $is_pub ) : ?>
			<div class="mbs-field" style="display:block;margin-top:6px;">
				<textarea name="mbs_contributor_statement[]"
					rows="2"
					class="large-text"
					placeholder="<?php esc_attr_e( 'Contributor statement (PUB)', 'my-book-showroom' ); ?>"><?php echo esc_textarea( $statement ); ?></textarea>
			</div>
			<?php else : ?>
				<!-- MBS: contributor statement requires PUB license -->
				<input type="hidden" name="mbs_contributor_statement[]" value="">
			<?php endif; ?>

			<button type="button" class="button mbs-remove-contributor-row" style="margin-left:4px;">
				<?php esc_html_e( 'Remove', 'my-book-showroom' ); ?>
			</button>

		</div>
		<?php
	}

	// -------------------------------------------------------------------------
	// Save
	// -------------------------------------------------------------------------

	public function save( int $post_id, WP_Post $post ): void {
		if ( ! $this->verify_save( $post_id, 'mbs_contributors_nonce', 'mbs_contributors_nonce' ) ) {
			return;
		}

		$names       = wp_unslash( $_POST['mbs_contributor_name']      ?? array() );
		$roles       = wp_unslash( $_POST['mbs_contributor_role']      ?? array() );
		$role_labels = wp_unslash( $_POST['mbs_contributor_role_label'] ?? array() );
		$publics     = wp_unslash( $_POST['mbs_contributor_public']    ?? array() );
		$sorts       = wp_unslash( $_POST['mbs_contributor_sort']      ?? array() );
		$ids         = wp_unslash( $_POST['mbs_contributor_id']        ?? array() );
		$statements  = wp_unslash( $_POST['mbs_contributor_statement'] ?? array() );

		$valid_roles = array_keys( MBS_Contributor_Book_DAO::get_role_options() );
		$is_pub      = mbs_is_pub();
		$count       = count( $names );
		$keep_ids    = array();

		for ( $i = 0; $i < $count; $i++ ) {
			$name = sanitize_text_field( $names[ $i ] ?? '' );
			if ( '' === $name ) {
				continue;
			}

			$role_code = strtoupper( sanitize_text_field( $roles[ $i ] ?? '' ) );
			if ( ! in_array( $role_code, $valid_roles, true ) ) {
				continue;
			}
			// A01 (Author) is managed via mbs_author taxonomy — block here to prevent ONIX duplication.
			if ( 'A01' === $role_code ) {
				continue;
			}

			// Resolve or create contributor term.
			$term = term_exists( $name, MBS_TAX_CONTRIBUTOR );
			if ( ! $term ) {
				$term = wp_insert_term( $name, MBS_TAX_CONTRIBUTOR );
			}
			if ( is_wp_error( $term ) ) {
				continue;
			}
			$term_id = is_array( $term ) ? (int) $term['term_id'] : (int) $term;

			$data = array(
				'term_id'        => $term_id,
				'onix_role_code' => $role_code,
				'role_label'     => ( 'Z01' === $role_code )
					? sanitize_text_field( $role_labels[ $i ] ?? '' )
					: '',
				'sort_order'     => absint( $sorts[ $i ] ?? $i ),
				'public'         => (int) (bool) ( $publics[ $i ] ?? 0 ),
				'statement'      => $is_pub
					? sanitize_textarea_field( $statements[ $i ] ?? '' )
					: '',
			);

			$row_id = ! empty( $ids[ $i ] ) ? (int) $ids[ $i ] : 0;
			if ( $row_id > 0 ) {
				MBS_Contributor_Book_DAO::update( $row_id, $data );
				$keep_ids[] = $row_id;
			} else {
				$data['post_id'] = $post_id;
				$new_id = MBS_Contributor_Book_DAO::insert( $data );
				if ( $new_id ) {
					$keep_ids[] = $new_id;
				}
			}
		}

		MBS_Contributor_Book_DAO::soft_delete_missing_for_post( $post_id, $keep_ids );
	}

	/**
	 * 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 );
	}

}
