/**
 * EPOFW Admin Filter/Search Functionality
 *
 * Extensible filtering system for addon list page.
 * Supports both client-side and AJAX server-side search.
 *
 * @package Extra_Product_Options_For_WooCommerce
 * @since   4.4.5
 */

( function( $ ) {
	'use strict';

	/**
	 * EPOFW Admin Filter Module
	 * 
	 * Features:
	 * - AJAX server-side search (pagination compatible)
	 * - Client-side fallback
	 * - Debounced requests
	 * - Loading states
	 * - Custom filters via registerFilter()
	 */
	var EPOFW_Filter = {

		/**
		 * Configuration
		 */
		config: {
			debounceDelay: 300,
			minSearchLength: 0,
			useAjax: true,
			animationClass: 'epofw-search-match',
			hiddenClass: 'epofw-hidden',
			loadingClass: 'epofw-searching',
			cardSelector: '.epofw-addon-card',
			containerSelector: '.epofw-addons-container',
			noResultsSelector: '#epofw-no-results',
			emptyStateSelector: '#empty-state'
		},

		/**
		 * Current active filters
		 */
		activeFilters: {},

		/**
		 * Registered filter handlers (for client-side)
		 */
		filterHandlers: {},

		/**
		 * DOM Elements cache
		 */
		elements: {},

		/**
		 * Debounce timer
		 */
		debounceTimer: null,

		/**
		 * Current AJAX request
		 */
		currentRequest: null,

		/**
		 * Original cards HTML (for restoring)
		 */
		originalCardsHTML: '',

		/**
		 * Initialize the filter module
		 */
		init: function() {
			// Cache DOM elements
			this.cacheElements();

			// Only initialize if search input exists
			if ( this.elements.$searchInput.length === 0 ) {
				return;
			}

			// Store original cards HTML for restoration
			this.originalCardsHTML = this.elements.$container.html();

			// Register built-in client-side filters
			this.registerBuiltInFilters();

			// Bind events
			this.bindEvents();

			// Initialize from URL params (if any)
			this.initFromURL();
		},

		/**
		 * Cache frequently used DOM elements
		 */
		cacheElements: function() {
			this.elements = {
				$searchInput: $( '#epofw-addon-search' ),
				$clearBtn: $( '.epofw-search-clear' ),
				$searchIcon: $( '.epofw-search-icon' ),
				$searchBox: $( '.epofw-search-box' ),
				$container: $( this.config.containerSelector ),
				$noResults: $( this.config.noResultsSelector ),
				$emptyState: $( this.config.emptyStateSelector ),
				$cards: $( this.config.cardSelector ),
				$statusFilter: $( '#epofw-status-filter' ),
				$fieldTypeFilter: $( '#epofw-field-type-filter' ),
				$addonsSection: $( '.epofw-addons-section' )
			};
		},

		/**
		 * Register built-in client-side filters
		 */
		registerBuiltInFilters: function() {
			// Text Search Filter
			this.registerFilter( 'search', {
				match: function( $card, value ) {
					if ( ! value || value === '' ) {
						return true;
					}
					var searchTerm = value.toLowerCase().trim();
					var addonName  = ( $card.data( 'name' ) || '' ).toString().toLowerCase();
					var cardTitle  = $card.find( '.epofw-card-type span' ).text().toLowerCase();
					var fieldTypes = $card.find( '.epofw-card-description-item' ).text().toLowerCase();

					return addonName.indexOf( searchTerm ) !== -1 ||
						   cardTitle.indexOf( searchTerm ) !== -1 ||
						   fieldTypes.indexOf( searchTerm ) !== -1;
				}
			} );

			// Status Filter
			this.registerFilter( 'status', {
				match: function( $card, value ) {
					if ( ! value || value === '' || value === 'all' ) {
						return true;
					}
					return $card.data( 'status' ) === value;
				}
			} );
		},

		/**
		 * Register a custom filter
		 */
		registerFilter: function( name, handler ) {
			if ( typeof handler.match !== 'function' ) {
				return;
			}
			this.filterHandlers[ name ] = handler;
			this.activeFilters[ name ]  = null;
		},

		/**
		 * Bind all events
		 */
		bindEvents: function() {
			var self = this;

			// Search input with debounce
			this.elements.$searchInput.on( 'input', function() {
				var value = $( this ).val();
				self.updateSearchUI( value );
				self.setFilter( 'search', value, true );
			} );

			// Escape key clears search
			this.elements.$searchInput.on( 'keydown', function( e ) {
				if ( e.keyCode === 27 ) {
					self.clearSearch();
				}
			} );

			// Clear button
			this.elements.$clearBtn.on( 'click', function( e ) {
				e.preventDefault();
				self.clearSearch();
			} );

			// Clear search link in no results
			$( document ).on( 'click', '.epofw-clear-search-link', function( e ) {
				e.preventDefault();
				self.clearSearch();
			} );

			// Status filter dropdown
			if ( this.elements.$statusFilter.length ) {
				this.elements.$statusFilter.on( 'change', function() {
					self.setFilter( 'status', $( this ).val(), true );
				} );
			}

			// Keyboard shortcut: Ctrl/Cmd + F
			$( document ).on( 'keydown', function( e ) {
				if ( ( e.ctrlKey || e.metaKey ) && e.keyCode === 70 ) {
					if ( self.elements.$searchInput.length && self.elements.$searchInput.is( ':visible' ) ) {
						e.preventDefault();
						self.elements.$searchInput.focus().select();
					}
				}
			} );
		},

		/**
		 * Update search box UI (icon/clear button visibility)
		 */
		updateSearchUI: function( value ) {
			if ( value && value.length > 0 ) {
				this.elements.$clearBtn.show();
				this.elements.$searchIcon.hide();
			} else {
				this.elements.$clearBtn.hide();
				this.elements.$searchIcon.show();
			}
		},

		/**
		 * Set a filter value
		 */
		setFilter: function( name, value, debounce ) {
			var self = this;

			this.activeFilters[ name ] = value;

			if ( debounce ) {
				// Cancel pending request/timer
				if ( this.debounceTimer ) {
					clearTimeout( this.debounceTimer );
				}
				if ( this.currentRequest ) {
					this.currentRequest.abort();
				}

				this.debounceTimer = setTimeout( function() {
					self.applyFilters();
				}, this.config.debounceDelay );
			} else {
				this.applyFilters();
			}
		},

		/**
		 * Clear search
		 */
		clearSearch: function() {
			this.elements.$searchInput.val( '' ).focus();
			this.updateSearchUI( '' );
			this.activeFilters.search = null;
			this.activeFilters.status = 'all';

			// Cancel pending request
			if ( this.currentRequest ) {
				this.currentRequest.abort();
			}

			// Restore original cards
			this.restoreOriginalCards();

			$( document ).trigger( 'epofw_search_cleared' );
		},

		/**
		 * Apply filters - decides between AJAX or client-side
		 */
		applyFilters: function() {
			var searchTerm = this.activeFilters.search || '';
			var status     = this.activeFilters.status || 'all';

			// If no search term and status is all, restore original
			if ( searchTerm === '' && status === 'all' ) {
				this.restoreOriginalCards();
				return;
			}

			// Use AJAX if enabled
			if ( this.config.useAjax && typeof epofw_var !== 'undefined' ) {
				this.performAjaxSearch( searchTerm, status );
			} else {
				this.performClientSearch();
			}
		},

		/**
		 * Perform AJAX server-side search
		 */
		performAjaxSearch: function( searchTerm, status ) {
			var self = this;

			// Show loading state
			this.showLoading();

			// Cancel pending request
			if ( this.currentRequest ) {
				this.currentRequest.abort();
			}

			this.currentRequest = $.ajax( {
				url: epofw_var.ajaxurl,
				type: 'POST',
				data: {
					action: 'epofw_search_addons',
					nonce: epofw_var.epofw_admin_nonce,
					search: searchTerm,
					status: status,
					page: 1,
					per_page: 50
				},
				success: function( response ) {
					self.hideLoading();

					if ( response.success && response.data ) {
						self.renderSearchResults( response.data );
					} else {
						self.showNoResults();
					}
				},
				error: function( xhr, status ) {
					if ( status !== 'abort' ) {
						self.hideLoading();
						self.performClientSearch(); // Fallback to client-side
					}
				},
				complete: function() {
					self.currentRequest = null;
				}
			} );
		},

		/**
		 * Perform client-side search (fallback)
		 */
		performClientSearch: function() {
			var self       = this;
			var $cards     = $( this.config.cardSelector );
			var matchCount = 0;

			$cards.each( function() {
				var $card   = $( this );
				var matches = true;

				Object.keys( self.filterHandlers ).forEach( function( filterName ) {
					var filterValue   = self.activeFilters[ filterName ];
					var filterHandler = self.filterHandlers[ filterName ];

					if ( filterValue !== null && filterValue !== undefined && filterValue !== '' ) {
						if ( ! filterHandler.match( $card, filterValue ) ) {
							matches = false;
						}
					}
				} );

				if ( matches ) {
					$card.removeClass( self.config.hiddenClass ).addClass( self.config.animationClass );
					matchCount++;
				} else {
					$card.addClass( self.config.hiddenClass ).removeClass( self.config.animationClass );
				}
			} );

			this.updateEmptyStates( matchCount, $cards.length );
		},

		/**
		 * Render AJAX search results
		 */
		renderSearchResults: function( data ) {
			var self   = this;
			var addons = data.addons || [];

			if ( addons.length === 0 ) {
				this.showNoResults();
				return;
			}

			// Build cards HTML
			var cardsHTML = '';
			addons.forEach( function( addon ) {
				cardsHTML += self.buildAddonCardHTML( addon );
			} );

			// Update container
			this.elements.$container.html( cardsHTML ).show();
			this.elements.$noResults.hide();
			this.elements.$emptyState.hide();

			// Re-bind card action events
			this.rebindCardEvents();

			// Update stats display if needed
			this.updateSearchStats( data.total, addons.length );

			$( document ).trigger( 'epofw_search_results', [ data ] );
		},

		/**
		 * Build HTML for a single addon card
		 */
		buildAddonCardHTML: function( addon ) {
			var statusClass = addon.status;
			var fieldTypesHTML = addon.field_types.length > 0 ? addon.field_types.join( ', ' ) : '';
			var usageHTML = this.buildUsageHTML( addon.usage );

			return '<div class="epofw-addon-card epofw-search-match" data-status="' + statusClass + '" data-id="' + addon.id + '" data-name="' + addon.name.toLowerCase() + '">' +
				'<div class="epofw-card-header">' +
					'<div class="epofw-card-type"><span>' + this.escapeHtml( addon.name ) + '</span></div>' +
					'<div class="epofw-card-status ' + statusClass + '">' +
						'<span class="epofw-status-indicator"></span>' +
						addon.status_text +
					'</div>' +
				'</div>' +
				'<div class="epofw-card-body">' +
					'<div class="epofw-card-description-wrapper epofw-card-description">' +
						'<div class="epofw-card-description-item"><strong>Enabled fields types:</strong></div>' +
						'<div class="epofw-card-description-item">' + this.escapeHtml( fieldTypesHTML ) + '</div>' +
					'</div>' +
					'<div class="epofw-card-meta">' +
						'<div class="epofw-meta-item">' +
							'<i class="dashicons dashicons-clock"></i>' +
							'<span>Updated at ' + this.escapeHtml( addon.updated ) + '</span>' +
						'</div>' +
						'<div class="epofw-meta-item epofw-used-in-meta">' +
							'<i class="dashicons dashicons-visibility"></i>' +
							'<span>Used in ' + usageHTML + '</span>' +
						'</div>' +
					'</div>' +
				'</div>' +
				'<div class="epofw-card-footer">' +
					'<div class="epofw-card-actions">' +
						'<a href="' + addon.edit_url + '" class="epofw-action-btn epofw-edit-btn" title="Edit"><i class="dashicons dashicons-edit"></i></a>' +
						'<button type="button" class="epofw-action-btn epofw-duplicate-btn" title="Duplicate"><i class="dashicons dashicons-admin-page"></i></button>' +
						'<button type="button" class="epofw-action-btn epofw-export-btn" data-addon-id="' + addon.id + '" title="Export JSON"><i class="dashicons dashicons-download"></i></button>' +
						'<button type="button" class="epofw-action-btn epofw-delete-btn" title="Delete"><i class="dashicons dashicons-trash"></i></button>' +
					'</div>' +
					'<div class="epofw-card-toggle">' +
						'<button type="button" class="epofw-action-btn epofw-toggle-btn" title="' + ( addon.status === 'active' ? 'Disable' : 'Enable' ) + '">' +
							'<i class="dashicons dashicons-admin-tools"></i>' +
						'</button>' +
					'</div>' +
				'</div>' +
			'</div>';
		},

		/**
		 * Build usage HTML from usage data
		 */
		buildUsageHTML: function( usage ) {
			var parts = [];
			var total, names;

			if ( usage.products && usage.products.length > 0 ) {
				total = usage.products_total || usage.products.length;
				names = usage.products.map( function( p ) {
					return '<a href="' + p.url + '" target="_blank" class="epofw-item-link">' + p.name + '</a>';
				} ).join( ', ' );
				parts.push( total + ' ' + ( total === 1 ? 'Product' : 'Products' ) + ' (' + names + ')' );
			}

			if ( usage.categories && usage.categories.length > 0 ) {
				total = usage.categories_total || usage.categories.length;
				names = usage.categories.map( function( c ) {
					return '<a href="' + c.url + '" target="_blank" class="epofw-item-link">' + c.name + '</a>';
				} ).join( ', ' );
				parts.push( total + ' ' + ( total === 1 ? 'Category' : 'Categories' ) + ' (' + names + ')' );
			}

			if ( usage.variations && usage.variations.length > 0 ) {
				total = usage.variations_total || usage.variations.length;
				names = usage.variations.map( function( v ) {
					return '<a href="' + v.url + '" target="_blank" class="epofw-item-link">' + v.name + '</a>';
				} ).join( ', ' );
				parts.push( total + ' ' + ( total === 1 ? 'Variation' : 'Variations' ) + ' (' + names + ')' );
			}

			if ( usage.user_roles && usage.user_roles.length > 0 ) {
				total = usage.user_roles_total || usage.user_roles.length;
				names = usage.user_roles.map( function( r ) { return r.name; } ).join( ', ' );
				parts.push( total + ' ' + ( total === 1 ? 'User Role' : 'User Roles' ) + ' (' + names + ')' );
			}

			return parts.length > 0 ? parts.join( ', ' ) : '';
		},

		/**
		 * Escape HTML special characters
		 */
		escapeHtml: function( text ) {
			if ( ! text ) {
				return '';
			}
			var div = document.createElement( 'div' );
			div.textContent = text;
			return div.innerHTML;
		},

		/**
		 * Re-bind card action events after AJAX render
		 */
		rebindCardEvents: function() {
			// Events are bound with delegation in epofw-admin.js
			// Just trigger a refresh event
			$( document ).trigger( 'epofw_cards_refreshed' );
		},

		/**
		 * Show loading state
		 */
		showLoading: function() {
			this.elements.$searchBox.addClass( this.config.loadingClass );
			this.elements.$container.css( 'opacity', '0.5' );
		},

		/**
		 * Hide loading state
		 */
		hideLoading: function() {
			this.elements.$searchBox.removeClass( this.config.loadingClass );
			this.elements.$container.css( 'opacity', '1' );
		},

		/**
		 * Show no results message
		 */
		showNoResults: function() {
			this.elements.$container.hide();
			this.elements.$noResults.show();
			this.elements.$emptyState.hide();
		},

		/**
		 * Restore original cards
		 */
		restoreOriginalCards: function() {
			if ( this.originalCardsHTML ) {
				this.elements.$container.html( this.originalCardsHTML );
			}
			this.elements.$container.show();
			this.elements.$noResults.hide();
			
			// Show/hide empty state based on card count
			var cardCount = $( this.config.cardSelector ).length;
			if ( cardCount === 0 ) {
				this.elements.$emptyState.show();
			} else {
				this.elements.$emptyState.hide();
			}

			// Remove any hidden/match classes
			$( this.config.cardSelector ).removeClass( this.config.hiddenClass + ' ' + this.config.animationClass );

			this.rebindCardEvents();
		},

		/**
		 * Update empty states
		 */
		updateEmptyStates: function( matchCount, totalCards ) {
			if ( matchCount === 0 && this.hasActiveFilters() ) {
				this.elements.$noResults.show();
				this.elements.$container.hide();
				this.elements.$emptyState.hide();
			} else if ( totalCards === 0 ) {
				this.elements.$noResults.hide();
				this.elements.$container.hide();
				this.elements.$emptyState.show();
			} else {
				this.elements.$noResults.hide();
				this.elements.$container.show();
				this.elements.$emptyState.hide();
			}
		},

		/**
		 * Update search stats display
		 */
		updateSearchStats: function( total, showing ) {
			// Could add a "Showing X of Y results" message here
			$( document ).trigger( 'epofw_search_stats', [ total, showing ] );
		},

		/**
		 * Check if any filter is active
		 */
		hasActiveFilters: function() {
			var self = this;
			return Object.keys( this.activeFilters ).some( function( key ) {
				var value = self.activeFilters[ key ];
				return value !== null && value !== undefined && value !== '' && value !== 'all';
			} );
		},

		/**
		 * Initialize from URL parameters
		 */
		initFromURL: function() {
			var urlParams = new URLSearchParams( window.location.search );

			var searchParam = urlParams.get( 'addon_search' );
			if ( searchParam ) {
				this.elements.$searchInput.val( searchParam );
				this.updateSearchUI( searchParam );
				this.setFilter( 'search', searchParam );
			}

			var statusParam = urlParams.get( 'addon_status' );
			if ( statusParam && this.elements.$statusFilter.length ) {
				this.elements.$statusFilter.val( statusParam );
				this.setFilter( 'status', statusParam );
			}
		},

		/**
		 * Get current filters
		 */
		getFilters: function() {
			return $.extend( {}, this.activeFilters );
		},

		/**
		 * Refresh cards cache
		 */
		refreshCards: function() {
			this.originalCardsHTML = this.elements.$container.html();
			this.elements.$cards = $( this.config.cardSelector );
		}
	};

	// Initialize on document ready
	$( document ).ready( function() {
		EPOFW_Filter.init();
	} );

	// Expose to global scope
	window.EPOFW_Filter = EPOFW_Filter;

} )( jQuery );
