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

/**
 * Internal dependencies.
 */
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,
			fieldLabel,
			fieldPlaceholder,
			fieldIcon,
			isRequired,
			fieldId,
			showLabel
		},
		setAttributes,
		context
	} = props;

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

	// Get block children.
	const { hasChildBlocks } = useSelect( ( select ) => {
		const { getBlocks } = select( 'core/block-editor' );
		const currentBlockChildren = getBlocks( clientId );

		// Return the required data.
		return {
			hasChildBlocks: currentBlockChildren.length > 0
		};
	} );

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

	// Function to update existing inner blocks when wrapper attributes change
	const updateExistingBlocks = () => {
		const { getBlocks } = wp.data.select( 'core/block-editor' );
		const childBlocks = getBlocks( clientId );
		
		childBlocks.forEach( block => {
			if ( block.name === 'spectra-pro/form-input-field' ) {
				// Update the input field's placeholder
				updateBlockAttributes( block.clientId, {
					placeholder: fieldPlaceholder,
					isRequired
				} );
			} else if ( block.name === 'spectra-pro/form-input-label' ) {
				// Only update required state; never overwrite custom label text
				updateBlockAttributes( block.clientId, {
					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' ) {
						// Only update icon if it's not already set (preserve custom icons)
						const updates = {};
						// Don't override custom icon - only set if icon doesn't exist
						if ( !innerBlock.attributes.icon ) {
							updates.icon = fieldIcon;
						}
						updateBlockAttributes( innerBlock.clientId, updates );
					}
				} );
			}
		} );
	};

	// 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 label only when first created
	useEffect( () => {
		if ( fieldType && fieldLabel === undefined ) {
			// Only set default label if no label exists yet (undefined means not set)
			// Empty string means user intentionally cleared it
			const defaultLabels = {
				username: 'Username or Email',
				email: 'Email Address',
				password: 'Password',
				first_name: 'First Name',
				last_name: 'Last Name',
				confirm_password: 'Confirm Password'
			};
			const defaultLabel = defaultLabels[ fieldType ] || 'Field Label';
			setAttributes( { fieldLabel: defaultLabel } );
		}
	}, [ fieldType, fieldLabel, setAttributes ] );

	// Set default field placeholder only when first created
	useEffect( () => {
		if ( fieldType && fieldPlaceholder === undefined ) {
			// Only set default placeholder if no placeholder exists yet (undefined means not set)
			// Empty string means user intentionally cleared it
			const defaultPlaceholders = {
				username: 'Enter your username or email',
				email: 'Enter your email address',
				password: 'Enter your password',
				first_name: 'Enter your first name',
				last_name: 'Enter your last name',
				confirm_password: 'Confirm your password'
			};
			const defaultPlaceholder = defaultPlaceholders[ fieldType ] || 'Enter value...';
			setAttributes( { fieldPlaceholder: defaultPlaceholder } );
		}
	}, [ fieldType, fieldPlaceholder, setAttributes ] );

	// Set default field icon if not provided
	useEffect( () => {
		if ( ! fieldIcon && fieldType ) {
			const defaultIcons = {
				username: 'user',
				email: 'envelope',
				password: 'lock',
				first_name: 'user',
				last_name: 'user',
				confirm_password: 'lock'
			};
			setAttributes( { fieldIcon: defaultIcons[ fieldType ] || 'user' } );
		}
	}, [ fieldType, fieldIcon, setAttributes ] );

	// Update template based on show/hide settings
	useEffect( () => {
		// Only create template if no children exist (initial setup)
		if ( hasChildBlocks ) {
			// If children exist, update their attributes instead of recreating
			updateExistingBlocks();
			return;
		}

		const shouldShowLabels = showLabel !== undefined ? showLabel : parentShowLabels;
		const template = [];

		// Add label if enabled (use existing label when present, otherwise sensible defaults)
		if ( shouldShowLabels ) {
			const defaultLabels = {
				username: 'Username or Email',
				email: 'Email Address',
				password: 'Password',
				first_name: 'First Name',
				last_name: 'Last Name',
				confirm_password: 'Confirm Password'
			};
			const computedLabelText = fieldLabel || defaultLabels[ fieldType ] || 'Field Label';
			template.push( [
				'spectra-pro/form-input-label',
				{
					labelText: computedLabelText,
					isRequired
				}
			] );
		}

		// Create input field block - always present
		const inputAttributes = {
			inputType: getInputType( fieldType ),
			placeholder: fieldPlaceholder,
			isRequired
		};

		// Create input group container with icon and field
		const inputGroupChildren = [];
		
		// Always add icon - the form-icon component will handle visibility based on context
		if ( fieldIcon ) {
			inputGroupChildren.push( [
				'spectra-pro/form-icon',
				{
					icon: fieldIcon
				}
			] );
		}
		
		// Add input field
		inputGroupChildren.push( [
			'spectra-pro/form-input-field',
			inputAttributes
		] );

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

		// Replace inner blocks with the new template
		if ( template.length > 0 ) {
			replaceInnerBlocks( clientId, createBlocksFromInnerBlocksTemplate( template ) );
		}
	}, [ fieldType, fieldLabel, fieldPlaceholder, fieldIcon, isRequired, showLabel, parentShowLabels, hasChildBlocks, clientId, replaceInnerBlocks, updateBlockAttributes ] );

	// Get the input type based on field type
	const getInputType = ( type ) => {
		const inputTypes = {
			username: 'text',
			email: 'email',
			password: 'password',
			first_name: 'text',
			last_name: 'text',
			confirm_password: 'password'
		};
		return inputTypes[ type ] || 'text';
	};


	// Custom class names for form input wrapper
	const customClassNames = [
		'spectra-pro-form-input-wrapper',
		`spectra-pro-form-input-wrapper--${fieldType}`,
	];

	// Get block props with basic class names only (colors handled by parent)
	const blockProps = useBlockProps( {
		className: spectraClassNames( customClassNames )
	} );

	// Get inner blocks props
	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 } />;
};

export default memo( Render );