/**
 * External dependencies
 */
import {
	useBlockProps,
	useInnerBlocksProps,
	store as blockEditorStore,
	__experimentalUseBlockPreview as useBlockPreview,
} from '@wordpress/block-editor';
import { useSelect, useDispatch } from '@wordpress/data';
import { memo, useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';

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

// Texts to display in the preview.
const PREVIEW_TEXTS = [
	__( 'Categories', 'spectra-pro' ),
	__( 'Uncategorized', 'spectra-pro' ),
];

/**
 * Renders a preview of a filter button block with updated attributes.
 *
 * This component takes a set of blocks and a text value, modifies the first block’s attributes
 * (e.g., text and className), and uses the experimental `useBlockPreview` hook to render a
 * preview. It also adds an onClick handler to select the original block in the editor.
 *
 * @param {Object} props The component props.
 * @return {Element} A div element containing the block preview with enhanced props.
 */
const FilterButtonBlockPreview = ( props ) => {
	const { blocks, text } = props;
	const [ isHovered, setIsHovered ] = useState( false );

	// Extract the first block’s attributes
	const firstBlock = blocks[ 0 ] || {};
	const blockAttributes = firstBlock.attributes || {};

	// Extract hover-specific attributes (if they exist)
	const textColorHover = blockAttributes.textColorHover || undefined;
	const backgroundColorHover =
		blockAttributes.backgroundColorHover || undefined;
	const backgroundGradientHover =
		blockAttributes.backgroundGradientHover || undefined;

	// Block scoped CSS variables.
	const blockScopedCssVariables = {
		'--spectra-text-color-hover': textColorHover,
		'--spectra-background-color-hover': backgroundColorHover,
		'--spectra-background-gradient-hover': backgroundGradientHover,
	};

	const blockScopedClassName = spectraClassNames( [
		'filter-button-preview-wrapper',
		isHovered && textColorHover && 'spectra-text-color-hover',
		isHovered && backgroundColorHover && 'spectra-background-color-hover',
		isHovered &&
			backgroundGradientHover &&
			'spectra-background-gradient-hover',
	] );

	// Clone and modify the first block’s attributes for the preview
	const updatedBlocks = blocks.map( ( block, index ) =>
		index === 0
			? {
					...block,
					attributes: {
						...block.attributes,
						text,
						className: 'filter-button-preview', // Add a specific class for styling.
						textColorActive: undefined, // Clear active text color for preview.
						backgroundColorActive: undefined, // Clear active background color for preview.
					},
			  }
			: block
	);

	// Get dispatch method to select a block in the editor.
	const { selectBlock } = useDispatch( blockEditorStore );

	// Generate preview props using the experimental hook with updated blocks.
	const blockPreviewProps = useBlockPreview( {
		blocks: updatedBlocks,
	} );

	const handleOnClick = () => selectBlock( blocks[ 0 ]?.clientId );

	// Enhance preview props with an onClick handler to select the original block.
	const enhancedPreviewProps = {
		...blockPreviewProps,
		className: blockScopedClassName,
		style: blockScopedCssVariables,
		onClick: handleOnClick,
		onKeyPress: handleOnClick,
		onMouseEnter: () => setIsHovered( true ),
		onMouseLeave: () => setIsHovered( false ),
	};

	// Render the preview inside a div with enhanced props.
	return <div { ...enhancedPreviewProps } />;
};

// Memoize the preview component to prevent unnecessary re-renders.
const MemoizedFilterButtonBlockPreview = memo( FilterButtonBlockPreview );

/**
 * The Editor Block render.
 *
 * @since x.x.x
 *
 * @param {Object} props The element props.
 * @return {Element} The rendered block.
 */
const Render = ( props ) => {
	const {
		clientId,
		attributes: { filterType },
	} = props;

	// Block props.
	const blockProps = useBlockProps();

	// Fetch child blocks of type 'spectra-pro/loop-builder-child-filter-button'.
	const filterButtonBlocks = useSelect(
		( select ) => {
			const { getBlocks } = select( blockEditorStore );
			return getBlocks( clientId ).filter(
				( block ) =>
					block.name ===
					'spectra-pro/loop-builder-child-filter-button'
			);
		},
		[ clientId, filterType ]
	);

	// Configure props for inner blocks with allowed types and a locked template.
	const innerBlocksProps = useInnerBlocksProps( blockProps, {
		allowedBlocks: [ 'spectra-pro/loop-builder-child-filter-button' ],
		template: [
			[ 'spectra-pro/loop-builder-child-filter-select' ],
			[ 'spectra-pro/loop-builder-child-filter-checkbox' ],
			[
				'spectra-pro/loop-builder-child-filter-button',
				{
					text: __( 'All', 'spectra-pro' ),
					className: 'editor-active',
				},
			],
		],
		templateLock: 'all',
	} );

	return (
		<div { ...innerBlocksProps }>
			{ innerBlocksProps.children }
			{ 'button' === filterType &&
				filterButtonBlocks.length &&
				PREVIEW_TEXTS.map( ( text, index ) => (
					<MemoizedFilterButtonBlockPreview
						key={ index }
						blocks={ filterButtonBlocks }
						text={ text }
					/>
				) ) }
		</div>
	);
};

export default memo( Render );
