/**
 * Deep Link Handler for Admin Settings
 *
 * Provides automatic highlighting and scrolling to elements based on URL hash.
 * Supports nested panels and automatic accordion/panel opening.
 *
 * Works alongside query string tab navigation (e.g., ?tab=referrals#target).
 * The deep link handler processes the hash after the page loads with the correct tab.
 *
 * @since 1.1.0
 */

/**
 * Register the Deep Link Handler store with Alpine
 *
 * @param {Object} Alpine - Alpine.js instance
 */
export function registerDeepLinkHandler( Alpine ) {
	Alpine.store( 'deepLink', {
		/**
		 * Default highlight duration in milliseconds.
		 *
		 * @type {number}
		 */
		defaultDuration: 3500,

		/**
		 * CSS classes applied to highlighted elements.
		 *
		 * @type {string[]}
		 */
		highlightClasses: [
			'ring-2',
			'ring-blue-500',
			'ring-offset-2',
			'rounded-lg',
			'transition-all',
			'duration-300',
		],

		/**
		 * Initialize the deep link handler.
		 * Called automatically after Alpine starts via alpine:initialized event.
		 */
		init() {
			// Process any hash on initial page load
			this.checkDeepLink();

			// Listen for hash changes (e.g., when clicking internal links)
			window.addEventListener( 'hashchange', () => this.checkDeepLink() );

			// Listen for custom event that can be dispatched to navigate programmatically
			window.addEventListener( 'rewardswp:navigate-to', ( event ) => {
				if ( event.detail && event.detail.target ) {
					this.navigateTo( event.detail.target, event.detail.updateUrl !== false );
				}
			} );
		},

		/**
		 * Check if there's a hash in the URL and process it.
		 */
		checkDeepLink() {
			const hash = window.location.hash.replace( '#', '' );
			if ( ! hash ) {
				return;
			}

			// Longer delay to ensure Alpine has rendered tab content
			// Tab content uses x-show which needs time to render after Alpine initializes
			setTimeout( () => this.processDeepLink( hash ), 500 );
		},

		/**
		 * Process a deep link target.
		 *
		 * @param {string} targetId - The ID of the target element (without #)
		 */
		processDeepLink( targetId ) {
			// Try finding by ID first
			let element = document.getElementById( targetId );

			// Try data-deeplink-id attribute
			if ( ! element ) {
				element = document.querySelector( `[data-deeplink-id="${ targetId }"]` );
			}

			// Try with underscores replaced by hyphens (common convention difference)
			if ( ! element ) {
				const hyphenatedId = targetId.replace( /_/g, '-' );
				element = document.getElementById( hyphenatedId );
				if ( ! element ) {
					element = document.querySelector( `[data-deeplink-id="${ hyphenatedId }"]` );
				}
			}

			// Try with hyphens replaced by underscores (reverse)
			if ( ! element ) {
				const underscoredId = targetId.replace( /-/g, '_' );
				element = document.getElementById( underscoredId );
				if ( ! element ) {
					element = document.querySelector( `[data-deeplink-id="${ underscoredId }"]` );
				}
			}

			if ( ! element ) {
				return;
			}

			this.processElement( element );
		},

		/**
		 * Process a target element: open parent panels and highlight it.
		 *
		 * @param {HTMLElement} element - The target element
		 */
		processElement( element ) {
			// Open any parent panels/accordions
			this.openParentPanels( element );

			// Wait for panels to open, then scroll and highlight
			setTimeout( () => this.highlightElement( element ), 350 );
		},

		/**
		 * Walk up the DOM tree and open any collapsed panels containing the element.
		 * Handles x-show, x-collapse, and other common patterns.
		 *
		 * @param {HTMLElement} element - The target element
		 */
		openParentPanels( element ) {
			let current = element.parentElement;

			while ( current && current !== document.body ) {
				// Check for Alpine x-show panels
				if ( current.hasAttribute( 'x-show' ) ) {
					const showExpression = current.getAttribute( 'x-show' );

					// Find the controlling x-data component
					const controller = current.closest( '[x-data]' );
					if ( controller && controller._x_dataStack ) {
						// Try to find and set the controlling variable to true
						const data = controller._x_dataStack[ 0 ];
						if ( data && typeof showExpression === 'string' ) {
							// Handle simple expressions like "isOpen" or "showSection"
							const varName = showExpression.trim();
							if ( varName in data && typeof data[ varName ] === 'boolean' ) {
								data[ varName ] = true;
							}
						}
					}
				}

				// Check for Alpine x-collapse elements (they're typically controlled by x-show on parent)
				if ( current.hasAttribute( 'x-collapse' ) ) {
					// The actual control is usually x-show on the same element
					// Already handled above
				}

				// Check for details/summary elements (native HTML accordions)
				if ( current.tagName === 'DETAILS' && ! current.open ) {
					current.open = true;
				}

				// Check for common accordion patterns with hidden class
				if ( current.classList.contains( 'hidden' ) ) {
					// Look for a toggle button/trigger in the parent
					const parent = current.parentElement;
					if ( parent ) {
						const trigger = parent.querySelector( '[data-accordion-trigger], [aria-expanded]' );
						if ( trigger ) {
							trigger.click();
						}
					}
				}

				current = current.parentElement;
			}
		},

		/**
		 * Scroll to and highlight an element.
		 *
		 * @param {HTMLElement} element - The element to highlight
		 */
		highlightElement( element ) {
			// Scroll into view smoothly
			element.scrollIntoView( {
				behavior: 'smooth',
				block: 'center',
			} );

			// Add highlight classes
			element.classList.add( ...this.highlightClasses );

			// Get custom duration if specified, otherwise use default
			const duration = parseInt(
				element.getAttribute( 'data-deeplink-duration' ) || this.defaultDuration,
				10
			);

			// Remove highlight after duration
			setTimeout( () => {
				element.classList.remove( ...this.highlightClasses );
			}, duration );
		},

		/**
		 * Programmatically navigate to a target.
		 * Can be called from other Alpine components or JavaScript.
		 *
		 * @param {string} targetId - The ID of the target element (without #)
		 * @param {boolean} updateUrl - Whether to update the URL hash (default: true)
		 */
		navigateTo( targetId, updateUrl = true ) {
			if ( updateUrl ) {
				// This will trigger hashchange event which calls checkDeepLink
				window.location.hash = targetId;
			} else {
				// Directly process without updating URL
				this.processDeepLink( targetId );
			}
		},

		/**
		 * Clear the current hash from the URL without triggering navigation.
		 */
		clearHash() {
			history.pushState( '', document.title, window.location.pathname + window.location.search );
		},
	} );

	// Initialize after Alpine is fully ready
	document.addEventListener( 'alpine:initialized', () => {
		// Small delay to ensure all Alpine components are mounted
		setTimeout( () => {
			Alpine.store( 'deepLink' ).init();
		}, 100 );
	} );
}
