/**
 * External dependencies.
 */
import { useEffect, memo, useCallback } from '@wordpress/element';
import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';
import { useSelect, useDispatch } from '@wordpress/data';
import { createBlocksFromInnerBlocksTemplate } from '@wordpress/blocks';

/**
 * Internal dependencies.
 */
import { useSpectraStyles } from '@spectra-hooks';
import { spectraClassNames } from '@spectra-helpers';

/**
 * The Editor Block render for Form Input Wrapper.
 *
 * @param {Object} props The element props.
 * @since 2.0.0
 * @return {Element} The rendered block.
 */
const Render = ( props ) => {
	// Destructure the required props.
	const {
		clientId,
		attributes: {
			fieldType,
			fieldPlaceholder,
			isRequired,
			fieldId,
		},
		setAttributes,
		context
	} = props;

	// Get context values from parent form
	const {
		'spectra-pro/form/formType': formType,
		'spectra-pro/form/demoFieldErrorMessage': demoFieldErrorMessage,
		'spectra-pro/form/messageOtherError': messageOtherError,
	} = context;


	const { replaceInnerBlocks, updateBlockAttributes } = useDispatch( 'core/block-editor' );

	// Check if block already has children
	const { hasChildBlocks } = useSelect( ( select ) => {
		const { getBlocks } = select( 'core/block-editor' );
		const currentBlockChildren = getBlocks( clientId );
		return {
			hasChildBlocks: currentBlockChildren.length > 0
		};
	}, [ clientId ] );

	// Function to update existing inner blocks when wrapper attributes change
	// This preserves custom icons while updating other attributes
	// Wrapped in useCallback to prevent unnecessary re-creation
	const updateExistingBlocks = useCallback( () => {
		const { getBlocks } = wp.data.select( 'core/block-editor' );
		const childBlocks = getBlocks( clientId );

		childBlocks.forEach( block => {
			if ( block.name === 'spectra-pro/form-input-label' ) {
				// Update the label's text and required state
				updateBlockAttributes( block.clientId, {
					labelText: 'First Name',
					isRequired
				} );
			} else if ( block.name === 'spectra-pro/form-field-wrapper' ) {
				// Check inner blocks of the field wrapper
				block.innerBlocks.forEach( innerBlock => {
					if ( innerBlock.name === 'spectra-pro/form-input-field' ) {
						updateBlockAttributes( innerBlock.clientId, {
							placeholder: fieldPlaceholder,
							isRequired
						} );
					} else if ( innerBlock.name === 'spectra-pro/form-icon' ) {
						// DON'T update icon attribute - preserve custom icons
						// Form-icon will use fieldType from context to determine default
					}
				} );
			}
		} );
	}, [ clientId, fieldPlaceholder, isRequired, updateBlockAttributes ] );

	// Generate unique field ID if not set
	useEffect( () => {
		if ( ! fieldId && fieldType ) {
			const uniqueId = `${formType || 'form'}_${fieldType}_${clientId}`;
			setAttributes( { fieldId: uniqueId } );
		}
	}, [ fieldType, fieldId, formType, clientId, setAttributes ] );

	// Set default field icon if not provided
	// Note: fieldIcon attribute is no longer used - form-icon block handles its own defaults based on fieldType
	// This preserves custom SVG icons set by the user

	// Create template ONLY on initial setup - following form-input-wrapper pattern
	useEffect( () => {
		// Only create template if no children exist (initial setup)
		if ( hasChildBlocks ) {
			// If children exist, update their attributes instead of recreating
			updateExistingBlocks();
			return;
		}

		const template = [];

		// Always add label - it will hide itself via context when showLabels is false
		template.push( [
			'spectra-pro/form-input-label',
			{
				labelText: 'First Name',
				isRequired
			}
		] );

		// Create input group container with icon and field
		const inputGroupChildren = [];

		// Always add icon - it will hide itself via context when showIcons is false
		// Don't set any attributes - form-icon will use fieldType from context to determine default
		// This preserves custom SVG icons
		inputGroupChildren.push( [
			'spectra-pro/form-icon',
			{}
		] );

		// Add input field
		inputGroupChildren.push( [
			'spectra-pro/form-input-field',
			{
				inputType: 'text',
				placeholder: 'Enter your first name',
				isRequired
			}
		] );

		// Add input group field wrapper
		template.push( [
			'spectra-pro/form-field-wrapper',
			{
				className: 'spectra-pro-form-input-group'
			},
			inputGroupChildren
		] );

		// Only create blocks if template is not empty
		if ( template.length > 0 ) {
			replaceInnerBlocks( clientId, createBlocksFromInnerBlocksTemplate( template ) );
		}
	}, [ hasChildBlocks, isRequired, clientId ] );

	// Create combined attributes with context values for color handling
	const combinedAttributes = {
		...props.attributes,
		labelColor: props.attributes.labelColor || context['spectra-pro/form/labelColor'],
		labelColorHover: props.attributes.labelColorHover || context['spectra-pro/form/labelColorHover'],
		inputTextColor: props.attributes.inputTextColor || context['spectra-pro/form/inputTextColor'],
		inputTextColorHover: props.attributes.inputTextColorHover || context['spectra-pro/form/inputTextColorHover'],
		inputBgColor: props.attributes.inputBgColor || context['spectra-pro/form/inputBgColor'],
		inputBgColorHover: props.attributes.inputBgColorHover || context['spectra-pro/form/inputBgColorHover'],
		iconColor: props.attributes.iconColor || context['spectra-pro/form/iconColor'],
	};

	// Configuration for useSpectraStyles hook
	const config = [
		{ key: 'labelColor', cssVar: '--spectra-label-color', className: 'spectra-label-color' },
		{ key: 'labelColorHover', cssVar: '--spectra-label-color-hover', className: 'spectra-label-color-hover' },
		{ key: 'inputTextColor', cssVar: '--spectra-input-text-color', className: 'spectra-input-text-color' },
		{ key: 'inputTextColorHover', cssVar: '--spectra-input-text-color-hover', className: 'spectra-input-text-color-hover' },
		{ key: 'inputBgColor', cssVar: '--spectra-input-bg-color', className: 'spectra-input-bg-color' },
		{ key: 'inputBgColorHover', cssVar: '--spectra-input-bg-color-hover', className: 'spectra-input-bg-color-hover' },
		{ key: 'iconColor', cssVar: '--spectra-icon-color', className: 'spectra-icon-color' },
	];

	// Generate styles and class names using useSpectraStyles hook
	const { style: generatedStyle, classNames: generatedClassNames } = useSpectraStyles( combinedAttributes, config );

	// Custom class names
	const customClassNames = [
		'spectra-pro-form-input-wrapper',
		`spectra-pro-form-input-wrapper--${fieldType}`,
		// Add error class when demo field error is enabled
		...( demoFieldErrorMessage ? ['spectra-pro-register-form__input-error'] : [] )
	];

	// Get block props
	const blockProps = useBlockProps( {
		className: spectraClassNames( [...customClassNames, ...generatedClassNames] ),
		style: generatedStyle
	} );

	// Get inner blocks props without template (template applied via useEffect)
	const innerBlocksProps = useInnerBlocksProps( blockProps, {
		allowedBlocks: [ 'spectra-pro/form-input-label', 'spectra-pro/form-field-wrapper', 'spectra-pro/form-input-field', 'spectra-pro/form-icon' ],
		templateLock: 'all',
		renderAppender: false
	} );

	return (
		<div { ...innerBlocksProps }>
			{ innerBlocksProps.children }
			{ demoFieldErrorMessage && (
				<span className="spectra-pro-register-form__field-error-message">
					{ messageOtherError || 'First name is required.' }
				</span>
			) }
		</div>
	);
};

export default memo( Render );