/* global wp */
( function () {
	const { createElement, render } = wp.element || {};
	

	if ( ! createElement || ! render ) {
		return;
	}

	function icfpNormalizeText( str ) {
		if ( ! str ) return '';
		return str.replace( /\s+/g, ' ' ).trim().toLowerCase();
	}
	
	function icfpGetBlockFromDatatext( datatext ) {
		if ( ! datatext ) return null;
	
		const marks = document.querySelectorAll(
			`mark[datatext="${ datatext }"]`
		);
	
		for ( let i = 0; i < marks.length; i++ ) {
			const blockId = findBlockIdForMark( marks[ i ] );
			if ( blockId ) {
				return {
					blockId,
					mark: marks[ i ]
				};
			}
		}
	
		return null;
	}
	

	function BlockDebugInfo( { blockId, blockName, attrs } ) {
		return createElement(
			'div',
			{ className: 'icfp-block-debug-info', style: { fontSize: '11px', opacity: 0.6 } },
			`Block: ${ blockName }`,
			createElement( 'br' ),
			`ID: ${ blockId }`,
			createElement( 'br' ),
			'Attrs: ',
			JSON.stringify( attrs )
		);
	}

	/**
	 * Find the block ID for a given mark element by traversing up the DOM
	 * @param {HTMLElement} markElement - The mark element to find the block for
	 * @returns {string|null} - The block ID or null if not found
	 */
	function findBlockIdForMark( markElement ) {
		let current = markElement;
		while ( current && current !== document.body ) {
			if ( current.hasAttribute && current.hasAttribute( 'data-icfp-block-id' ) ) {
				return current.getAttribute( 'data-icfp-block-id' );
			}
			current = current.parentElement;
		}
		return null;
	}

	/**
	 * Update data-block-id on cf-inline-feedback-wrapper elements based on their associated marks
	 */
	function updateCommentWrapperBlockIds() {
		
		// Find all comment wrappers
		const commentWrappers = document.getElementsByClassName( 'cf-inline-feedback-wrapper' );
		
		for ( let i = 0; i < commentWrappers.length; i++ ) {
			const wrapper = commentWrappers[ i ];
			const datatext = wrapper.getAttribute( 'data-datatext' );
			const commentId = wrapper.getAttribute( 'data-comment-id' );
			const commentContent = wrapper.getAttribute( 'data-content' );
			const currentBlockId = wrapper.getAttribute( 'data-block-id' );
			
			// Skip if no datatext and no comment-id
			if ( ! datatext && ! commentId ) {
				continue;
			}
			

			
			// Find the mark element - try datatext first, then comment-id
			const contentAreas = document.getElementsByClassName( 'entry-content' );
			const postContent = document.getElementsByClassName( 'wp-block-post-content' );
			const searchContainers = [];
			
			if ( contentAreas.length > 0 ) {
				for ( let j = 0; j < contentAreas.length; j++ ) {
					searchContainers.push( contentAreas[ j ] );
				}
			}
			if ( postContent.length > 0 ) {
				for ( let j = 0; j < postContent.length; j++ ) {
					searchContainers.push( postContent[ j ] );
				}
			}
			
			let markElement = null;
			
			// First, try to find by datatext (most reliable)
			if ( datatext ) {
				for ( let c = 0; c < searchContainers.length && !markElement; c++ ) {
					const container = searchContainers[ c ];
					const marks = container.getElementsByTagName( 'mark' );
					const spans = container.getElementsByTagName( 'span' );
					
					// Check mark elements
					// for ( let m = 0; m < marks.length && !markElement; m++ ) {
					// 	const mark = marks[ m ];
					// 	const markDatatext = mark.getAttribute( 'datatext' );
					// 	if ( markDatatext === datatext ) {
					// 		// Verify text content matches if commentContent is available
					// 		if ( commentContent ) {
					// 			const markText = mark.textContent?.trim().toLowerCase().replace( /\s+/g, ' ' );
					// 			const normalizedCommentText = commentContent.trim().toLowerCase().replace( /\s+/g, ' ' );
								
					// 			if ( markText && normalizedCommentText && markText.includes( normalizedCommentText ) ) {
					// 				markElement = mark;
					// 					datatext: datatext,
					// 					markText: mark.textContent?.trim().substring( 0, 50 ),
					// 					commentContent: commentContent.substring( 0, 50 )
					// 				} );
					// 				break;
					// 			} else {
					// 				console.warn( 'Mark with datatext found but text does not match:', {
					// 					datatext: datatext,
					// 					markText: mark.textContent?.trim().substring( 0, 50 ),
					// 					commentContent: commentContent.substring( 0, 50 )
					// 				} );
					// 			}
					// 		} else {
					// 			// No commentContent to verify, use the mark
					// 			markElement = mark;
					// 			break;
					// 		}
					// 	}
					// }
					
					// // Check span elements if mark not found
					// if ( !markElement ) {
					// 	for ( let s = 0; s < spans.length && !markElement; s++ ) {
					// 		const span = spans[ s ];
					// 		const spanDatatext = span.getAttribute( 'datatext' );
					// 		if ( spanDatatext === datatext ) {
					// 			// Verify text content matches if commentContent is available
					// 			if ( commentContent ) {
					// 				const spanText = span.textContent?.trim().toLowerCase().replace( /\s+/g, ' ' );
					// 				const normalizedCommentText = commentContent.trim().toLowerCase().replace( /\s+/g, ' ' );
									
					// 				if ( spanText && normalizedCommentText && spanText.includes( normalizedCommentText ) ) {
					// 					markElement = span;
					// 						datatext: datatext,
					// 						spanText: span.textContent?.trim().substring( 0, 50 ),
					// 						commentContent: commentContent.substring( 0, 50 )
					// 					} );
					// 					break;
					// 				} else {
					// 					console.warn( 'Span with datatext found but text does not match:', {
					// 						datatext: datatext,
					// 						spanText: span.textContent?.trim().substring( 0, 50 ),
					// 						commentContent: commentContent.substring( 0, 50 )
					// 					} );
					// 				}
					// 			} else {
					// 				// No commentContent to verify, use the span
					// 				markElement = span;
					// 				break;
					// 			}
					// 		}
					// 	}
					// }
				}
			}
			
			// If not found by datatext, try to find by comment-id (for older comments)
			// if ( ! markElement && commentId ) {
			// 	const markId = `icfp-highlight-${commentId}`;
			// 	let foundMarkWithWrongText = false;
				
			// 	for ( let c = 0; c < searchContainers.length && !markElement; c++ ) {
			// 		const container = searchContainers[ c ];
			// 		const marks = container.getElementsByTagName( 'mark' );
					
			// 		// Check mark elements by id
			// 		for ( let m = 0; m < marks.length && !markElement; m++ ) {
			// 			const mark = marks[ m ];
			// 			if ( mark.id === markId || mark.getAttribute( 'data-icfp-highlight-id' ) === markId ) {
			// 				// Verify text content matches if commentContent is available
			// 				if ( commentContent ) {
			// 					const markText = mark.textContent?.trim().toLowerCase().replace( /\s+/g, ' ' );
			// 					const normalizedCommentText = commentContent.trim().toLowerCase().replace( /\s+/g, ' ' );
								
			// 					if ( markText && normalizedCommentText && markText.includes( normalizedCommentText ) ) {
			// 						markElement = mark;
			// 							commentId: commentId,
			// 							markText: mark.textContent?.trim().substring( 0, 50 ),
			// 							commentContent: commentContent.substring( 0, 50 )
			// 						} );
			// 						break;
			// 					} else {
			// 						// Mark has the right ID but wrong text - don't use it, but note that we found it
			// 						foundMarkWithWrongText = true;
			// 						console.warn( 'Mark with comment-id found but text does not match (will search by text instead):', {
			// 							commentId: commentId,
			// 							markText: mark.textContent?.trim().substring( 0, 50 ),
			// 							commentContent: commentContent.substring( 0, 50 )
			// 						} );
			// 					}
			// 				} else {
			// 					// No commentContent to verify, use the mark
			// 					markElement = mark;
			// 					break;
			// 				}
			// 			}
			// 		}
			// 	}
				
			// 	// If we found a mark with the right ID but wrong text, don't use it
			// 	// We'll search by text content instead (see below)
			// }
			
			// If still not found and we have commentContent, try searching by text content
			// This handles cases where:
			// 1. Comments without datatext that weren't restored
			// 2. Marks with wrong text content (data mismatch)
			// if ( ! markElement && commentContent ) {
			// 	const normalizedCommentText = commentContent.trim().toLowerCase().replace( /\s+/g, ' ' );
			// 	const expectedMarkId = commentId ? `icfp-highlight-${commentId}` : null;
				
			// 	for ( let c = 0; c < searchContainers.length && !markElement; c++ ) {
			// 		const container = searchContainers[ c ];
			// 		const marks = container.getElementsByTagName( 'mark' );
					
			// 		// Search for marks that contain the comment text
			// 		for ( let m = 0; m < marks.length && !markElement; m++ ) {
			// 			const mark = marks[ m ];
			// 			const markText = mark.textContent?.trim().toLowerCase().replace( /\s+/g, ' ' );
						
			// 			// Check if mark text matches comment content (exact or contains)
			// 			if ( markText && normalizedCommentText && markText.includes( normalizedCommentText ) ) {
			// 				const markId = mark.id || mark.getAttribute( 'data-icfp-highlight-id' );
							
			// 				// Prefer marks that don't have an ID (likely not yet associated) or have the expected ID
			// 				// Avoid marks that have a different comment ID
			// 				if ( expectedMarkId ) {
			// 					if ( markId === expectedMarkId ) {
			// 						// Perfect match - ID and text both match
			// 						markElement = mark;
			// 							commentId: commentId,
			// 							markText: mark.textContent?.trim().substring( 0, 50 ),
			// 							commentContent: commentContent.substring( 0, 50 )
			// 						} );
			// 						break;
			// 					} else if ( ! markId || markId === '' ) {
			// 						// Mark has no ID - could be the right one, but verify no other mark has the expected ID
			// 						// Check if there's already a mark with the expected ID (which we rejected earlier due to wrong text)
			// 						let hasExpectedIdMark = false;
			// 						for ( let checkM = 0; checkM < marks.length; checkM++ ) {
			// 							const checkMark = marks[ checkM ];
			// 							const checkMarkId = checkMark.id || checkMark.getAttribute( 'data-icfp-highlight-id' );
			// 							if ( checkMarkId === expectedMarkId ) {
			// 								hasExpectedIdMark = true;
			// 								break;
			// 							}
			// 						}
									
			// 						if ( ! hasExpectedIdMark ) {
			// 							// No mark with expected ID exists, use this one
			// 							markElement = mark;
			// 							// Set the ID on this mark for future reference
			// 							mark.setAttribute( 'id', expectedMarkId );
			// 							mark.setAttribute( 'data-icfp-highlight-id', expectedMarkId );
			// 								commentId: commentId,
			// 								markText: mark.textContent?.trim().substring( 0, 50 ),
			// 								commentContent: commentContent.substring( 0, 50 )
			// 							} );
			// 							break;
			// 						}
			// 					}
			// 					// If mark has a different ID, skip it (it belongs to another comment)
			// 				} else {
			// 					// No commentId to verify, use the first matching mark
			// 					markElement = mark;
			// 						markText: mark.textContent?.trim().substring( 0, 50 ),
			// 						commentContent: commentContent.substring( 0, 50 )
			// 					} );
			// 					break;
			// 				}
			// 			}
			// 		}
			// 	}
			// }
			
			// If mark found, get its block ID and update the wrapper
			// if ( markElement ) {
			// 	const blockId = findBlockIdForMark( markElement );
			// 	if ( blockId ) {
			// 		// Only update if block ID is different or wrapper doesn't have one
			// 		if ( currentBlockId !== blockId || ! currentBlockId ) {
			// 			wrapper.setAttribute( 'data-block-id', blockId );
			// 				datatext: datatext,
			// 				commentId: commentId,
			// 				oldBlockId: currentBlockId,
			// 				newBlockId: blockId
			// 			} );
			// 		} else {
			// 		}
			// 	} else {
			// 		console.warn( 'Could not find block ID for mark element:', markElement );
			// 	}
			// } else {
			// 	console.warn( 'Mark element not found for:', {
			// 		datatext: datatext,
			// 		commentId: commentId,
			// 		commentContent: commentContent?.substring( 0, 50 )
			// 	} );
			// }
			// Check if function exists (it's defined in elementor.js which may not be loaded)
			if ( typeof icfpHighlightTextInBlock === 'function' && datatext ) {

				const resolved = icfpGetBlockFromDatatext( datatext );
			
				// ❌ HARD STOP if block cannot be resolved
				if ( ! resolved || ! resolved.blockId ) {
					console.warn(
						'Highlight aborted – block not resolved for datatext',
						datatext
					);
					return;
				}
			
				// ❌ Prevent wrong-block rebinding
				if ( currentBlockId && currentBlockId !== resolved.blockId ) {
					console.warn(
						'Block mismatch detected – stopping rebind',
						{
							expected: currentBlockId,
							found: resolved.blockId,
							datatext
						}
					);
					return;
				}
			
				icfpHighlightTextInBlock({
					blockId: resolved.blockId,
					searchText: commentContent,
					datatext,
					commentId
				});
			}
			
		}

		
	}

	document.addEventListener( 'DOMContentLoaded', function () {
		// Only look for blocks inside .entry-content or .wp-block-post-content sections.
		// This ensures we only process blocks that are part of the main post content,
		// not blocks in widgets, sidebars, headers, footers, etc.
		const contentAreas = document.getElementsByClassName( 'entry-content' );
		const postContent = document.getElementsByClassName( 'wp-block-post-content' );
		const contentContainers = [];
		
		if ( contentAreas.length > 0 ) {
			for ( let i = 0; i < contentAreas.length; i++ ) {
				contentContainers.push( contentAreas[ i ] );
			}
		}
		if ( postContent.length > 0 ) {
			for ( let i = 0; i < postContent.length; i++ ) {
				contentContainers.push( postContent[ i ] );
			}
		}
		
		if ( contentContainers.length === 0 ) {
			return;
		}

		const blocks = [];
		contentContainers.forEach( function ( container ) {
			// Use getElementsByTagName for common block tags instead of querySelector
			const commonBlockTags = [ 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'div', 'ul', 'ol', 'li' ];
			for ( let t = 0; t < commonBlockTags.length; t++ ) {
				const elements = container.getElementsByTagName( commonBlockTags[ t ] );
				for ( let i = 0; i < elements.length; i++ ) {
					const el = elements[ i ];
					if ( el.hasAttribute && el.hasAttribute( 'data-icfp-block-id' ) ) {
						blocks.push( el );
					}
				}
			}
		} );

		blocks.forEach( function ( node ) {
			const blockId   = node.getAttribute( 'data-icfp-block-id' );
			const blockName = node.getAttribute( 'data-icfp-block-name' );
			const attrsJson = node.getAttribute( 'data-icfp-block-attrs' ) || '{}';

			let attrs = {};
			try {
				attrs = JSON.parse( attrsJson );
			} catch ( e ) {
				attrs = {};
			}

			// Create a container inside the block for any React UI.
			const mountNode = document.createElement( 'div' );
			mountNode.className = 'icfp-block-react-root';
			node.appendChild( mountNode );

			// This component is just a debug/example UI. You can replace it
			// with your inline-comment tooling that needs blockId/attrs.
			render(
				createElement( BlockDebugInfo, { blockId, blockName, attrs } ),
				mountNode
			);
		} );
		
		// Update comment wrapper block IDs after a short delay to ensure marks are restored
		// Use multiple timeouts to catch marks that are restored at different times
		setTimeout( function () {
			updateCommentWrapperBlockIds();
		}, 500 );
		
		setTimeout( function () {
			updateCommentWrapperBlockIds();
		}, 2000 );
		
		// Also update when marks might be restored later
		// Listen for custom event that might be fired when marks are restored
		document.addEventListener( 'icfp-marks-restored', function () {
			setTimeout( function() {
				updateCommentWrapperBlockIds();
			}, 50 ); // Small delay to ensure DOM is updated
		} );
	} );
} )();


