/**
 * @file assets/js/mbs-front-search.js
 * Debounced live-search with dropdown results (Spec 5 / Phase 3).
 *
 * Fires against wp_ajax_mbs_search / wp_ajax_nopriv_mbs_search.
 * Nonce and AJAX URL are read from .mbs-search-wrapper data attributes.
 * MIN_CHARS: 3 | DEBOUNCE_MS: 350 | MAX_RESULTS: 6.
 * Uses DOM construction throughout -- never innerHTML or .html() (F-003).
 *
 * @package MyBookShowroom
 * @since   1.0.0
 */

/* global jQuery */

( function( MBS, $, undefined ) {
	'use strict';

	/**
	 * Debounced live-search with dropdown results.
	 *
	 * @namespace MBS.Search
	 */
	MBS.Search = {

		MIN_CHARS:   3,
		MAX_RESULTS: 6,
		DEBOUNCE_MS: 350,
		_timer: null,

		/**
		 * Bind the delegated input handler.
		 *
		 * @return {void}
		 */
		init: function() {
			$( document ).on( 'input', '.mbs-search-input', this._onInput.bind( this ) );
		},

		/**
		 * Input event handler -- cancels pending fetch, hides results on short queries,
		 * or schedules a new fetch after DEBOUNCE_MS of silence.
		 *
		 * @param {jQuery.Event} e Input event.
		 * @return {void}
		 */
		_onInput: function( e ) {
			var $input   = $( e.currentTarget );
			var $wrap    = $input.closest( '.mbs-search-wrapper' );
			var $results = $wrap.find( '.mbs-search-results' );
			var $spinner = $wrap.find( '.mbs-search-spinner' );
			var query    = $input.val().trim();

			clearTimeout( MBS.Search._timer );

			if ( query.length < MBS.Search.MIN_CHARS ) {
				$results.empty().hide().removeAttr( 'role' );
				$spinner.hide();
				return;
			}

			var ajaxUrl = $wrap.data( 'ajaxurl' ) || '';
			var nonce   = $wrap.data( 'nonce' )   || '';

			$spinner.show();
			MBS.Search._timer = setTimeout( function() {
				MBS.Search._fetch( query, $results, $spinner, ajaxUrl, nonce );
			}, MBS.Search.DEBOUNCE_MS );
		},

		/**
		 * POST to mbs_search and render the live-results dropdown via DOM construction.
		 *
		 * Uses DOM construction (createElement + textContent) throughout -- no innerHTML
		 * or jQuery .html() to prevent XSS regardless of upstream sanitization state (F-003).
		 *
		 * @param {string} query    Trimmed search query.
		 * @param {jQuery} $results Results container element.
		 * @param {jQuery} $spinner Spinner element.
		 * @param {string} ajaxUrl  admin-ajax.php URL from wrapper data attribute.
		 * @param {string} nonce    Nonce from wrapper data attribute.
		 * @returns {void}
		 */
		_fetch: function( query, $results, $spinner, ajaxUrl, nonce ) {
			$.post( ajaxUrl, {
				action : 'mbs_search',
				query  : query,
				nonce  : nonce,
				limit  : MBS.Search.MAX_RESULTS
			}, function( response ) {
				$spinner.hide();
				$results.empty();

				var items = response && response.success &&
				           response.data && response.data.results
				           ? response.data.results : [];

				if ( ! items.length ) {
					$results.hide().removeAttr( 'role' );
					return;
				}

				var ul = document.createElement( 'ul' );
				ul.className = 'mbs-search-result-list';
				ul.setAttribute( 'role', 'listbox' );

				var max = Math.min( items.length, MBS.Search.MAX_RESULTS );
				for ( var i = 0; i < max; i++ ) {
					var book = items[ i ];

					var li = document.createElement( 'li' );
					li.setAttribute( 'role', 'option' );

					var a  = document.createElement( 'a' );
					a.href = book.permalink;

					if ( book.cover_url ) {
						var img       = document.createElement( 'img' );
						img.src       = book.cover_url;
						img.alt       = '';
						img.className = 'mbs-search-result-thumb';
						img.width     = 40;
						img.height    = 40;
						a.appendChild( img );
					}

					var textWrap       = document.createElement( 'span' );
					textWrap.className = 'mbs-result-text';

					var titleSpan         = document.createElement( 'span' );
					titleSpan.className   = 'mbs-result-title';
					titleSpan.textContent = book.title;
					textWrap.appendChild( titleSpan );

					if ( book.teaser_excerpt ) {
						var teaserSpan         = document.createElement( 'span' );
						teaserSpan.className   = 'mbs-result-teaser';
						teaserSpan.textContent = book.teaser_excerpt;
						textWrap.appendChild( teaserSpan );
					}

					a.appendChild( textWrap );
					li.appendChild( a );
					ul.appendChild( li );
				}

				$results.attr( 'role', 'listbox' ).append( ul ).show();
			} );
		}
	};

	MBS.register( function() {
		MBS.Search.init();
	} );

} )( window.MBS = window.MBS || {}, jQuery );
