import { forwardRef, useEffect, useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import clsx from '../../../utils/clsx';
import { Icon } from '../Icon';

const sizeClasses = {
	extrasmall: 'rbfb-input__group--xs',
	small: 'rbfb-input__group--sm',
	medium: 'rbfb-input__group--md',
	large: 'rbfb-input__group--lg',
	extralarge: 'rbfb-input__group--xl',
};

const Input = forwardRef( ( props, ref ) => {
	const {
		id,
		name,
		background = 'white',
		style,
		inputStyle,
		className = '',
		gap = 10,
		inputClassName = '',
		type = 'text',
		title,
		placeholder = __( 'Type...', 'rewind-form-bridge-for-brevo' ),
		value: controlledValue = '',
		visible = true,
		disabled = false,
		readOnly = false,
		required = false,
		spellCheck = false,
		color = 'primary-light',
		inputTextColor = 'black',
		size = 'medium',
		borderStyle = 'solid',
		rounded = 'sm',
		fullWidth = true,
		customWidth,
		label,
		labelColor = 'black',
		labelFontSize = 'md',
		labelFontWeight = 'medium',
		helperText,
		error = false,
		errorText,
		prefix,
		suffix,
		searchIcon = false,
		ariaLabel,
		tabIndex,
		preventDefault = false,
		stopPropagation = false,
		onClick,
		onChange,
		onBlur,
		onKeyDown,
		...rest
	} = props;

	const [ internalValue, setInternalValue ] = useState( controlledValue );

	useEffect( () => {
		setInternalValue( controlledValue );
	}, [ controlledValue ] );

	const handleChange = ( e ) => {
		const newValue = e.target.value;
		setInternalValue( newValue );
		onChange?.( type === 'number' ? Number( newValue ) || 0 : newValue );
	};

	const handleBlur = () => {
		onBlur?.(
			type === 'number' ? Number( internalValue ) || 0 : internalValue
		);
	};

	if ( ! visible ) return null;

	const wrapperStyle = {
		...style,
		...( gap && { gap } ),
		width: fullWidth ? '100%' : customWidth,
	};

	const wrapperClass = clsx(
		'rbfb-input',
		disabled && 'rbfb-input--disabled',
		className
	);

	const inputClasses = clsx( `text-${ inputTextColor }`, inputClassName );

	const inputGroupClass = clsx(
		'rbfb-input__group',
		sizeClasses[ size ],
		`bg-${ background }`,
		`rounded-${ rounded }`,
		'border',
		error ? 'border-error' : `border-${ color }`,
		`border-${ borderStyle }`,
		searchIcon && 'rbfb-input__group--search-icon',
		prefix && 'rbfb-input__group--prefix',
		suffix && 'rbfb-input__group--suffix'
	);

	return (
		<div style={ wrapperStyle } className={ wrapperClass }>
			{ label && (
				<label
					htmlFor={ id }
					className={ clsx(
						`text-${ labelFontSize }`,
						`font-${ labelFontWeight }`,
						`text-${ labelColor }`
					) }
				>
					{ label }
					{ required && (
						<span className="rbfb-input__required">*</span>
					) }
				</label>
			) }

			<div className={ inputGroupClass }>
				{ ( prefix || searchIcon ) && (
					<span className="rbfb-input__group-prefix-icon">
						{ searchIcon ? (
							<Icon name="search" fontSize="lg" />
						) : (
							prefix
						) }
					</span>
				) }

				<input
					id={ id }
					name={ name }
					ref={ ref }
					type={ type }
					placeholder={ placeholder }
					title={ title }
					value={ internalValue }
					disabled={ disabled }
					readOnly={ readOnly }
					required={ required }
					spellCheck={ spellCheck }
					aria-label={ ariaLabel }
					aria-invalid={ error }
					aria-describedby={ error ? `${ id }-error` : undefined }
					tabIndex={ tabIndex }
					style={ inputStyle }
					className={ inputClasses }
					onClick={ ( e ) => {
						if ( preventDefault ) e.preventDefault();
						if ( stopPropagation ) e.stopPropagation();
						onClick?.( e );
					} }
					onChange={ handleChange }
					onBlur={ handleBlur }
					onKeyDown={ onKeyDown }
					{ ...rest }
				/>

				{ suffix && (
					<span className="rbfb-input__group-suffix-icon">
						{ suffix }
					</span>
				) }
			</div>

			{ ( helperText || ( error && errorText ) ) && (
				<span
					id={ error ? `${ id }-error` : undefined }
					className={ clsx(
						'rbfb-input__helper-text',
						error && 'rbfb-input-error'
					) }
				>
					{ error && errorText ? errorText : helperText }
				</span>
			) }
		</div>
	);
} );

export default Input;
