/**
 * @file assets/js/mbs-admin.js
 * Book list drag-and-drop ordering with jQuery UI Sortable and arrow-button fallback; loaded on the Books list screen.
 * @package MyBookShowroom
 * @since   1.0.0
 */
/* global MBS_AdminData, ajaxurl */
(function ($) {
	'use strict';
	var __ = wp.i18n.__;
	var escAttr = MBS_AdminUtils.escAttr;

	// Guard — only run when the localised data object is present (list screen).
	if ( typeof MBS_AdminData === 'undefined' || ! MBS_AdminData.orderNonce ) {
		return;
	}

	var isPro = !! ( MBS_AdminData.isPro );

	/**
	 * Collect the current row order (post IDs) from #the-list.
	 *
	 * @returns {number[]}
	 */
	function collectOrder() {
		var ids = [];
		$( '#the-list tr[id^="post-"]' ).each( function () {
			var postId = parseInt( this.id.replace( 'post-', '' ), 10 );
			if ( postId > 0 ) {
				ids.push( postId );
			}
		} );
		return ids;
	}

	/**
	 * Persist the current row order to the server via AJAX.
	 *
	 * @param {Function} [done] Optional callback on completion.
	 */
	function saveOrder( done ) {
		var $spinner = $( '.mbs-order-spinner' );
		$spinner.css( 'visibility', 'visible' );

		$.post(
			ajaxurl,
			{
				action : 'mbs_save_book_order',
				nonce  : MBS_AdminData.orderNonce,
				order  : collectOrder()
			},
			function () {
				$spinner.css( 'visibility', 'hidden' );
				if ( typeof done === 'function' ) {
					done();
				}
			}
		);
	}

	/**
	 * Refresh disabled state on fallback ▲/▼ buttons so the first row's
	 * Up and the last row's Down are never active.
	 *
	 * @param {jQuery} $list
	 */
	function updateFallbackButtons( $list ) {
		var $rows = $list.find( 'tr' );
		$rows.find( '.mbs-order-up, .mbs-order-down' ).prop( 'disabled', false );
		$rows.first().find( '.mbs-order-up' ).prop( 'disabled', true );
		$rows.last().find( '.mbs-order-down' ).prop( 'disabled', true );
	}

	/**
	 * Inject the drag-handle (or fallback ▲/▼) cell into any row in $list
	 * that does not already have one.  Safe to call repeatedly — skips rows
	 * that already have the cell.
	 *
	 * Called once at DOM ready for all existing rows, and again after every
	 * Quick Edit AJAX save so the replacement row receives its cell.
	 *
	 * @param {jQuery} $list The #the-list element.
	 */
	function injectOrderCells( $list ) {
		var hasSortable = typeof $.fn.sortable !== 'undefined' && isPro;
		var injected    = false;

		$list.find( 'tr' ).each( function () {
			if ( $( this ).find( 'td.mbs-order-col, th.mbs-order-col' ).length ) {
				return; // already injected
			}
			if ( hasSortable ) {
				$( this ).prepend(
					'<td class="mbs-order-col">' +
					'<span class="mbs-sort-handle dashicons dashicons-menu" ' +
					'      title="' + escAttr( __( 'Drag to reorder', 'my-book-showroom' ) ) + '"></span>' +
					'</td>'
				);
			} else {
				$( this ).prepend(
					'<td class="mbs-order-col mbs-order-col-fallback">' +
					'<button type="button" class="mbs-order-up" ' +
					'        title="' + escAttr( __( 'Move up', 'my-book-showroom' ) ) + '" ' +
					'        aria-label="' + escAttr( __( 'Move up', 'my-book-showroom' ) ) + '">▲</button>' +
					'<button type="button" class="mbs-order-down" ' +
					'        title="' + escAttr( __( 'Move down', 'my-book-showroom' ) ) + '" ' +
					'        aria-label="' + escAttr( __( 'Move down', 'my-book-showroom' ) ) + '">▼</button>' +
					'</td>'
				);
				injected = true;
			}
		} );

		if ( injected ) {
			updateFallbackButtons( $list );
		}
	}

	// -------------------------------------------------------------------------
	// DOM ready
	// -------------------------------------------------------------------------

	$( function () {
		var $list = $( '#the-list' );

		if ( ! $list.length ) {
			return;
		}

		// Insert handle cell header (width accommodates either icon or buttons).
		$( '#posts-filter thead tr, #posts-filter tfoot tr' ).prepend(
			'<th class="mbs-order-col" scope="col" style="width:40px;"></th>'
		);

		// Inject a spinner next to the page title — reused across saves.
		$( '#wpbody-content .wrap h1' ).after(
			'<span class="mbs-order-spinner spinner" ' +
			'style="float:none; visibility:hidden; margin-left:8px; vertical-align:middle;"></span>'
		);

		// Inject drag-handle cells into all existing rows.
		injectOrderCells( $list );

		if ( typeof $.fn.sortable !== 'undefined' && isPro ) {

			// ── Primary: drag-and-drop with hamburger handle ────────────────────

			$list.sortable( {
				handle     : '.mbs-sort-handle',
				items      : 'tr',
				axis       : 'y',
				cursor     : 'grabbing',
				placeholder: 'mbs-sort-placeholder',
				forcePlaceholderSize: true,
				helper: function ( e, $row ) {
					// Give each cloned <td> an explicit width so the helper
					// row does not collapse to a single column while dragging.
					$row.children().each( function () {
						$( this ).width( $( this ).width() );
					} );
					return $row.clone();
				},
				stop: function () {
					saveOrder();
				}
			} );

			$list.disableSelection();

		} else {

			// ── Fallback: ▲ / ▼ keyboard-style buttons ────────────────────

			updateFallbackButtons( $list );

			$list.on( 'click', '.mbs-order-up', function () {
				var $row  = $( this ).closest( 'tr' );
				var $prev = $row.prev( 'tr' );
				if ( $prev.length ) {
					$row.insertBefore( $prev );
					updateFallbackButtons( $list );
					saveOrder();
				}
			} );

			$list.on( 'click', '.mbs-order-down', function () {
				var $row  = $( this ).closest( 'tr' );
				var $next = $row.next( 'tr' );
				if ( $next.length ) {
					$row.insertAfter( $next );
					updateFallbackButtons( $list );
					saveOrder();
				}
			} );
		}

		// ── Re-inject drag-handle cell after Quick Edit row refresh ────────────
		// WordPress replaces the entire <tr> via AJAX when Quick Edit is saved.
		// The replacement row comes from WP_Posts_List_Table::single_row() which
		// only renders registered WP columns — the mbs-order-col cell is absent.
		// Listening on ajaxComplete and checking for action=inline-save
		// re-injects the cell into any row that is missing it.
		$( document ).on( 'ajaxComplete', function ( event, xhr, settings ) {
			var data = ( settings && settings.data ) ? settings.data : '';
			if ( typeof data === 'string' && data.indexOf( 'action=inline-save' ) !== -1 ) {
				injectOrderCells( $list );
			}
		} );
	} );

}( jQuery ) );
