/**
 * External dependencies.
 */
// React hooks for state management and side effects
import { useState, useEffect } from '@wordpress/element';
// WordPress internationalization for translatable strings
import { __ } from '@wordpress/i18n';
// WordPress API fetch utility for making REST API calls
import apiFetch from '@wordpress/api-fetch';
// Brainstorm Force UI components for consistent interface design
import {
	Container,
	DropdownMenu,
	Button,
	Label,
	Loader,
	Title,
	Toaster,
	toast,
	Badge,
} from '@bsf/force-ui';
// Icons from lucide-react for UI elements
import { ChevronDown, Save, CircleFadingPlus, CircleCheckBig } from 'lucide-react';
// React Select for enhanced multi-select dropdown functionality
import Select from 'react-select';

/**
 * Internal dependencies.
 */
// Import function that retrieves available global style classes
import getClassOptions from '@spectra-pro-extensions/global-styles/options';

/**
 * Available block types that support default class configuration.
 * Each option represents a Spectra block that can have default classes applied.
 *
 * Groups are separated by dropdown-sections.
 * The wrapper type blocks are those that can contain innerBlocks.
 * The parent type blocks are those that are the root parent of a given group.
 * The child type blocks are those that are rendered only within a parent block in the current group.
 */
const blockOptions = [
	{ value: 'dropdown-section', expanded: false, heading: __( 'Common Blocks', 'spectra-pro' ) }, // Indicates a new section of blocks and innerblocks.
	{ value: 'container', label: __( 'Container', 'spectra-pro' ), type: [ 'wrapper' ] }, // Container/section block.
	{ value: 'content', label: __( 'Text', 'spectra-pro' ) }, // Content/text block.
	{ value: 'google-map', label: __( 'Google Map', 'spectra-pro' ) }, // Google Map block.
	{ value: 'separator', label: __( 'Separator', 'spectra-pro' ) }, // Separator block.
	{ value: 'dropdown-section', expanded: false, heading: __( 'Button Blocks', 'spectra-pro' ) }, // Indicates a new section of blocks and innerblocks.
	{ value: 'buttons', label: __( 'Buttons', 'spectra-pro' ), type: [ 'wrapper', 'parent' ] }, // Buttons container block.
	{ value: 'button', label: __( 'Button', 'spectra-pro' ), type: [ 'child' ] }, // Individual button block.
	{ value: 'dropdown-section', expanded: false, heading: __( 'Icon Blocks', 'spectra-pro' ) }, // Indicates a new section of blocks and innerblocks.
	{ value: 'icons', label: __( 'Icons', 'spectra-pro' ), type: [ 'wrapper', 'parent' ] }, // Multiple icons block.
	{ value: 'icon', label: __( 'Icon', 'spectra-pro' ), type: [ 'child' ] }, // Single icon block.
	{ value: 'dropdown-section', expanded: false, heading: __( 'List Blocks', 'spectra-pro' ) }, // Indicates a new section of blocks and innerblocks.
	{ value: 'list', label: __( 'List', 'spectra-pro' ), type: [ 'wrapper', 'parent' ] }, // List container block.
	{ value: 'list-child-item', label: __( 'List Item', 'spectra-pro' ), type: [ 'child' ] }, // Individual list item block.
	{ value: 'list-child-icon', label: __( 'List Icon', 'spectra-pro' ), type: [ 'child' ] }, // List item icon block.
	{ value: 'dropdown-section', expanded: false, heading: __( 'Tabs Blocks', 'spectra-pro' ) }, // Indicates a new section of blocks and innerblocks.
	{ value: 'tabs', label: __( 'Tabs', 'spectra-pro' ), type: [ 'wrapper', 'parent' ] }, // Tabs container block.
	{ value: 'tabs-child-tab-wrapper', label: __( 'Tab Area', 'spectra-pro' ), type: [ 'child' ] }, // Tab wrapper/container for tab buttons.
	{ value: 'tabs-child-tab-button', label: __( 'Tab', 'spectra-pro' ), type: [ 'child' ] }, // Individual tab button.
	{ value: 'tabs-child-tabpanel', label: __( 'Panel', 'spectra-pro' ), type: [ 'child' ] }, // Tab content panel.
	{ value: 'dropdown-section', expanded: false, heading: __( 'Accordion Blocks', 'spectra-pro' ) }, // Indicates a new section of blocks and innerblocks.
	{ value: 'accordion', label: __( 'Accordion', 'spectra-pro' ), type: [ 'wrapper', 'parent' ] }, // Accordion container block.
	{ value: 'accordion-child-item', label: __( 'Accordion Item', 'spectra-pro' ), type: [ 'child' ] }, // Individual accordion item block.
	{ value: 'accordion-child-header', label: __( 'Header', 'spectra-pro' ), type: [ 'child' ] }, // Accordion header block.
	{ value: 'accordion-child-details', label: __( 'Details', 'spectra-pro' ), type: [ 'child' ] }, // Accordion details block.
	{ value: 'accordion-child-header-content', label: __( 'Header Title', 'spectra-pro' ), type: [ 'child' ] }, // Accordion header title block.
	{ value: 'accordion-child-header-icon', label: __( 'Header Icon', 'spectra-pro' ), type: [ 'child' ] }, // Accordion header icon block.
	{ value: 'dropdown-section', expanded: false, heading: __( 'Slider Blocks', 'spectra-pro' ) }, // Indicates a new section of blocks and innerblocks.
	{ value: 'slider', label: __( 'Slider', 'spectra-pro' ), type: [ 'wrapper', 'parent' ] }, // Slider container block.
	{ value: 'slider-child', label: __( 'Slide', 'spectra-pro' ), type: [ 'child' ] }, // Individual slide block.
	{ value: 'dropdown-section', expanded: false, heading: __( 'Countdown Blocks', 'spectra-pro' ) }, // Indicates a new section of blocks and innerblocks.
	{ value: 'countdown', label: __( 'Countdown', 'spectra-pro' ), type: [ 'wrapper', 'parent' ] }, // Countdown container block.
	{ value: 'countdown-child-day', label: __( 'Day Container', 'spectra-pro' ), type: [ 'child' ] }, // Day time unit container.
	{ value: 'countdown-child-hour', label: __( 'Hour Container', 'spectra-pro' ), type: [ 'child' ] }, // Hour time unit container.
	{ value: 'countdown-child-minute', label: __( 'Minute Container', 'spectra-pro' ), type: [ 'child' ] }, // Minute time unit container.
	{ value: 'countdown-child-second', label: __( 'Second Container', 'spectra-pro' ), type: [ 'child' ] }, // Second time unit container.
	{ value: 'countdown-child-number', label: __( 'Number', 'spectra-pro' ), type: [ 'child' ] }, // Number display element.
	{ value: 'countdown-child-label', label: __( 'Label', 'spectra-pro' ), type: [ 'child' ] }, // Label text element.
	{ value: 'countdown-child-separator', label: __( 'Separator', 'spectra-pro' ), type: [ 'child' ] }, // Separator element.
	{ value: 'countdown-child-expiry-wrapper', label: __( 'Expiry Wrapper', 'spectra-pro' ), type: [ 'child' ] }, // Expiry wrapper element.
	{ value: 'dropdown-section', expanded: false, heading: __( 'Modal Blocks', 'spectra-pro' ) }, // Indicates a new section of blocks and innerblocks.
	{ value: 'modal', label: __( 'Modal', 'spectra-pro' ), type: [ 'wrapper', 'parent' ] }, // Modal container block.
	{ value: 'modal-child-trigger', label: __( 'Trigger', 'spectra-pro' ), type: [ 'child' ] }, // Modal trigger container.
	{ value: 'modal-child-button', label: __( 'Trigger: Button', 'spectra-pro' ), type: [ 'child' ] }, // Modal trigger button.
	{ value: 'modal-child-content', label: __( 'Trigger: Content', 'spectra-pro' ), type: [ 'child' ] }, // Modal trigger content.
	{ value: 'modal-child-icon', label: __( 'Trigger: Icon', 'spectra-pro' ), type: [ 'child' ] }, // Modal trigger icon.
	{ value: 'modal-popup', label: __( 'Overlay', 'spectra-pro' ), type: [ 'child' ] }, // Modal popup container.
	{ value: 'modal-popup-content', label: __( 'Popup', 'spectra-pro' ), type: [ 'child' ] }, // Modal popup content.
	{ value: 'modal-child-popup-close-icon', label: __( 'Close Icon', 'spectra-pro' ), type: [ 'child' ] }, // Modal close icon.
	{ value: 'dropdown-section', expanded: false, heading: __( 'Loop Builder Blocks', 'spectra-pro' ) }, // Indicates a new section of blocks and innerblocks.
	{ value: 'loop-builder', label: __( 'Loop Builder', 'spectra-pro' ), type: [ 'wrapper', 'parent' ] }, // Loop Builder container block.
	{ value: 'loop-builder-child-search', label: __( 'Search', 'spectra-pro' ), type: [ 'child' ] }, // Search component.
	{ value: 'loop-builder-child-filter', label: __( 'Filter', 'spectra-pro' ), type: [ 'child' ] }, // Filter container.
	{ value: 'loop-builder-child-filter-select', label: __( 'Filter: Dropdown', 'spectra-pro' ), type: [ 'child' ] }, // Filter select dropdown.
	{ value: 'loop-builder-child-filter-checkbox', label: __( 'Filter: Checkbox', 'spectra-pro' ), type: [ 'child' ] }, // Filter checkbox.
	{ value: 'loop-builder-child-filter-button', label: __( 'Filter: Button', 'spectra-pro' ), type: [ 'child' ] }, // Filter button.
	{ value: 'loop-builder-child-reset-all-button', label: __( 'Reset Button', 'spectra-pro' ), type: [ 'child' ] }, // Reset all filters button.
	{ value: 'loop-builder-child-sort', label: __( 'Sort', 'spectra-pro' ), type: [ 'child' ] }, // Sort component.
	{ value: 'loop-builder-child-template', label: __( 'Template', 'spectra-pro' ), type: [ 'child' ] }, // Template container.
	{ value: 'loop-builder-child-pagination', label: __( 'Pagination', 'spectra-pro' ), type: [ 'child' ] }, // Pagination container.
	{ value: 'loop-builder-child-pagination-previous-button', label: __( 'Previous Button', 'spectra-pro' ), type: [ 'child' ] }, // Previous page button.
	{ value: 'loop-builder-child-pagination-page-numbers-button', label: __( 'Page Numbers', 'spectra-pro' ), type: [ 'child' ] }, // Page numbers buttons.
	{ value: 'loop-builder-child-pagination-next-button', label: __( 'Next Button', 'spectra-pro' ), type: [ 'child' ] }, // Next page button.
	{ value: 'loop-builder-child-no-results', label: __( 'No Results', 'spectra-pro' ), type: [ 'child' ] }, // No results message.
];

/**
 * Groups block options into separate arrays based on dropdown-section.
 * This creates distinct groups that will be rendered as separate DropdownMenu.List components.
 * Each group includes the dropdown-section heading and expanded state for display purposes.
 *
 * @return {Array} Array of group objects with heading, blocks, and isExpanded properties
 */
const groupBlockOptions = () => {
	const groups = [];
	let currentGroup = [];
	let currentHeading = null;
	let currentExpanded = true; // Default to expanded if not specified
	
	blockOptions.forEach( option => {
		if ( option.value === 'dropdown-section' ) {
			// When we hit a dropdown-section, save current group if it has blocks
			if ( currentGroup.length > 0 && currentHeading !== null ) {
				groups.push( {
					heading: currentHeading,
					blocks: [...currentGroup],
					isExpanded: currentExpanded
				} );
				currentGroup = [];
			}
			// Store the heading and expanded state from this dropdown-section for the next group
			currentHeading = option.heading;
			currentExpanded = option.expanded !== undefined ? option.expanded : true;
		} else if ( option.value ) {
			// Add non-dropdown-section, non-empty blocks to current group
			currentGroup.push( option );
		}
	} );
	
	// Don't forget the last group if it has blocks
	if ( currentGroup.length > 0 && currentHeading !== null ) {
		groups.push( {
			heading: currentHeading,
			blocks: currentGroup,
			isExpanded: currentExpanded
		} );
	}
	
	return groups;
};

/**
 * Determines if a dropdown group should be open based on expanded state and selected block.
 * A group will be open if either:
 * 1. The group's isExpanded state is true, OR
 * 2. A block from that group is currently selected
 *
 * @param {Object} group         - The group object containing blocks and isExpanded state
 * @param {string} selectedBlock - The currently selected block value
 * @return {boolean} Whether the group should be open
 */
const shouldGroupBeOpen = ( group, selectedBlock ) => {
	// Check if the currently selected block belongs to this group
	const hasSelectedBlock = group.blocks.some( block => block.value === selectedBlock );
	
	// Open if either the group is expanded by default OR a block from this group is selected
	return group.isExpanded || hasSelectedBlock;
};

/**
 * Renders the BlockDefaults tab.
 * This component allows users to set default CSS classes for different Spectra blocks.
 * Users can select a block type, choose classes to apply, preview the result, and save their configuration.
 *
 * @return {Element} The rendered block default page.
 */
const BlockDefaults = () => {
	// State for currently selected block type (e.g., 'buttons', 'button', 'container')
	const [ selectedBlock, setSelectedBlock ] = useState( '' );

	// State for currently selected pseudo-selector
	const [ selectedPseudoSelector, setSelectedPseudoSelector ] = useState( 'default' );
	
	// State for CSS classes selected for the current block and pseudo-selector
	const [ selectedClasses, setSelectedClasses ] = useState( [] );

	// State for all saved block defaults configuration
	// Structure: { blockName: { pseudoSelector: [array of class names] } }
	const [ blockDefaults, setBlockDefaults ] = useState( {} );

	// State to track if save operation is in progress
	const [ isSaving, setIsSaving ] = useState( false );

	// Temporary memory for unsaved class changes per block
	// Structure: { blockName: { pseudoSelector: [array of class names] } }
	const [ tempClassMemory, setTempClassMemory ] = useState( {} );

	// State to track iframe loading status
	const [ isIframeLoading, setIsIframeLoading ] = useState( true );

	// State to track badge visibility: 'loading', 'success', or 'hidden'
	const [ badgeStatus, setBadgeStatus ] = useState( 'loading' );

	// Object of supported pseudo-selectors for Block Defaults (limited set)
	const pseudoSelectors = {
		state: [
			'default',
			'hover',
			'focus-visible',
		],
	};

	// Computed value to check if current block has unsaved changes
	const hasUnsavedChanges = selectedBlock && tempClassMemory[ selectedBlock ] !== undefined && 
		Object.keys( tempClassMemory[ selectedBlock ] || {} ).some( pseudoSelector => {
			const savedClasses = blockDefaults[ selectedBlock ]?.[pseudoSelector] || [];
			const tempClasses = tempClassMemory[ selectedBlock ]?.[pseudoSelector] || [];
			return JSON.stringify( savedClasses ) !== JSON.stringify( tempClasses );
		} );

	/**
	 * Get available CSS classes from the global styles configuration.
	 * This function retrieves all registered global style classes that can be applied to blocks.
	 *
	 * @return {Array} Array of class options formatted for React Select component
	 */
	const getAvailableClasses = () => {
		// Use the imported getClassOptions function which returns the properly formatted options
		const classOptions = getClassOptions();
		
		// The getClassOptions returns an array that may contain grouped options
		// We need to ensure it's in the format React Select expects
		if ( classOptions && classOptions.length > 0 ) {
			return classOptions;
		}
		
		// If no classes are available, return an empty array.
		return [];
	};
	
	// Initialize available classes once on component mount
	// Using useState ensures this computation only happens once
	const [ availableClasses ] = useState( getAvailableClasses() );
	
	/**
	 * Effect: Load existing block defaults configuration on component mount.
	 * This reads saved block defaults from the global window object that was
	 * localized by PHP when the admin page was loaded.
	 */
	useEffect( () => {
		// Check if the global admin object exists and contains block defaults
		if ( window.spectra_admin_gs && window.spectra_admin_gs.block_defaults ) {
			// Set the block defaults from the saved configuration
			setBlockDefaults( window.spectra_admin_gs.block_defaults );
		}

		// Set up message listener for iframe communication
		const handleIframeMessage = ( event ) => {
			if ( ! event.data || ! event.data.type ) return;

			switch ( event.data.type ) {
				case 'spectra-gs-preview-ready':
					// Generate initial CSS for all saved block defaults
					generateInitialBlockDefaultsCSS();
					// If a block is already selected, send it to the iframe
					if ( selectedBlock ) {
						const parentBlock = getParentBlock( selectedBlock );
						const context = { originalBlock: selectedBlock };
						sendBlockToIframe( parentBlock, context );
					}
					break;

				case 'spectra-gs-preview-error':
					console.error( 'Block preview error:', event.data.error, 'for block:', event.data.blockName ); // eslint-disable-line no-console
					break;

				default:
					// Ignore other message types
					break;
			}
		};

		// Add event listener
		window.addEventListener( 'message', handleIframeMessage );

		// Cleanup on unmount
		return () => {
			window.removeEventListener( 'message', handleIframeMessage );
		};
	}, [ selectedBlock ] ); // Include selectedBlock in dependency array
	
	/**
	 * Get the parent block for a given block within its group.
	 * Searches backward from the block to find the nearest parent-type block.
	 *
	 * @param {string} blockValue - The value of the selected block
	 * @return {string} The parent block value or the block itself if it's a parent
	 */
	const getParentBlock = ( blockValue ) => {
		const blockIndex = blockOptions.findIndex( opt => opt.value === blockValue );
		if ( blockIndex === -1 ) return blockValue;
		
		// If the block itself is a parent, return it
		const currentBlock = blockOptions[ blockIndex ];
		if ( currentBlock.type?.includes( 'parent' ) ) {
			return blockValue;
		}
		
		// Search backward for the nearest parent block before a dropdown-section
		for ( let i = blockIndex - 1; i >= 0; i-- ) {
			const block = blockOptions[ i ];
			
			// Stop at dropdown-section - no parent found in this group
			if ( block.value === 'dropdown-section' ) {
				break;
			}
			
			// Found a parent block
			if ( block.type?.includes( 'parent' ) ) {
				return block.value;
			}
		}
		
		// No parent found, return the block itself
		return blockValue;
	};
	
	/**
	 * Get block data configuration for iframe preview.
	 * Maps block options to the proper block structure with inner blocks.
	 *
	 * @param {string} blockValue - The selected block value
	 * @param {Object} context    - Additional context for block configuration
	 * @return {Object|null} Block data object for iframe or null if not found
	 */
	const getBlockDataForPreview = ( blockValue, context = {} ) => {
		// Map of block values to WordPress block names
		const blockNameMapping = {
			'buttons': 'spectra/buttons',
			'button': 'spectra/button',
			'icons': 'spectra/icons', 
			'icon': 'spectra/icon',
			'list': 'spectra/list',
			'list-child-item': 'spectra/list-child-item',
			'list-child-icon': 'spectra/list-child-icon',
			'container': 'spectra/container',
			'content': 'spectra/content',
			'google-map': 'spectra/google-map',
			'separator': 'spectra/separator',
			'tabs': 'spectra/tabs',
			'tabs-child-tab-wrapper': 'spectra/tabs-child-tab-wrapper',
			'tabs-child-tab-button': 'spectra/tabs-child-tab-button',
			'tabs-child-tabpanel': 'spectra/tabs-child-tabpanel',
			'accordion': 'spectra/accordion',
			'accordion-child-item': 'spectra/accordion-child-item',
			'accordion-child-header': 'spectra/accordion-child-header',
			'accordion-child-details': 'spectra/accordion-child-details',
			'accordion-child-header-content': 'spectra/accordion-child-header-content',
			'accordion-child-header-icon': 'spectra/accordion-child-header-icon',
			'slider': 'spectra/slider',
			'slider-child': 'spectra/slider-child',
			'countdown': 'spectra/countdown',
			'countdown-child-day': 'spectra/countdown-child-day',
			'countdown-child-hour': 'spectra/countdown-child-hour',
			'countdown-child-minute': 'spectra/countdown-child-minute',
			'countdown-child-second': 'spectra/countdown-child-second',
			'countdown-child-number': 'spectra/countdown-child-number',
			'countdown-child-label': 'spectra/countdown-child-label',
			'countdown-child-separator': 'spectra/countdown-child-separator',
			'countdown-child-expiry-wrapper': 'spectra/countdown-child-expiry-wrapper',
			'modal': 'spectra/modal',
			'modal-child-trigger': 'spectra/modal-child-trigger',
			'modal-child-button': 'spectra/modal-child-button',
			'modal-child-content': 'spectra/modal-child-content',
			'modal-child-icon': 'spectra/modal-child-icon',
			'modal-popup': 'spectra/modal-popup',
			'modal-child-popup-close-icon': 'spectra/modal-child-popup-close-icon',
			'modal-popup-content': 'spectra/modal-popup-content',
			'loop-builder': 'spectra-pro/loop-builder',
			'loop-builder-child-search': 'spectra-pro/loop-builder-child-search',
			'loop-builder-child-filter': 'spectra-pro/loop-builder-child-filter',
			'loop-builder-child-filter-select': 'spectra-pro/loop-builder-child-filter-select',
			'loop-builder-child-filter-checkbox': 'spectra-pro/loop-builder-child-filter-checkbox',
			'loop-builder-child-filter-button': 'spectra-pro/loop-builder-child-filter-button',
			'loop-builder-child-reset-all-button': 'spectra-pro/loop-builder-child-reset-all-button',
			'loop-builder-child-sort': 'spectra-pro/loop-builder-child-sort',
			'loop-builder-child-template': 'spectra-pro/loop-builder-child-template',
			'loop-builder-child-pagination': 'spectra-pro/loop-builder-child-pagination',
			'loop-builder-child-pagination-previous-button': 'spectra-pro/loop-builder-child-pagination-previous-button',
			'loop-builder-child-pagination-page-numbers-button': 'spectra-pro/loop-builder-child-pagination-page-numbers-button',
			'loop-builder-child-pagination-next-button': 'spectra-pro/loop-builder-child-pagination-next-button',
			'loop-builder-child-no-results': 'spectra-pro/loop-builder-child-no-results',
		};

		const blockName = blockNameMapping[ blockValue ];
		if ( ! blockName ) return null;

		// Base block configuration
		const blockData = {
			name: blockName,
			attributes: {
				isPreview: false,
				variationSelected: true
			}
		};

		// Configure block defaults for specific blocks. Not adding them here will render the default block as in the editor.
		switch ( blockValue ) {
			case 'container':
				blockData.inner_blocks = [
					{
						name: 'spectra/content',
						attributes: {
							text: __( 'This is container content for preview', 'spectra-pro' )
						}
					}
				];
				break;
			case 'content':
				blockData.attributes.text = __( 'This is sample content text for preview', 'spectra-pro' );
				break;
			case 'google-map':
				blockData.attributes.address = __( 'New York, NY, USA', 'spectra-pro' );
				blockData.attributes.zoom = 12;
				break;
			case 'buttons':
				blockData.inner_blocks = [
					{
						name: 'spectra/button',
						attributes: { 
							isPreview: false, 
							text: __( 'Button 1', 'spectra-pro' )
						}
					},
					{
						name: 'spectra/button',
						attributes: { 
							isPreview: false, 
							text: __( 'Button 2', 'spectra-pro' )
						}
					}
				];
				break;
			case 'icons':
				blockData.inner_blocks = [
					{
						name: 'spectra/icon',
						attributes: { isPreview: false, icon: 'star' }
					},
					{
						name: 'spectra/icon',
						attributes: { isPreview: false, icon: 'heart' }
					}
				];
				break;
			case 'list':
				blockData.inner_blocks = [
					{
						name: 'spectra/list-child-item',
						attributes: { index: 1 },
						inner_blocks: [
							{
								name: 'spectra/list-child-icon',
								attributes: { itemIndex: 1 }
							},
							{
								name: 'spectra/content',
								attributes: {
									text: __( 'First list item with content', 'spectra-pro' )
								}
							}
						]
					},
					{
						name: 'spectra/list-child-item',
						attributes: { index: 2 },
						inner_blocks: [
							{
								name: 'spectra/list-child-icon',
								attributes: { itemIndex: 2 }
							},
							{
								name: 'spectra/content',
								attributes: {
									text: __( 'Second list item with content', 'spectra-pro' )
								}
							}
						]
					},
					{
						name: 'spectra/list-child-item',
						attributes: { index: 3 },
						inner_blocks: [
							{
								name: 'spectra/list-child-icon',
								attributes: { itemIndex: 3 }
							},
							{
								name: 'spectra/content',
								attributes: {
									text: __( 'Third list item with content', 'spectra-pro' )
								}
							}
						]
					}
				];
				break;
			case 'tabs':
				blockData.attributes.currentTab = 0;
				blockData.inner_blocks = [
					{
						name: 'spectra/tabs-child-tab-wrapper',
						attributes: {},
						inner_blocks: [
							{
								name: 'spectra/tabs-child-tab-button',
								attributes: { 
									currentTab: 0, 
									text: __( 'Tab 1', 'spectra-pro' )
								}
							},
							{
								name: 'spectra/tabs-child-tab-button',
								attributes: { 
									currentTab: 1, 
									text: __( 'Tab 2', 'spectra-pro' )
								}
							},
							{
								name: 'spectra/tabs-child-tab-button',
								attributes: { 
									currentTab: 2, 
									text: __( 'Tab 3', 'spectra-pro' )
								}
							}
						]
					},
					{
						name: 'spectra/tabs-child-tabpanel',
						attributes: { currentTab: 0 },
						inner_blocks: [
							{
								name: 'spectra/content',
								attributes: {
									text: __( 'The content of Tab 1 comes here.', 'spectra-pro' )
								}
							}
						]
					},
					{
						name: 'spectra/tabs-child-tabpanel',
						attributes: { currentTab: 1 },
						inner_blocks: [
							{
								name: 'spectra/content',
								attributes: {
									text: __( 'The content of Tab 2 comes here.', 'spectra-pro' )
								}
							}
						]
					},
					{
						name: 'spectra/tabs-child-tabpanel',
						attributes: { currentTab: 2 },
						inner_blocks: [
							{
								name: 'spectra/content',
								attributes: {
									text: __( 'The content of Tab 3 comes here.', 'spectra-pro' )
								}
							}
						]
					}
				];
				break;
			case 'accordion':
				blockData.inner_blocks = [
					{
						name: 'spectra/accordion-child-item',
						attributes: {},
						inner_blocks: [
							{
								name: 'spectra/accordion-child-header',
								attributes: {},
								inner_blocks: [
									{
										name: 'spectra/accordion-child-header-icon',
										attributes: {}
									},
									{
										name: 'spectra/accordion-child-header-content',
										attributes: {
											text: __( 'Item 1', 'spectra-pro' )
										}
									}
								]
							},
							{
								name: 'spectra/accordion-child-details',
								attributes: {},
								inner_blocks: [
									{
										name: 'spectra/content',
										attributes: {
											tagName: 'p',
											text: __( 'These are the details associated with item 1', 'spectra-pro' )
										}
									}
								]
							}
						]
					},
					{
						name: 'spectra/accordion-child-item',
						attributes: {},
						inner_blocks: [
							{
								name: 'spectra/accordion-child-header',
								attributes: {},
								inner_blocks: [
									{
										name: 'spectra/accordion-child-header-icon',
										attributes: {}
									},
									{
										name: 'spectra/accordion-child-header-content',
										attributes: {
											text: __( 'Item 2', 'spectra-pro' )
										}
									}
								]
							},
							{
								name: 'spectra/accordion-child-details',
								attributes: {},
								inner_blocks: [
									{
										name: 'spectra/content',
										attributes: {
											tagName: 'p',
											text: __( 'These are the details associated with item 2', 'spectra-pro' )
										}
									}
								]
							}
						]
					},
					{
						name: 'spectra/accordion-child-item',
						attributes: {},
						inner_blocks: [
							{
								name: 'spectra/accordion-child-header',
								attributes: {},
								inner_blocks: [
									{
										name: 'spectra/accordion-child-header-icon',
										attributes: {}
									},
									{
										name: 'spectra/accordion-child-header-content',
										attributes: {
											text: __( 'Item 3', 'spectra-pro' )
										}
									}
								]
							},
							{
								name: 'spectra/accordion-child-details',
								attributes: {},
								inner_blocks: [
									{
										name: 'spectra/content',
										attributes: {
											text: __( 'These are the details associated with item 3', 'spectra-pro' )
										}
									}
								]
							}
						]
					}
				];
				break;
			case 'slider':
				blockData.inner_blocks = [
					{
						name: 'spectra/slider-child',
						attributes: {},
						inner_blocks: [
							{
								name: 'spectra/content',
								attributes: {
									text: __( 'This is content in slide 1 for preview', 'spectra-pro' )
								}
							}
						]
					},
					{
						name: 'spectra/slider-child',
						attributes: {},
						inner_blocks: [
							{
								name: 'spectra/content',
								attributes: {
									text: __( 'This is content in slide 2 for preview', 'spectra-pro' )
								}
							}
						]
					},
					{
						name: 'spectra/slider-child',
						attributes: {},
						inner_blocks: [
							{
								name: 'spectra/content',
								attributes: {
									text: __( 'This is content in slide 3 for preview', 'spectra-pro' )
								}
							}
						]
					}
				];
				break;
			case 'countdown':
				blockData.attributes.timerEndAction = 'replace';
				if ( 'countdown-child-expiry-wrapper' === context.originalBlock ) {
					blockData.attributes.editorInnerBlocksPreview = true;
				}
				blockData.inner_blocks = [
					{
						name: 'spectra/countdown-child-day',
						attributes: {}
					},
					{
						name: 'spectra/countdown-child-hour', 
						attributes: {}
					},
					{
						name: 'spectra/countdown-child-minute',
						attributes: {}
					},
					{
						name: 'spectra/countdown-child-second',
						attributes: {}
					},
					{
						name: 'spectra/countdown-child-separator',
						attributes: {}
					},
					{
						name: 'spectra/countdown-child-expiry-wrapper',
						attributes: {
							lock: { 
								move: true,
								remove: true,
							},
							style: {
								typography: {
									fontSize: '1rem',
								},
							},
						},
						inner_blocks: [
							{
								name: 'spectra/content',
								attributes: {
									text: __( 'This is a preview of the expiry wrapper', 'spectra-pro' )
								}
							}
						]
					}
				];
				break;
			case 'modal':
				blockData.attributes.isVisible = true;
				
				// Set modalTrigger attribute based on original selected block
				if ( context.originalBlock === 'modal-child-icon' ) {
					blockData.attributes.modalTrigger = 'icon';
				} else if ( context.originalBlock === 'modal-child-content' ) {
					blockData.attributes.modalTrigger = 'text';
				}
				
				blockData.inner_blocks = [
					{
						name: 'spectra/modal-child-trigger',
						attributes: {},
						inner_blocks: [
							{
								name: 'spectra/modal-child-button',
								attributes: {}
							},
							{
								name: 'spectra/modal-child-icon',
								attributes: {}
							},
							{
								name: 'spectra/modal-child-content',
								attributes: {}
							}
						]
					},
					{
						name: 'spectra/modal-popup',
						attributes: {},
						inner_blocks: [
							{
								name: 'spectra/modal-child-popup-close-icon',
								attributes: {}
							},
							{
								name: 'spectra/modal-popup-content',
								attributes: {},
								inner_blocks: [
									{
										name: 'spectra/content',
										attributes: {
											tagName: 'p',
											text: __( 'This is modal content for preview', 'spectra-pro' )
										}
									},
								]
							}
						]
					}
				];
				break;
			case 'loop-builder':
				blockData.attributes.layout = {
					type: 'flex',
					flexWrap: 'nowrap',
					orientation: 'horizontal',
					justifyContent: 'space-between',
					verticalAlignment: 'top'
				};
				blockData.attributes.variationSelected = true;
				blockData.attributes.queryId = 3;
				blockData.attributes.query = {
					perPage: 2,
					pages: 0,
					offset: 0,
					postType: 'post',
					order: 'desc',
					orderBy: 'date',
					author: '',
					search: '',
					exclude: [],
					sticky: '',
					taxQuery: null,
					parents: [],
					format: []
				};
				blockData.inner_blocks = [
					{
						name: 'spectra/container',
						attributes: {
							layout: {
								type: 'flex',
								flexWrap: 'nowrap',
								justifyContent: 'left',
								verticalAlignment: 'top',
								orientation: 'vertical'
							},
							variationSelected: true,
							style: {
								layout: {
									selfStretch: 'fixed',
									flexSize: '25%'
								},
								spacing: {
									padding: '0'
								}
							},
						},
						inner_blocks: [
							{
								name: 'spectra/content',
								attributes: {
									tagName: 'h4',
									text: __( 'Sort', 'spectra-pro' ),
									isRootBlock: false,
								}
							},
							{
								name: 'spectra-pro/loop-builder-child-sort',
							},
							{
								name: 'spectra/content',
								attributes: {
									tagName: 'h4',
									text: __( 'Search', 'spectra-pro' ),
									isRootBlock: false,
								}
							},
							{
								name: 'spectra-pro/loop-builder-child-search',
							},
							{
								name: 'spectra/content',
								attributes: {
									tagName: 'h4',
									text: __( 'Categories', 'spectra-pro' ),
									isRootBlock: false,
								}
							},
							{
								name: 'spectra-pro/loop-builder-child-filter',
								attributes: {
									layout: {
										type: 'flex',
										justifyContent: 'left',
										flexWrap: 'wrap',
									},
									// Set filterType based on original selected block
									...( context.originalBlock === 'loop-builder-child-filter-select' ? {} : // eslint-disable-line no-nested-ternary
										 context.originalBlock === 'loop-builder-child-filter-button' ? { filterType: 'button' } : 
										 { filterType: 'checkbox' } ),
								},
								inner_blocks: [
									{
										name: 'spectra-pro/loop-builder-child-filter-select',
									},
									{
										name: 'spectra-pro/loop-builder-child-filter-checkbox',
									},
									{
										name: 'spectra-pro/loop-builder-child-filter-button',
										attributes: {
											text: __( 'All', 'spectra-pro' ),
											className: 'editor-active',
											style: {
												spacing: {
													padding: {
														top: 'var:preset|spacing|20',
														right: 'var:preset|spacing|20',
														bottom: 'var:preset|spacing|20',
														left: 'var:preset|spacing|20'
													}
												},
												border: {
													radius: '0.3em'
												}
											},
										}
									}
								]
							},
							{
								name: 'spectra-pro/loop-builder-child-reset-all-button',
								attributes: { 
									text: __( 'Reset Filters', 'spectra-pro' ),
								}
							}
						]
					},
					{
						name: 'spectra/container',
						attributes: {
							layout: {
								type: 'flex',
								flexWrap: 'nowrap',
								justifyContent: 'stretch',
								verticalAlignment: 'top',
								orientation: 'vertical'
							},
							variationSelected: true,
							style: {
								layout: {
									selfStretch: 'fixed',
									flexSize: '75%'
								},
								spacing: {
									padding: '0'
								}
							},
						},
						inner_blocks: [
							{
								name: 'spectra-pro/loop-builder-child-template',
								attributes: {
									layout: { type: 'grid', columnCount: 2 },
									variationSelected: true,
								},
								inner_blocks: [
									{
										name: 'spectra/container',
										attributes: {
											layout: { type: 'default' },
											variationSelected: true,
											height: '100%',
											style: {
												spacing: {
													padding: '0',
													blockGap: 'var:preset|spacing|20'
												}
											},
										},
										inner_blocks: [
											{
												name: 'core/post-featured-image',
												attributes: {
													isLink: true,
													aspectRatio: '16/9',
													width: '100%'
												}
											},
											{
												name: 'core/post-date',
												attributes: {}
											},
											{
												name: 'core/post-title',
												attributes: { isLink: true }
											},
											{
												name: 'core/post-excerpt',
												attributes: { moreText: __( 'Read more', 'spectra-pro' ) }
											}
										]
									}
								]
							},
							{
								name: 'spectra-pro/loop-builder-child-pagination',
								inner_blocks: [
									{
										name: 'spectra-pro/loop-builder-child-pagination-previous-button',
										attributes: {
											text: __( 'Previous', 'spectra-pro' ),
											icon: 'angles-left',
											iconPosition: 'before',
											size: '15px',
											gap: '0.625rem',
											flipForRTL: true,
											style: {
												spacing: {
													padding: {
														top: 'var:preset|spacing|20',
														right: 'var:preset|spacing|20',
														bottom: 'var:preset|spacing|20',
														left: 'var:preset|spacing|20'
													},
													blockGap: 'var:preset|spacing|20'
												},
												border: {
													radius: '0.3em'
												}
											},
										}
									},
									{
										name: 'spectra-pro/loop-builder-child-pagination-page-numbers-button',
										attributes: {
											text: __( ' 1 2 3 4 5…7', 'spectra-pro' ),
											midSize: 2,
											style: {
												spacing: {
													padding: {
														top: 'var:preset|spacing|20',
														right: 'var:preset|spacing|20',
														bottom: 'var:preset|spacing|20',
														left: 'var:preset|spacing|20'
													},
													blockGap: 'var:preset|spacing|20'
												},
												border: {
													radius: '0.3em'
												}
											},
										}
									},
									{
										name: 'spectra-pro/loop-builder-child-pagination-next-button',
										attributes: {
											text: __( 'Next', 'spectra-pro' ),
											icon: 'angles-right',
											iconPosition: 'after',
											size: '15px',
											gap: '0.625rem',
											flipForRTL: true,
											style: {
												spacing: {
													padding: {
														top: 'var:preset|spacing|20',
														right: 'var:preset|spacing|20',
														bottom: 'var:preset|spacing|20',
														left: 'var:preset|spacing|20'
													},
													blockGap: 'var:preset|spacing|20'
												},
												border: {
													radius: '0.3em'
												}
											},
										}
									}
								]
							},
							{
								name: 'spectra-pro/loop-builder-child-no-results',
								inner_blocks: [
									{
										name: 'spectra/content',
										attributes: {
											tagName: 'p',
											text: __( 'No results found.', 'spectra-pro' ),
											isRootBlock: false,
											style: {
												typography: {
													textAlign: 'center'
												}
											},
										}
									}
								]
							}
						]
					}
				];
				break;
		}

		return blockData;
	};

	/**
	 * Send block data to iframe for preview rendering.
	 *
	 * @param {string} blockValue - The block value to preview
	 * @param {Object} context    - Additional context for block configuration
	 */
	const sendBlockToIframe = ( blockValue, context = {} ) => {
		const iframe = document.querySelector( 'iframe' );
		if ( ! iframe || ! iframe.contentWindow ) return;

		const blockData = getBlockDataForPreview( blockValue, context );
		if ( ! blockData ) return;

		// Send message to iframe
		iframe.contentWindow.postMessage( {
			type: 'spectra-gs-render-block',
			blockData
		}, '*' );
	};

	/**
	 * Effect: Update preview block when selected block changes.
	 * Only re-renders preview when switching to a block from a different group.
	 */
	useEffect( () => {
		if ( ! selectedBlock ) {
			setSelectedPseudoSelector( 'default' ); // Reset pseudo-selector when no block is selected
			return;
		}
		
		// Get the parent block for the newly selected block
		const newParentBlock = getParentBlock( selectedBlock );
		
		// Send the parent block to iframe for preview with original block context
		const context = { originalBlock: selectedBlock };
		sendBlockToIframe( newParentBlock, context );
	}, [ selectedBlock ] );
	
	/**
	 * Effect: Load classes for the selected block and pseudo-selector.
	 * This ensures the class selection UI reflects the correct data for the selected block and pseudo-selector.
	 */
	useEffect( () => {
		// Initialize global storage if not exists
		if ( ! window.spectraGSTemporaryStorage ) {
			window.spectraGSTemporaryStorage = {};
		}
		
		// Load classes for the selected block and pseudo-selector
		if ( ! selectedBlock || ! selectedPseudoSelector ) {
			setSelectedClasses( [] );
			return;
		}
		
		let classesToLoad = [];
		
		// Check global storage first for cross-navigation persistence
		const tempData = window.spectraGSTemporaryStorage[ selectedBlock ];
		if ( tempData && tempData[ selectedPseudoSelector ] !== undefined ) {
			// Load from global storage
			classesToLoad = tempData[ selectedPseudoSelector ];
		} else if ( blockDefaults[ selectedBlock ]?.[selectedPseudoSelector] ) {
			// Load the saved classes for this block and pseudo-selector
			classesToLoad = blockDefaults[ selectedBlock ][ selectedPseudoSelector ];
		} else {
			// No classes for this block and pseudo-selector
			classesToLoad = [];
		}
		
		// Update UI and temp memory with the correct classes
		setSelectedClasses( classesToLoad );
		setTempClassMemory( prev => ( { 
			...prev, 
			[ selectedBlock ]: {
				...( prev[ selectedBlock ] || {} ),
				[ selectedPseudoSelector ]: classesToLoad 
			}
		} ) );

		// Generate and send CSS for the loaded classes
		generateAndSendCSS( selectedBlock, selectedPseudoSelector, classesToLoad );
	}, [ selectedBlock, selectedPseudoSelector, blockDefaults ] );
	
	/**
	 * Effect: Sync tempClassMemory changes to global storage.
	 * This ensures unsaved changes persist across navigation.
	 */
	useEffect( () => {
		if ( ! window.spectraGSTemporaryStorage ) {
			window.spectraGSTemporaryStorage = {};
		}
		
		// Only sync blocks that have actual unsaved changes
		Object.keys( tempClassMemory ).forEach( blockName => {
			const tempPseudoSelectors = tempClassMemory[ blockName ] || {};
			const savedPseudoSelectors = blockDefaults[ blockName ] || {};
			
			// Check if any pseudo-selector has changes
			let hasChanges = false;
			const cleanedTempData = {};
			
			Object.keys( tempPseudoSelectors ).forEach( pseudoSelector => {
				const tempClasses = tempPseudoSelectors[ pseudoSelector ] || [];
				const savedClasses = savedPseudoSelectors[ pseudoSelector ] || [];
				
				// Store if there are changes for this pseudo-selector
				if ( JSON.stringify( tempClasses ) !== JSON.stringify( savedClasses ) ) {
					hasChanges = true;
					cleanedTempData[ pseudoSelector ] = tempClasses;
				}
			} );
			
			// Only update global storage if there are actual changes
			if ( hasChanges ) {
				window.spectraGSTemporaryStorage[ blockName ] = cleanedTempData;
			} else {
				// Remove from global storage if no changes
				delete window.spectraGSTemporaryStorage[ blockName ];
			}
		} );
	}, [ tempClassMemory, blockDefaults ] );
	
	/**
	 * Effect: Clean up temporary memory on component unmount.
	 * This prevents memory leaks and ensures a clean state on remount.
	 */
	useEffect( () => {
		return () => {
			// Clear temporary memory when component unmounts
			setTempClassMemory( {} );
		};
	}, [] ); // Empty dependency array - only run on mount/unmount

	/**
	 * Convert selected classes array to React Select format.
	 * This transforms the simple array of class names into objects with value/label pairs
	 * that React Select component can display properly.
	 */
	const selectedClassesForSelect = selectedClasses.map( cls => {
		// Start with the class name as both value and label
		let label = cls;
		
		// Search through all available class groups to find the proper label
		availableClasses.forEach( group => {
			// Look for this class in the current group's options
			const found = group.options?.find( opt => opt.value === cls );
			if ( found ) {
				// Use the human-readable label if found
				label = found.label;
			}
		} );
		
		// Return object format expected by React Select
		return { value: cls, label };
	} );

	/**
	 * Generate initial stylesheet with all saved block defaults on iframe load.
	 * This ensures the iframe starts with the correct CSS for saved block defaults.
	 */
	const generateInitialBlockDefaultsCSS = async () => {
		if ( ! blockDefaults || Object.keys( blockDefaults ).length === 0 ) {
			return;
		}

		try {
			// Process each saved block and its pseudo-selectors
			for ( const blockName of Object.keys( blockDefaults ) ) {
				const blockDefaultPseudoSelectors = blockDefaults[ blockName ];
				
				// Handle both legacy format (simple array) and new format (pseudo-selector object)
				const processedPseudoSelectors = Array.isArray( blockDefaultPseudoSelectors ) 
					? { default: blockDefaultPseudoSelectors }
					: blockDefaultPseudoSelectors;

				for ( const pseudoSelector of Object.keys( processedPseudoSelectors ) ) {
					const classNames = processedPseudoSelectors[ pseudoSelector ];
					
					if ( Array.isArray( classNames ) && classNames.length > 0 ) {
						// Generate CSS for each class using the add logic
						for ( const className of classNames ) {
							await updateClassInStylesheet( 'add', blockName, pseudoSelector, className );
						}
					}
				}
			}
		} catch ( error ) {
			console.error( '[BlockDefaults] generateInitialBlockDefaultsCSS error:', error ); // eslint-disable-line no-console
		}
	};

	/**
	 * Handle class changes by sending add/remove commands to iframe.
	 * This approach tracks differences and sends only the changes needed.
	 *
	 * @param {string} blockName      - The block name to update CSS for
	 * @param {string} pseudoSelector - The pseudo-selector
	 * @param {Array}  newClassNames  - Array of new class names
	 */
	const generateAndSendCSS = async ( blockName, pseudoSelector, newClassNames ) => {
		// Don't generate CSS if no block name
		if ( ! blockName ) {
			return;
		}

		// Get the current classes from both saved state AND temporary memory
		const savedClasses = blockDefaults[ blockName ] && blockDefaults[ blockName ][ pseudoSelector ] 
			? blockDefaults[ blockName ][ pseudoSelector ] 
			: [];
		const tempClasses = tempClassMemory[ blockName ] && tempClassMemory[ blockName ][ pseudoSelector ]
			? tempClassMemory[ blockName ][ pseudoSelector ]
			: null;
		
		// Use temp classes if they exist, otherwise use saved classes
		const currentClasses = tempClasses !== null ? tempClasses : savedClasses;

		// Find classes to add and remove
		const classesToAdd = newClassNames.filter( className => ! currentClasses.includes( className ) );
		const classesToRemove = currentClasses.filter( className => ! newClassNames.includes( className ) );


		try {
			// Handle class removals first
			for ( const className of classesToRemove ) {
				await updateClassInStylesheet( 'remove', blockName, pseudoSelector, className );
			}

			// Then handle class additions
			for ( const className of classesToAdd ) {
				await updateClassInStylesheet( 'add', blockName, pseudoSelector, className );
			}

		} catch ( error ) {
			console.error( '[BlockDefaults] generateAndSendCSS error:', error ); // eslint-disable-line no-console
		}
	};

	/**
	 * Update a specific class in the iframe stylesheet.
	 *
	 * @param {string} action         - 'add' or 'remove'
	 * @param {string} blockName      - The block name
	 * @param {string} pseudoSelector - The pseudo-selector
	 * @param {string} className      - The class name to add/remove
	 */
	const updateClassInStylesheet = async ( action, blockName, pseudoSelector, className ) => {
		try {
			// Prepare form data for AJAX request
			const formData = new window.FormData();
			formData.append( 'action', 'spectra_pro_gs_update_class_in_stylesheet' );
			formData.append( 'security', window.spectra_admin_gs.ajax_nonce );
			formData.append( 'action_type', action );
			formData.append( 'block_name', blockName );
			formData.append( 'pseudo_selector', pseudoSelector );
			formData.append( 'class_name', className );

			// Make AJAX request
			const response = await apiFetch( {
				url: window.spectra_admin_gs.ajax_url,
				method: 'POST',
				body: formData,
			} );

			if ( response.success ) {
				if ( action === 'add' && response.data.css ) {
					// Send add command to iframe with CSS
					sendClassUpdateToIframe( 'add', blockName, pseudoSelector, className, response.data.css );
				} else if ( action === 'remove' ) {
					// Send remove command to iframe
					sendClassUpdateToIframe( 'remove', blockName, pseudoSelector, className, '' );
				}
			} else {
				console.error( '[BlockDefaults] AJAX failed:', response ); // eslint-disable-line no-console
			}
		} catch ( error ) {
			console.error( '[BlockDefaults] updateClassInStylesheet error:', error ); // eslint-disable-line no-console
		}
	};

	/**
	 * Send class update command to iframe for granular CSS updates.
	 *
	 * @param {string} action         - 'add' or 'remove'
	 * @param {string} blockName      - The block name
	 * @param {string} pseudoSelector - The pseudo-selector
	 * @param {string} className      - The class name to add/remove
	 * @param {string} css            - The CSS for the class (only needed for 'add')
	 */
	const sendClassUpdateToIframe = ( action, blockName, pseudoSelector, className, css ) => {
		const iframe = document.querySelector( 'iframe' );
		
		if ( ! iframe || ! iframe.contentWindow ) {
			return;
		}

		// Send message to iframe
		iframe.contentWindow.postMessage( {
			type: 'spectra-gs-update-class',
			action,
			blockName,
			pseudoSelector,
			className,
			css
		}, '*' );
	};

	/**
	 * Handle changes to the class selection multi-select dropdown.
	 * Converts React Select's object format back to simple array of class names.
	 * Stores changes in temporary memory for the current block and pseudo-selector.
	 *
	 * @param {Array} newValue - Array of selected options from React Select
	 */
	const handleClassChange = ( newValue ) => {
		// Extract just the class names (values) from the selected options
		// If newValue is null/empty, use empty array
		const newClasses = newValue ? newValue.map( item => item.value ) : [];
		
		// Update the selected classes state
		setSelectedClasses( newClasses );
		
		// Store in temporary memory for this block and pseudo-selector
		if ( selectedBlock && selectedPseudoSelector ) {
			const savedClasses = blockDefaults[ selectedBlock ]?.[selectedPseudoSelector] || [];
			
			// Check if new classes match saved state exactly
			if ( JSON.stringify( newClasses ) === JSON.stringify( savedClasses ) ) {
				// Classes match saved state - clean up temp memory for this pseudo-selector
				setTempClassMemory( prev => {
					const updated = { ...prev };
					if ( updated[ selectedBlock ] ) {
						delete updated[ selectedBlock ][ selectedPseudoSelector ];
						
						// If no pseudo-selectors left, remove the entire block entry
						if ( Object.keys( updated[ selectedBlock ] ).length === 0 ) {
							delete updated[ selectedBlock ];
						}
					}
					return updated;
				} );
				
				// Also immediately clean up global storage
				if ( window.spectraGSTemporaryStorage && window.spectraGSTemporaryStorage[ selectedBlock ] ) {
					delete window.spectraGSTemporaryStorage[ selectedBlock ][ selectedPseudoSelector ];
					
					// If no pseudo-selectors left, remove the entire block entry from global storage
					if ( Object.keys( window.spectraGSTemporaryStorage[ selectedBlock ] ).length === 0 ) {
						delete window.spectraGSTemporaryStorage[ selectedBlock ];
					}
				}
			} else {
				// Classes differ from saved state - store in temp memory
				setTempClassMemory( prev => ( {
					...prev,
					[ selectedBlock ]: {
						...( prev[ selectedBlock ] || {} ),
						[ selectedPseudoSelector ]: newClasses
					}
				} ) );
			}

			// Generate and send CSS for preview
			generateAndSendCSS( selectedBlock, selectedPseudoSelector, newClasses );
		}
	};
	
	/**
	 * Handle saving block defaults configuration.
	 * Sends the updated configuration to the server via AJAX.
	 * Saves only the current block's changes.
	 */
	const handleSave = async () => {
		// Don't save if no changes made or no block selected
		if ( ! hasUnsavedChanges || ! selectedBlock ) {
			return;
		}
		
		// Show saving state in UI
		setIsSaving( true );
		
		// Create complete configuration with all existing blocks plus current block's changes
		const completeBlockDefaults = {
			...blockDefaults,
			[ selectedBlock ]: tempClassMemory[ selectedBlock ] || {}
		};
		
		// Prepare form data for AJAX request
		const formData = new window.FormData();
		formData.append( 'action', 'spectra_pro_gs_block_defaults' ); // WordPress AJAX action
		formData.append( 'security', window.spectra_admin_gs.ajax_nonce ); // Security nonce
		formData.append( 'block_defaults', JSON.stringify( completeBlockDefaults ) ); // Complete configuration
		
		try {
			// Make AJAX request to WordPress backend
			const response = await apiFetch( {
				url: window.spectra_admin_gs.ajax_url,
				method: 'POST',
				body: formData,
			} );
			
			// Handle successful response
			if ( response.success ) {
				// Show success notification
				toast.success( response.data.title || __( 'Block defaults saved!', 'spectra-pro' ), {
					description: response.data.description || __( 'Your changes have been saved successfully.', 'spectra-pro' )
				} );
				
				// Update local state with only current block's changes
				setBlockDefaults( prev => ( {
					...prev,
					[ selectedBlock ]: tempClassMemory[ selectedBlock ] || {}
				} ) );
				
				// Also update global window object for consistency
				if ( window.spectra_admin_gs ) {
					window.spectra_admin_gs.block_defaults = {
						...window.spectra_admin_gs.block_defaults,
						[ selectedBlock ]: tempClassMemory[ selectedBlock ] || {}
					};
				}
				
				// Clear temporary memory only for current block
				setTempClassMemory( prev => {
					const updated = { ...prev };
					delete updated[ selectedBlock ];
					return updated;
				} );
				
				// Clear global storage only for current block
				if ( window.spectraGSTemporaryStorage ) {
					delete window.spectraGSTemporaryStorage[ selectedBlock ];
				}
				

			} else {
				// Handle error response from server
				toast.error( response.data?.title || __( 'Failed to save!', 'spectra-pro' ), {
					description: response.data?.description || __( 'There was an error saving your changes.', 'spectra-pro' )
				} );
			}
		} catch ( error ) {
			// Handle network or other errors
			toast.error( __( 'Something went wrong.', 'spectra-pro' ), {
				description: error.message || __( 'Failed to save block defaults.', 'spectra-pro' )
			} );
		} finally {
			// Always clear saving state
			setIsSaving( false );
		}
	};



	// Render the component UI
	return (
		<>
			{/* Toast notification container for save success/error messages */}
			<Toaster position="top-right" design="stack" theme="dark" autoDismiss={ true } dismissAfter={ 2000 } />
			
			{/* Main container with padding and spacing */}
			<Container direction="column" className="flex gap-6 w-full mx-auto h-full pt-8 px-4">
				{/* Page title */}
				<Title
					className="text-text-primary text-xl"
					size="md"
					title={ __( 'Block Defaults', 'spectra-pro' ) }
				/>
				
				{/* Main content card */}
				<Container className="bg-background-primary w-full rounded-xl shadow-sm p-6" direction="column" gap="lg">
					{/* Grid layout: 25% left column for controls, 75% right column for preview */}
					<Container direction="row" containerType="grid" cols={ { sm: 1, md: 4 } } gap="lg">
						{/* Left Column - Controls Section (25% width on desktop) */}
						<Container.Item className="w-full" colSpan={ { sm: 1, md: 1 } }>
							<Container direction="column" gap="md">
								<Container containerType="grid" cols="2" gap="md" justify="stretch">
									{/* Block Type Selection Dropdown */}
									<Container.Item className="flex flex-col gap-2 items-stretch">
										<Label>{ __( 'Select a Block', 'spectra-pro' ) }</Label>
										<DropdownMenu>
											<DropdownMenu.Trigger>
												{/* Button shows selected block or prompt text */}
												<Button
													size="sm"
													variant="outline"
													icon={ <ChevronDown size={ 16 }/> }
													iconPosition="right"
													className="w-full justify-between"
													disabled={ isIframeLoading }
												>
													<span>{ selectedBlock ? blockOptions.find( opt => opt.value === selectedBlock )?.label : __( 'Select', 'spectra-pro' ) }</span>
												</Button>
											</DropdownMenu.Trigger>
											<DropdownMenu.ContentWrapper>
												<DropdownMenu.Content>
													{/* Render each block group as separate DropdownMenu.List */}
													{ groupBlockOptions().map( ( group, groupIndex ) => (
														<DropdownMenu.List
															key={ groupIndex }
															heading={ group.heading }
															open={ shouldGroupBeOpen( group, selectedBlock ) }
															arrow
														>
															{ group.blocks.map( ( option, optionIndex ) => (
																<DropdownMenu.Item 
																	key={ optionIndex }
																	className='text-sm' 
																	onClick={ () => {
																		setSelectedBlock( option.value );
																		setSelectedPseudoSelector( 'default' ); // Reset to default when changing block
																	} }
																>
																	{ option.label }
																</DropdownMenu.Item>
															) ) }
														</DropdownMenu.List>
													) ) }
												</DropdownMenu.Content>
											</DropdownMenu.ContentWrapper>
										</DropdownMenu>
									</Container.Item>

									{/* Pseudo-Selector (State) Selection Dropdown - Only shown when a block is selected */}
									{ selectedBlock && (
										<Container.Item className="flex flex-col gap-2 items-stretch">
											<Label>{ __( 'State', 'spectra-pro' ) }</Label>
											<DropdownMenu>
												<DropdownMenu.Trigger>
													<Button size="sm" variant="outline" icon={ <ChevronDown size={ 16 }/> } iconPosition="right" className="w-full justify-between">
														<span>{ 'default' !== selectedPseudoSelector ? `:${ selectedPseudoSelector }` : 'Default' }</span>
													</Button>
												</DropdownMenu.Trigger>
												<DropdownMenu.ContentWrapper>
													<DropdownMenu.Content>
														{ Object.entries( pseudoSelectors ).map( ( [ selector, selectorValues ], index ) => (
															<DropdownMenu.List
																key={ index }
																className='capitalize'
																heading={ selector }
															>
																{ selectorValues.map( ( selectorValue, selectorIndex ) => (
																	<DropdownMenu.Item key={ selectorIndex } className='text-sm' onClick={ () => {
																		setSelectedPseudoSelector( selectorValue );
																	} }>
																		{ selectorValue }
																	</DropdownMenu.Item>
																) ) }
															</DropdownMenu.List>
														) ) }
													</DropdownMenu.Content>
												</DropdownMenu.ContentWrapper>
											</DropdownMenu>
										</Container.Item>
									) }
								</Container>

								{/* CSS Class Multi-Select - Only shown when a block is selected */}
								{ selectedBlock && (
									<div>
										<Label className="mb-2">{ __( 'Add Classes', 'spectra-pro' ) }</Label>
										<Select
											isMulti // Allow multiple class selection
											closeMenuOnSelect={ false } // Keep dropdown open for multiple selections
											value={ selectedClassesForSelect } // Current selection in React Select format
											options={ availableClasses } // Available class options
											placeholder={ __( 'Select classes…', 'spectra-pro' ) }
											// Custom filter function for fuzzy search
											filterOption={ ( option, inputValue ) => {
												// Implement fuzzy search: characters must appear in order but not necessarily consecutive
												// Convert both strings to lowercase for case-insensitive matching
												const optionText = option?.label?.toLowerCase();
												const searchInput = inputValue?.toLowerCase();

												let lastIndex = -1;
												// Check each character in the search input
												for ( const char of searchInput ) {
													// Find next occurrence of char after lastIndex
													const index = optionText.indexOf( char, lastIndex + 1 );
													
													// If character isn't found or appears before previous match, return false
													if ( index === -1 || index <= lastIndex ) {
														return false;
													}
													
													// Update lastIndex for next iteration
													lastIndex = index;
												}

												return true;
											} }
											onChange={ handleClassChange }
											// Custom styling for React Select to match Force UI design
											styles={ {
												control: ( provided ) => ( {
													...provided,
													'minHeight': '36px',
													'borderColor': '#e5e7eb',
													'&:hover': {
														borderColor: '#d1d5db'
													}
												} ),
												multiValue: ( provided ) => ( {
													...provided,
													backgroundColor: '#f3f4f6',
												} ),
												multiValueLabel: ( provided ) => ( {
													...provided,
													color: '#374151',
												} ),
												multiValueRemove: ( provided ) => ( {
													...provided,
													'color': '#6b7280',
													'&:hover': {
														backgroundColor: '#e5e7eb',
														color: '#374151',
													}
												} )
											} }
										/>
									</div>
								) }
							</Container>

							{/* Save Button - Only shown when a block is selected */}
							{ selectedBlock && (
								<Container direction="row" className="mt-6" justify="start">
									<Button
										size="sm"
										variant="primary"
										icon={ <Save size={ 16 } /> }
										iconPosition="left"
										onClick={ handleSave }
										// Disable button when saving or no changes to save
										disabled={ isSaving || ! hasUnsavedChanges }
									>
										{/* Dynamic button text based on save state */}
										{ isSaving ? __( 'Saving…', 'spectra-pro' ) : __( 'Save Changes', 'spectra-pro' ) }
									</Button>
								</Container>
							) }
						</Container.Item>

						{/* Right Column - Preview Section (75% width on desktop) */}
						<Container.Item className="w-full" colSpan={ { sm: 1, md: 3 } }>
							{/* Preview header */}
							<div className="flex flex-col gap-2">
								<Label tag="p">{ __( 'Preview', 'spectra-pro' ) }</Label>
								{/* Preview area with minimum height for consistent layout */}
								<div className="bg-background-primary overflow-hidden border border-slate-200 rounded p-8 flex items-center justify-center" style={ { minHeight: '60vh', position: 'relative' } }>
									{ isIframeLoading && (
										<div className="flex items-center justify-center h-full">
											<div className="flex flex-col items-center gap-3">
												<div className="animate-spin h-8 w-8 border-4 border-slate-200 border-t-blue-500 rounded-full"></div>
												<p className="text-sm text-slate-500">{ __( 'Loading the preview area…', 'spectra-pro' ) }</p>
												<Loader
													size="md"
													variant="primary"
												/>
											</div>
										</div>
									) }
									<iframe
										title={ __( 'Spectra GS Preview', 'spectra-pro' ) }
										src={ window?.spectra_admin_gs?.preview_url } 
										width='800' 
										height='600' 
										style={ { 
											width: '100%',
											display: isIframeLoading ? 'none' : 'block'
										} }
										onLoad={ () => {
											// Hide loader and show iframe
											setIsIframeLoading( false );
											// Show success badge
											setBadgeStatus( 'success' );
											// Hide success badge after 2 seconds
											setTimeout( () => {
												setBadgeStatus( 'hidden' );
											}, 2000 );
											// Generate initial CSS for saved block defaults when iframe loads
											setTimeout( () => {
												generateInitialBlockDefaultsCSS();
												if ( selectedBlock ) {
													const parentBlock = getParentBlock( selectedBlock );
													const context = { originalBlock: selectedBlock };
													setTimeout( () => sendBlockToIframe( parentBlock, context ), 200 );
												}
											}, 100 );
										} }
									/>
									{/* Status badges positioned absolutely in top-left */}
									{ badgeStatus === 'loading' && (
										<div style={ { position: 'absolute', top: '0.5rem', left: '0.5rem' } }>
											<Badge
												disableHover
												icon={ <CircleFadingPlus /> }
												label={ __( 'Preview Loading…', 'spectra-pro' ) }
												size="md"
												type="rounded"
												variant="blue"
											/>
										</div>
									) }
									{ badgeStatus === 'success' && (
										<div style={ { position: 'absolute', top: '0.5rem', left: '0.5rem' } }>
											<Badge
												disableHover
												icon={ <CircleCheckBig /> }
												label={ __( 'Preview Loaded!', 'spectra-pro' ) }
												size="md"
												type="rounded"
												variant="green"
											/>
										</div>
									) }
								</div>
							</div>
						</Container.Item>
					</Container>
				</Container>
			</Container>
		</>
	);
};

export default BlockDefaults;