import { React, classnames } from '@gravityforms/libraries';
import { spacerClasses } from '@gravityforms/utils';
import FileUpload from '../../elements/FileUpload';
import Icon from '../../elements/Icon';

const { forwardRef } = React;

/**
 * @module Avatar
 * @description Renders an avatar component with optional file upload.
 *
 * @since 5.4.6
 *
 * @param {React.ReactNode|React.ReactNode[]}          [children]                                   - React element children
 * @param {Record<string, any>}                        [customAttributes]                           - Custom attributes for the component
 * @param {string|string[]|Record<string, boolean>}    [customClasses]                              - Custom classes for the component
 * @param {Record<string, any>}                        [fileUploadProps]                            - Props for the file upload component
 * @param {boolean}                                    [hasUpload=false]                            - Whether to show the upload button
 * @param {boolean}                                    [hideNoImageIcon=false]                      - Whether to show the no image icon in the background.
 * @param {boolean}                                    [hideLogo=false]                             - Whether to hide the logo
 * @param {string}                                     [imageFile='']                               - The image file for the avatar
 * @param {React.ComponentType}                        [Logo=null]                                  - The logo component
 * @param {string}                                     [noImageIcon='user']                         - The icon to show when no image is present
 * @param {string}                                     [noImageIconPrefix='gravity-component-icon'] - The icon prefix
 * @param {'xs'|'sm'|'md'|'lg'|'xl'|'2xl'}             [size='lg']                                  - The size of the avatar
 * @param {string|number|string[]|Record<string, any>} [spacing='']                                 - The spacing for the component
 * @param {React.RefObject<HTMLElement>|null}          ref                                          - Ref to the component
 *
 * @return {JSX.Element} The avatar component.
 *
 * @example
 * import Avatar from '@gravityforms/components/react/admin/modules/Avatar';
 *
 * return (
 *     <Avatar>
 *         { 'children' }
 *     </Avatar>
 * );
 *
 */
const Avatar = forwardRef( ( {
	children = null,
	customAttributes = {},
	customClasses = [],
	fileUploadProps = {},
	hasUpload = false,
	hideInitials = false,
	hideLogo = false,
	hideNoImageIcon = false,
	imageFile = '',
	initials = '',
	Logo = null,
	noImageIcon = 'user',
	noImageIconPrefix = 'gravity-component-icon',
	size = 'lg',
	spacing = '',
}, ref ) => {
	const style = {};
	if ( ! hasUpload ) {
		style.backgroundImage = `url(${ imageFile })`;
	}

	const attributes = {
		className: classnames( {
			'gform-avatar': true,
			[ `gform-avatar--size-${ size }` ]: true,
			[ `gform-avatar--has-upload` ]: hasUpload,
			[ `gform-avatar--no-image-icon-hidden` ]: hideNoImageIcon,
			...spacerClasses( spacing ),
		}, customClasses ),
		ref,
		style,
		...customAttributes,
	};

	const fileUploadAttributes = {
		fileURL: imageFile,
		uploadIcon: 'plus-regular',
		...fileUploadProps,
	};

	const noImageIconAttributes = {
		customClasses: [ 'gform-avatar__no-image-icon' ],
		icon: noImageIcon,
		iconPrefix: noImageIconPrefix,
	};

	const initialsAttributes = {
		className: 'gform-avatar__initials',
	};

	const renderLogo = () => {
		if ( Logo && ! hideLogo ) {
			return (
				<div className="gform-avatar__logo">
					<Logo />
				</div>
			);
		}
	};

	return hasUpload ? (
		<div { ...attributes }>
			<FileUpload { ...fileUploadAttributes } />
			{ ! hideInitials && <span { ...initialsAttributes }>{ initials }</span> }
			{ ! hideNoImageIcon && <Icon { ...noImageIconAttributes } /> }
			{ children }
			{ renderLogo() }
		</div>
	) : (
		<div { ...attributes }>
			{ ! hideInitials && imageFile.length === 0 && <span { ...initialsAttributes }>{ initials }</span> }
			{ ! hideNoImageIcon && imageFile.length === 0 && <Icon { ...noImageIconAttributes } /> }
			{ children }
			{ renderLogo() }
		</div>
	);
} );

Avatar.displayName = 'Avatar';

export default Avatar;
