/**
 * SimpleStats — HTML form conversion tracking.
 *
 * Reads window.simplestatsForms (set via wp_localize_script) for config:
 *   - ajaxUrl : admin-ajax.php endpoint URL.
 *   - action  : `action` field value (`simplestats_track_form`).
 *   - nonce   : nonce bound to the same action.
 *   - exclude : array of CSS selectors. Forms matching ANY of these are skipped.
 *
 * Behavior:
 *   - On DOMContentLoaded, find every form on the page and attach a submit listener
 *     to those that don't match the exclusion list.
 *   - On submit (once per form per page-load), POST form-encoded
 *     { action, nonce, form_id, form_name, page_url } to ajaxUrl,
 *     with keepalive:true.
 *   - Watch the DOM for late-added forms via MutationObserver.
 *   - Never preventDefault — tracking is fire-and-forget.
 *   - Never read input values — only the form element's own attributes.
 */
(function () {
	'use strict';

	var config = window.simplestatsForms;
	if ( ! config || typeof config.ajaxUrl !== 'string' || ! config.ajaxUrl ) {
		return;
	}

	var attached = new WeakSet();
	var excludeSelector = Array.isArray( config.exclude ) && config.exclude.length
		? config.exclude.join( ', ' )
		: null;

	// Derive a stable page-slug from the URL path for synthetic form ids.
	// `/blog/some-post/` -> `some-post`. `/` -> `home`. Sanitized to [a-z0-9-].
	var pageSlug = ( function () {
		var path = ( window.location.pathname || '' ).replace( /\/+$/, '' );
		var parts = path.split( '/' ).filter( Boolean );
		var raw = parts.length ? parts[ parts.length - 1 ] : 'home';
		return raw.toLowerCase().replace( /[^a-z0-9-]+/g, '-' ).replace( /^-+|-+$/g, '' ).substring( 0, 60 ) || 'home';
	}() );

	function shouldSkip( form ) {
		if ( ! excludeSelector ) {
			return false;
		}
		try {
			return form.matches( excludeSelector );
		} catch ( e ) {
			return false;
		}
	}

	// Read the form's own attribute — bypasses HTMLFormElement's named-property
	// access, which would otherwise return a child control if any input inside
	// the form has name="id" / name="name" / id="id" / id="name".
	function formAttr( form, name ) {
		var value = form.getAttribute( name );
		return value ? String( value ) : '';
	}

	function resolveFormId( form, formNumber ) {
		var id = formAttr( form, 'id' );
		if ( id ) {
			return id;
		}
		var name = formAttr( form, 'name' );
		if ( name ) {
			return name;
		}
		return 'form-' + pageSlug + '-' + formNumber;
	}

	function buildBody( form, formNumber ) {
		var body = new URLSearchParams();
		body.append( 'action', config.action || 'simplestats_track_form' );
		body.append( 'nonce', config.nonce || '' );
		body.append( 'form_id', resolveFormId( form, formNumber ) );
		body.append( 'form_name', formAttr( form, 'name' ) );
		body.append( 'page_url', window.location.href );
		return body;
	}

	function handleSubmit( form, formNumber ) {
		return function ( /* event */ ) {
			if ( form.dataset.simplestatsSubmitted === '1' ) {
				return;
			}
			form.dataset.simplestatsSubmitted = '1';

			try {
				fetch( config.ajaxUrl, {
					method     : 'POST',
					body       : buildBody( form, formNumber ),
					credentials: 'same-origin',
					keepalive  : true,
				} );
			} catch ( e ) {
				// Fire-and-forget — never block the form's native submit.
			}
		};
	}

	function attach( form, formNumber ) {
		if ( attached.has( form ) ) {
			return;
		}
		if ( shouldSkip( form ) ) {
			return;
		}
		attached.add( form );
		form.addEventListener( 'submit', handleSubmit( form, formNumber ), false );
	}

	function attachAllExisting() {
		// 1-based form number so synthetic ids read naturally (form-slug-1, form-slug-2).
		for ( var i = 0; i < document.forms.length; i++ ) {
			attach( document.forms[ i ], i + 1 );
		}
	}

	function observeNewForms() {
		if ( typeof MutationObserver !== 'function' ) {
			return;
		}
		var observer = new MutationObserver( function ( mutations ) {
			for ( var m = 0; m < mutations.length; m++ ) {
				var added = mutations[ m ].addedNodes;
				for ( var n = 0; n < added.length; n++ ) {
					var node = added[ n ];
					if ( ! node || node.nodeType !== 1 ) {
						continue;
					}
					if ( node.tagName === 'FORM' ) {
						// document.forms.length already includes the inserted node,
						// so this gives the form's 1-based position on the page.
						attach( node, document.forms.length );
					} else if ( typeof node.querySelectorAll === 'function' ) {
						var nested = node.querySelectorAll( 'form' );
						for ( var k = 0; k < nested.length; k++ ) {
							attach( nested[ k ], document.forms.length );
						}
					}
				}
			}
		} );
		observer.observe( document.body, { childList: true, subtree: true } );
	}

	function init() {
		attachAllExisting();
		observeNewForms();
	}

	if ( document.readyState === 'loading' ) {
		document.addEventListener( 'DOMContentLoaded', init );
	} else {
		init();
	}
}() );
