/**
 * WordPress dependencies
 */
import { useSelect, useDispatch, select } from '@wordpress/data';
import { useInstanceId } from '@wordpress/compose';
import { useEffect, useCallback, useState, useMemo, useRef } from '@wordpress/element';
import {
	BlockControls,
	InspectorControls,
	useBlockProps,
	store as blockEditorStore,
	useInnerBlocksProps,
	InnerBlocks,
} from '@wordpress/block-editor';
import { __ } from '@wordpress/i18n';
import { store as coreStore } from '@wordpress/core-data';
import { Spinner, Button } from '@wordpress/components';
import apiFetch from '@wordpress/api-fetch';


/**
 * Internal dependencies
 */
import SimpleInspectorControls from './inspector-controls/simple-controls';
import UserDirectoryToolbar from './user-directory-toolbar';
import SearchBarPreview from './search-bar-preview';
import SortingFieldsPreview from './sorting-fields-preview';
import DirectoryLayoutSelection from './directory-layout-selection';
import DirectoryConfirmationModal from './directory-confirmation-modal';
import { useUserFromParent } from '../../../utils/user-context';
import { getTemplate } from '../templates';
import { useUserDirectoryStore } from '../../../stores/user-directory-store';

// Register custom WordPress data store for directory state management
if (!wp.data.select('wpuf-ud/directory-state')) {
    wp.data.registerStore('wpuf-ud/directory-state', {
        reducer: (state = {}, action) => {
            let newState;
            switch (action.type) {
                case 'STORE_LAYOUT_STATE':
                    newState = {
                        ...state,
                        [action.layoutName]: {
                            ...action.stateSnapshot,
                            storedAt: Date.now()
                        }
                    };
                    return newState;
                case 'CLEAR_LAYOUT_STATE':
                    newState = { ...state };
                    delete newState[action.layoutName];
                    return newState;
                case 'CLEAR_ALL_STATES':
                    return {};
                default:
                    return state;
            }
        },
        actions: {
            storeLayoutState: (layoutName, stateSnapshot) => ({
                type: 'STORE_LAYOUT_STATE',
                layoutName,
                stateSnapshot
            }),
            clearLayoutState: (layoutName) => ({
                type: 'CLEAR_LAYOUT_STATE',
                layoutName
            }),
            clearAllStates: () => ({
                type: 'CLEAR_ALL_STATES'
            })
        },
        selectors: {
            getStoredState: (state, layoutName) => state[layoutName] || null,
            getAllStoredStates: (state) => state,
            getStoredLayoutNames: (state) => Object.keys(state),
            hasStoredState: (state, layoutName) => !!state[layoutName]
        }
    });
}

const ALLOWED_BLOCKS = [
	'wpuf-ud/directory-item',
	'core/group',
	'core/button',
	'wpuf-ud/button',
];

const TEMPLATE = [
	['wpuf-ud/directory-item', {}],
];

// Get template by layout name - now using centralized template system
const getLayoutTemplate = (layoutName) => {
	return getTemplate(layoutName);
};

// Deep state cloning function to capture complete block state
const captureCurrentState = (clientId, innerBlocks, selectedLayout, attributes) => {
    const select = wp.data.select;
    const blockEditor = select('core/block-editor');

    // Get all inner blocks recursively with full state
    const captureInnerBlocks = (blocks, depth = 0) => {
        if (!Array.isArray(blocks)) return [];

        return blocks.map((block, index) => {
            if (!block || !block.name) return null;

            // Get the complete block object from the store
            const fullBlock = blockEditor.getBlock(block.clientId) || block;

            // Deep clone attributes to avoid reference issues
            const clonedAttributes = JSON.parse(JSON.stringify(fullBlock.attributes || {}));

            // Recursively capture inner blocks using the full block from store
            const innerBlocksCaptured = fullBlock.innerBlocks && fullBlock.innerBlocks.length > 0
                ? captureInnerBlocks(fullBlock.innerBlocks, depth + 1)
                : [];



            // Check if block type is available
            let blockTypeInfo = null;
            try {
                blockTypeInfo = wp.blocks.getBlockType ? wp.blocks.getBlockType(block.name) : null;
            } catch (error) {
                console.warn(`Could not get block type for ${block.name}:`, error);
            }

            return {
                name: block.name,
                attributes: clonedAttributes,
                innerBlocks: innerBlocksCaptured,
                clientId: block.clientId,
                // Store additional metadata
                isValid: blockTypeInfo !== null,
                // Capture block order for restoration
                originalIndex: index,
                depth: depth,
                // Store block type info for debugging
                blockType: blockTypeInfo
            };
        }).filter(block => block !== null);
    };

    // Capture the complete state
    const capturedInnerBlocks = captureInnerBlocks(innerBlocks);
    

    
    const stateSnapshot = {
        // Block container information
        containerClientId: clientId,
        selectedLayout: selectedLayout,
        containerAttributes: { ...attributes },

        // All inner blocks with complete state
        innerBlocks: capturedInnerBlocks,

        // Metadata for restoration
        capturedAt: Date.now(),
        blockCount: innerBlocks ? innerBlocks.length : 0,

        // Directory-specific context
        directoryId: attributes.directory_id,
        roles: attributes.roles,
        maxItemPerPage: attributes.max_item_per_page,
        enableFrontendSorting: attributes.enable_frontend_sorting,
        enableSearch: attributes.enable_search,
        orderby: attributes.orderby,
        order: attributes.order
    };

    return stateSnapshot;
};

// Function to restore captured state
const restoreCapturedState = (stateSnapshot, replaceInnerBlocks, setAttributes) => {
    if (!stateSnapshot || !stateSnapshot.innerBlocks) {
        return false;
    }

    try {
        // Restore container attributes
        if (stateSnapshot.containerAttributes) {
            setAttributes({
                ...stateSnapshot.containerAttributes,
                // Ensure we don't override critical attributes
                hasSelectedLayout: true,
                selectedLayout: stateSnapshot.selectedLayout
            });
        }

        // Convert captured blocks back to block objects for restoration
        const restoreBlocksRecursively = (capturedBlocks) => {
            if (!Array.isArray(capturedBlocks)) return [];

            return capturedBlocks.map(capturedBlock => {
                if (!capturedBlock || !capturedBlock.name) return null;

                try {
                    // Create a new block with the captured attributes
                    const block = wp.blocks.createBlock(
                        capturedBlock.name,
                        capturedBlock.attributes,
                        capturedBlock.innerBlocks ? restoreBlocksRecursively(capturedBlock.innerBlocks) : []
                    );

                    return block;
                } catch (error) {
                    return null;
                }
            }).filter(block => block !== null);
        };

        const restoredBlocks = restoreBlocksRecursively(stateSnapshot.innerBlocks);

        // Replace inner blocks with restored blocks
        if (restoredBlocks.length > 0) {
            replaceInnerBlocks(stateSnapshot.containerClientId, restoredBlocks);
            return true;
        } else {
            return false;
        }

    } catch (error) {
        return false;
    }
};

// Function to process template with selective block replacement
const processTemplateWithState = (template, currentState) => {
    if (!template || !Array.isArray(template)) {
        return template;
    }

    if (!currentState || !currentState.innerBlocks) {
        return template;
    }



    // Find the directory-item block in current state
    const currentDirectoryItem = currentState.innerBlocks.find(block => block.name === 'wpuf-ud/directory-item');
    
    if (!currentDirectoryItem) {
        return template;
    }

    // Collect all wpuf-ud/* blocks from inside the directory-item (excluding directory-item itself)
    const availableWpufBlocks = new Map();
    const processedBlocks = new Set();

    const collectWpufBlocksFromDirectoryItem = (blocks, depth = 0) => {
        if (!Array.isArray(blocks)) return;

        blocks.forEach((block, index) => {
            if (!block || !block.name) return;

            // Only collect wpuf-ud/* blocks (excluding directory-item and unmatched-blocks)
            if (block.name.startsWith('wpuf-ud/') && 
                block.name !== 'wpuf-ud/directory-item' && 
                block.name !== 'wpuf-ud/unmatched-blocks' &&
                !processedBlocks.has(block.clientId)) {
                
                const blockKey = block.name;
                
                // Store first occurrence
                if (!availableWpufBlocks.has(blockKey)) {
                    availableWpufBlocks.set(blockKey, {
                        block: block,
                        clientId: block.clientId,
                        depth: depth,
                        index: index
                    });
                }
            }

            // Recursively process inner blocks - this is the key fix!
            if (block.innerBlocks && block.innerBlocks.length > 0) {
                collectWpufBlocksFromDirectoryItem(block.innerBlocks, depth + 1);
            }
        });
    };

    // Collect wpuf blocks from inside the directory-item
    collectWpufBlocksFromDirectoryItem(currentDirectoryItem.innerBlocks || []);



    // Process template recursively, focusing on the directory-item structure
    const processTemplateRecursively = (templateBlocks, depth = 0) => {
        if (!Array.isArray(templateBlocks)) return templateBlocks;

        return templateBlocks.map(templateBlock => {
            if (!Array.isArray(templateBlock) || templateBlock.length === 0) {
                return templateBlock;
            }

            const [blockName, attributes = {}, innerContent = []] = templateBlock;

            // If this is the directory-item block, process its inner content specially
            if (blockName === 'wpuf-ud/directory-item') {
                // Process the inner content of directory-item
                const processedInnerContent = Array.isArray(innerContent) ? 
                    processDirectoryItemInnerContent(innerContent, availableWpufBlocks, processedBlocks) : [];
                
                return [
                    blockName,
                    attributes, // Keep template attributes for directory-item
                    processedInnerContent
                ];
            }

            // For non-directory-item blocks, process normally
            return [
                blockName,
                attributes,
                Array.isArray(innerContent) ? processTemplateRecursively(innerContent, depth + 1) : []
            ];
        });
    };

    // Special function to process directory-item inner content
    const processDirectoryItemInnerContent = (innerContent, availableWpufBlocks, processedBlocks) => {
        if (!Array.isArray(innerContent)) return innerContent;



        const processedItems = innerContent.map(item => {
            if (!Array.isArray(item) || item.length === 0) {
                return item;
            }

            const [blockName, attributes = {}, itemInnerContent = []] = item;



            // Special handling for unmatched-blocks insertion point
            if (blockName === 'wpuf-ud/unmatched-blocks') {
                return {
                    type: 'insertion-point'
                };
            }

            // If this is a wpuf-ud/* block, check if we have a replacement
            if (blockName.startsWith('wpuf-ud/')) {
                const replacement = availableWpufBlocks.get(blockName);
                
                if (replacement) {
                    // Mark this block as processed
                    processedBlocks.add(replacement.clientId);
                    
                    // Use stored attributes and process inner blocks
                    const processedInnerBlocks = replacement.block.innerBlocks ? 
                        processDirectoryItemInnerContent(replacement.block.innerBlocks, availableWpufBlocks, processedBlocks) : [];
                    
                    return [
                        blockName,
                        replacement.block.attributes, // Use stored attributes
                        processedInnerBlocks
                    ];
                } else {
                    // Keep template default if no replacement found
                    return [
                        blockName,
                        attributes,
                        Array.isArray(itemInnerContent) ? processDirectoryItemInnerContent(itemInnerContent, availableWpufBlocks, processedBlocks) : []
                    ];
                }
            } else {
                // Non-wpuf-ud/* block - keep as-is but process inner content
                return [
                    blockName,
                    attributes,
                    Array.isArray(itemInnerContent) ? processDirectoryItemInnerContent(itemInnerContent, availableWpufBlocks, processedBlocks) : []
                ];
            }
        }).filter(item => item !== null); // Filter out null values but keep insertion points

        return processedItems;
    };

    // Process the template
    const processedTemplate = processTemplateRecursively(template);

    // Recursively collect unmatched blocks from current state
    const unmatchedBlocks = [];
    
    // Define layout blocks that should not be preserved
    const layoutBlocks = [
        'core/group',
        'core/columns', 
        'core/column',
        'core/row',
        'core/stack'
    ];
    
    const collectUnmatchedBlocks = (blocks, depth = 0) => {
        if (!Array.isArray(blocks)) return;

        blocks.forEach((block, index) => {
            if (!block || !block.name) return;



            // If it's any block and we haven't processed it yet
            if (!processedBlocks.has(block.clientId)) {
                // Skip layout blocks - they should not be preserved, but still process their inner blocks
                if (layoutBlocks.includes(block.name)) {
                    // Don't return here - continue to process inner blocks
                } else {
                                    // Skip directory-item block - it should always use the template's directory-item
                if (block.name === 'wpuf-ud/directory-item') {
                    // But still process its inner blocks recursively
                    if (block.innerBlocks && block.innerBlocks.length > 0) {
                        collectUnmatchedBlocks(block.innerBlocks, depth + 1);
                    }
                    return;
                }
                    
                unmatchedBlocks.push(block);
            }
        }

        // Recursively process inner blocks
        if (block.innerBlocks && block.innerBlocks.length > 0) {
            collectUnmatchedBlocks(block.innerBlocks, depth + 1);
        }
    });
};

    // Collect unmatched blocks from the current state
    // We need to collect from the complete state structure, not just top-level blocks
    collectUnmatchedBlocks(currentState.innerBlocks);
    


    // Insert unmatched blocks at specific insertion points
    if (unmatchedBlocks.length > 0) {
        
        // Convert unmatched blocks to template format
        const unmatchedTemplateBlocks = unmatchedBlocks.map(block => [
            block.name,
            block.attributes,
            block.innerBlocks ? processDirectoryItemInnerContent(block.innerBlocks, availableWpufBlocks, processedBlocks) : []
        ]);



        // Replace insertion point markers with unmatched blocks
        let insertionPointsReplaced = 0;
        
        const replaceInsertionPoints = (blocks, depth = 0) => {
            if (!Array.isArray(blocks)) return blocks;

            const result = [];
            
            for (let i = 0; i < blocks.length; i++) {
                const block = blocks[i];
                
                // Handle insertion point markers - replace with unmatched blocks
                if (block && typeof block === 'object' && block.type === 'insertion-point') {
                    result.push(...unmatchedTemplateBlocks);
                    insertionPointsReplaced++;
                    continue;
                }
                
                if (!Array.isArray(block) || block.length === 0) {
                    result.push(block);
                    continue;
                }

                const [blockName, attributes = {}, innerContent = []] = block;

                // Process inner content recursively
                const processedInnerContent = Array.isArray(innerContent) ? replaceInsertionPoints(innerContent, depth + 1) : innerContent;

                result.push([blockName, attributes, processedInnerContent]);
            }

            return result;
        };



        // Replace insertion points with unmatched blocks
        const finalTemplate = replaceInsertionPoints(processedTemplate);
        
        // Only append to the end if no insertion points were replaced
        if (insertionPointsReplaced === 0) {
            finalTemplate.push(...unmatchedTemplateBlocks);
        }

        // Safety check: ensure we have a directory-item block
        const hasDirectoryItem = finalTemplate.some(block => 
            Array.isArray(block) && block.length > 0 && block[0] === 'wpuf-ud/directory-item'
        );

        if (!hasDirectoryItem) {
            console.warn('⚠️ Directory: No directory-item found in processed template, using original template');
            return template;
        }

        return finalTemplate;
    }

    // Safety check: ensure we have a directory-item block
    const hasDirectoryItem = processedTemplate.some(block => 
        Array.isArray(block) && block.length > 0 && block[0] === 'wpuf-ud/directory-item'
    );

    if (!hasDirectoryItem) {
        console.warn('⚠️ Directory: No directory-item found in processed template, using original template');
        return template;
    }

    return processedTemplate;
};

// Function to check if we have a stored state for a layout using WordPress store
    const getStoredStateForLayout = (layoutName) => {
        const storedState = wp.data.select('wpuf-ud/directory-state').getStoredState(layoutName);
        
        if (storedState) {
            return storedState;
        }
        return null;
    };

// Function to manually restore a stored layout state using WordPress store
const restoreLayoutState = (layoutName, replaceInnerBlocks, setAttributes) => {
    const storedState = getStoredStateForLayout(layoutName);
    if (!storedState) {
        return false;
    }

    try {
        // Use the existing restoreCapturedState function
        const restoreResult = restoreCapturedState(storedState, replaceInnerBlocks, setAttributes);
        return restoreResult;
    } catch (error) {
        return false;
    }
};

// Helper function to convert template to blocks safely (filters out unmatched-blocks markers)
const convertTemplateToBlocks = (template, depth = 0) => {
    if (!Array.isArray(template)) {
        return [];
    }

    if (typeof wp === 'undefined' || !wp.blocks || !wp.blocks.createBlock) {
        return [];
    }

    // Prevent infinite recursion
    if (depth > 10) {
        console.warn('Directory: Maximum recursion depth reached, stopping template conversion');
        return [];
    }

    const result = [];

    template.forEach(item => {
        if (!Array.isArray(item) || item.length === 0) {
            return;
        }

        const [blockName, attributes = {}, innerContent = []] = item;

        if (typeof blockName !== 'string') {
            return;
        }

        // Skip insertion point markers - they should have been replaced with actual blocks by now
        if (blockName === 'wpuf-ud/unmatched-blocks') {
            console.warn('Directory: Found unmatched-blocks marker in convertTemplateToBlocks - this should not happen');
            return;
        }

        try {
            // Convert inner content to blocks recursively
            const innerBlocks = Array.isArray(innerContent) ? convertTemplateToBlocks(innerContent, depth + 1) : [];

            const block = wp.blocks.createBlock(blockName, attributes, innerBlocks);
            

            
            if (block) {
                result.push(block);
            }
        } catch (error) {
            console.warn('Failed to create block:', blockName, error);
        }
    });

    return result;
};

// Helper function to create blocks safely
const createBlocksSafely = (template) => {
    try {
        return convertTemplateToBlocks(template);
    } catch (error) {
        // Try to create a minimal fallback template
        try {
            return convertTemplateToBlocks([
                ['core/group', {className: 'wpuf-directory-fallback'}, [
                    ['core/heading', {level: 2}, 'User Directory'],
                    ['core/paragraph', {}, 'Directory content will be displayed here.']
                ]]
            ]);
        } catch (fallbackError) {
            return [];
        }
    }
};

// Helper function to render table preview in editor
const renderTablePreview = (attributes, realUsers = []) => {
    // Get table settings
    const show_avatar = attributes.show_avatar !== false; // Default to true
    const avatar_size = attributes.avatar_size || 'medium';
    const avatar_shape = attributes.avatar_shape || 'circle';
    const avatar_fallback_type = attributes.avatar_fallback_type || 'initial';
    const table_columns = Array.isArray(attributes.table_columns) ? attributes.table_columns : ['username', 'email', 'display_name'];
    
    // Use real users if available, otherwise fall back to sample data
    const users = realUsers.length > 0 ? realUsers : [
        {
            id: 1,
            user_login: 'john_doe',
            user_email: 'john@example.com',
            display_name: 'John Doe',
            first_name: 'John',
            last_name: 'Doe',
            nickname: 'Johnny',
            user_url: 'https://example.com'
        },
        {
            id: 2,
            user_login: 'jane_smith',
            user_email: 'jane@example.com',
            display_name: 'Jane Smith',
            first_name: 'Jane',
            last_name: 'Smith',
            nickname: 'Jane',
            user_url: 'https://jane.com'
        },
        {
            id: 3,
            user_login: 'bob_wilson',
            user_email: 'bob@example.com',
            display_name: 'Bob Wilson',
            first_name: 'Bob',
            last_name: 'Wilson',
            nickname: 'Bobby',
            user_url: ''
        }
    ];

    // Helper function to get column label
    const getColumnLabel = (column) => {
        const labels = {
            'username': __('Username', 'wpuf-pro'),
            'first_name': __('First Name', 'wpuf-pro'),
            'last_name': __('Last Name', 'wpuf-pro'),
            'nickname': __('Nickname', 'wpuf-pro'),
            'display_name': __('Display Name', 'wpuf-pro'),
            'email': __('Email', 'wpuf-pro'),
            'website': __('Website', 'wpuf-pro'),
            'bio': __('Bio', 'wpuf-pro'),
            'registered_date': __('Registration Date', 'wpuf-pro'),
            'posts_count': __('Posts Count', 'wpuf-pro'),
            'comments_count': __('Comments Count', 'wpuf-pro'),
            'location': __('Location', 'wpuf-pro')
        };
        
        // If we have a predefined label, use it
        if (labels[column]) {
            return labels[column];
        }
        
        // For meta keys (like delivery_location, user_phone_no), format them to be readable
        // Convert underscores to spaces and capitalize first letter of each word
        if (column.includes('_')) {
            return column.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
        }
        
        // For single words, just capitalize the first letter
        return column.charAt(0).toUpperCase() + column.slice(1);
    };

    // Helper function to render cell content
    const renderCellContent = (user, column) => {
        switch (column) {
            case 'username':
                return <span className="wpuf-text-sm wpuf-font-medium wpuf-text-gray-900">{user.user_login}</span>;
            case 'first_name':
                return <span className="wpuf-text-sm wpuf-text-gray-900">{user.first_name}</span>;
            case 'last_name':
                return <span className="wpuf-text-sm wpuf-text-gray-900">{user.last_name}</span>;
            case 'nickname':
                return <span className="wpuf-text-sm wpuf-text-gray-900">{user.nickname}</span>;
            case 'display_name':
                return <span className="wpuf-text-sm wpuf-font-medium wpuf-text-gray-900">{user.display_name}</span>;
            case 'email':
                return <span className="wpuf-text-sm wpuf-text-gray-900">{user.user_email}</span>;
            case 'website':
                return user.user_url ? (
                    <a href={user.user_url} className="wpuf-text-sm wpuf-text-blue-600 hover:wpuf-text-blue-800" target="_blank" rel="noopener noreferrer">
                        {user.user_url}
                    </a>
                ) : (
                    <span className="wpuf-text-sm wpuf-text-gray-400">-</span>
                );
            case 'bio':
                return user.description ? (
                    <span className="wpuf-text-sm wpuf-text-gray-900 wpuf-line-clamp-2">{user.description}</span>
                ) : (
                    <span className="wpuf-text-sm wpuf-text-gray-400">-</span>
                );
            case 'registered_date':
                return user.user_registered ? (
                    <span className="wpuf-text-sm wpuf-text-gray-900">
                        {new Date(user.user_registered).toLocaleDateString()}
                    </span>
                ) : (
                    <span className="wpuf-text-sm wpuf-text-gray-400">-</span>
                );
            case 'posts_count':
                return user.posts_count !== undefined ? (
                    <span className="wpuf-text-sm wpuf-text-gray-900">{user.posts_count}</span>
                ) : (
                    <span className="wpuf-text-sm wpuf-text-gray-400">-</span>
                );
            case 'comments_count':
                return user.comments_count !== undefined ? (
                    <span className="wpuf-text-sm wpuf-text-gray-900">{user.comments_count}</span>
                ) : (
                    <span className="wpuf-text-sm wpuf-text-gray-400">-</span>
                );
            default:
                // Handle meta fields dynamically
                if (user[column] !== undefined && user[column] !== null && user[column] !== '') {
                    // For meta fields, display the value
                    return <span className="wpuf-text-sm wpuf-text-gray-900">{user[column]}</span>;
                } else {
                    // For empty meta fields, show a dash
                    return <span className="wpuf-text-sm wpuf-text-gray-400">-</span>;
                }
        }
    };

    // Helper function to render avatar with real data fetching
    const AvatarComponent = ({ user, size, shape, fallbackType }) => {
        const [avatarData, setAvatarData] = useState(null);
        const [isLoading, setIsLoading] = useState(false);
        const [error, setError] = useState(null);

        // Calculate display size
        const getDisplaySize = () => {
            const sizeMap = {
                'small': 32,
                'medium': 96,
                'large': 150,
                'xlarge': 300,
            };
            return sizeMap[size] || 96;
        };

        // Fetch avatar data
        const fetchAvatarData = async () => {
            if (user.id === 0) {
                return null; // Sample user, no real data
            }

            try {
                setIsLoading(true);
                setError(null);
                const displaySize = getDisplaySize();
                const response = await fetch(`/wp-json/wpuf-pro/v1/user/${user.id}/avatar?size=${displaySize}&fallback_type=${fallbackType}`);
                
                if (response.ok) {
                    const data = await response.json();
                    setAvatarData(data);
                } else {
                    console.warn('Failed to fetch avatar data:', response.status);
                    setError('Failed to load avatar');
                }
            } catch (error) {
                console.warn('Error fetching avatar data:', error);
                setError('Error loading avatar');
            } finally {
                setIsLoading(false);
            }
        };

        // Fetch avatar on mount
        useEffect(() => {
            if (user.id > 0) {
                fetchAvatarData();
            }
        }, [user.id, size, fallbackType]);

        // Get size and shape classes
        const sizeClasses = {
            'small': 'wpuf-w-8 wpuf-h-8',
            'medium': 'wpuf-w-24 wpuf-h-24',
            'large': 'wpuf-w-36 wpuf-h-36',
            'xlarge': 'wpuf-w-72 wpuf-h-72',
        };
        
        const shapeClasses = {
            'circle': 'wpuf-rounded-full',
            'squared': 'wpuf-rounded-none',
            'rounded': 'wpuf-rounded-lg',
        };
        
        const sizeClass = sizeClasses[size] || sizeClasses['medium'];
        const shapeClass = shapeClasses[shape] || shapeClasses['circle'];

        // Render loading state
        if (isLoading) {
            return (
                <div className={`${sizeClass} ${shapeClass} wpuf-bg-gray-200 wpuf-flex wpuf-items-center wpuf-justify-center`}>
                    <div className="wpuf-animate-spin wpuf-w-4 wpuf-h-4 wpuf-border-2 wpuf-border-gray-300 wpuf-border-t-blue-600 wpuf-rounded-full"></div>
                </div>
            );
        }

        // Render error state
        if (error) {
            return (
                <div className={`${sizeClass} ${shapeClass} wpuf-bg-red-100 wpuf-flex wpuf-items-center wpuf-justify-center`}>
                    <span className="wpuf-text-xs wpuf-text-red-600">!</span>
                </div>
                );
        }

        // Render real avatar if available
        if (avatarData && avatarData.url) {
            return (
                <img
                    src={avatarData.url}
                    alt={avatarData.alt || user.display_name}
                    className={`${sizeClass} ${shapeClass} wpuf-object-cover`}
                />
            );
        }

        // Fallback to initials
        const initials = user.display_name.substring(0, 2).toUpperCase();
        return (
            <div className={`${sizeClass} ${shapeClass} wpuf-bg-gray-300 wpuf-flex wpuf-items-center wpuf-justify-center wpuf-text-sm wpuf-font-medium wpuf-text-gray-700`}>
                {initials}
            </div>
        );
    };

    return (
        <div className="wpuf-overflow-x-auto">
            <div className="wpuf-inline-block wpuf-min-w-full wpuf-align-middle">
                <div className="wpuf-overflow-hidden wpuf-shadow wpuf-outline wpuf-outline-1 wpuf-outline-black/5 sm:wpuf-rounded-lg">
                    <table className="wpuf-relative wpuf-min-w-full wpuf-divide-y wpuf-divide-gray-300">
                        <thead className="wpuf-bg-gray-50">
                            <tr>
                                {show_avatar && (
                                    <th scope="col" className="wpuf-py-3.5 wpuf-pl-4 wpuf-pr-3 wpuf-text-left wpuf-text-sm wpuf-font-semibold wpuf-text-gray-900 sm:wpuf-pl-6">
                                        {__('Avatar', 'wpuf-pro')}
                                    </th>
                                )}
                                {table_columns.map(column => (
                                    <th key={column} scope="col" className="wpuf-px-3 wpuf-py-3.5 wpuf-text-left wpuf-text-sm wpuf-font-semibold wpuf-text-gray-900">
                                        {getColumnLabel(column)}
                                    </th>
                                ))}
                                <th scope="col" className="wpuf-py-3.5 wpuf-pl-3 wpuf-pr-4 sm:wpuf-pr-6">
                                    <span className="wpuf-sr-only">{__('Actions', 'wpuf-pro')}</span>
                                </th>
                            </tr>
                        </thead>
                        <tbody className="wpuf-divide-y wpuf-divide-gray-200 wpuf-bg-white">
                            {users.map(user => (
                                <tr key={user.id} className="wpuf-hover:wpuf-bg-gray-50">
                                    {show_avatar && (
                                        <td className="wpuf-whitespace-nowrap wpuf-py-4 wpuf-pl-4 wpuf-pr-3 sm:wpuf-pl-6">
                                            <AvatarComponent 
                                                user={user} 
                                                size={avatar_size} 
                                                shape={avatar_shape} 
                                                fallbackType={avatar_fallback_type}
                                            />
                                        </td>
                                    )}
                                    {table_columns.map(column => (
                                        <td key={column} className="wpuf-whitespace-nowrap wpuf-px-3 wpuf-py-4 wpuf-text-sm wpuf-text-gray-500">
                                            {renderCellContent(user, column)}
                                        </td>
                                    ))}
                                    <td className="wpuf-whitespace-nowrap wpuf-py-4 wpuf-pl-3 wpuf-pr-4 wpuf-text-right wpuf-text-sm wpuf-font-medium sm:wpuf-pr-6">
                                        <span 
                                            className="wpuf-inline-flex wpuf-items-center wpuf-px-3 wpuf-py-1.5 wpuf-border wpuf-border-transparent wpuf-text-xs wpuf-font-medium wpuf-rounded-md wpuf-text-white wpuf-bg-emerald-600"
                                            style={{ cursor: 'pointer' }}
                                        >
                                            {__('View Profile', 'wpuf-pro')}
                                        </span>
                                    </td>
                                </tr>
                            ))}
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    );
};

const UserDirectoryContent = ({ attributes, setAttributes, clientId }) => {
	const blockProps = useBlockProps();
	const { replaceInnerBlocks, updateBlockAttributes } = useDispatch(blockEditorStore);
	const innerBlocksProps = useInnerBlocksProps(blockProps, {
		allowedBlocks: ALLOWED_BLOCKS,
		template: TEMPLATE,
		orientation: 'horizontal',
	});

	// Ref to track programmatic updates
	const isUpdatingRef = useRef(false);
	const previousLayoutRef = useRef(attributes.directory_layout);
	const updateCountRef = useRef(0);
	const userInitiatedChangeRef = useRef(false);
	const isTemplateSwitchingRef = useRef(false); // Track template switching operations
	const hasInitializedRef = useRef(false); // Track if component has initialized

	// Layout selection state
	const [showLayoutSelection, setShowLayoutSelection] = useState(false);
	const [showConfirmation, setShowConfirmation] = useState(false);
	const [pendingLayout, setPendingLayout] = useState(null);
	const [pendingTemplate, setPendingTemplate] = useState(null);
	const [isSwitchingLayout, setIsSwitchingLayout] = useState(false);
	const [previousLayout, setPreviousLayout] = useState(null);

	// Get WordPress store selectors and dispatchers for directory state
	const directoryStateSelect = useSelect((select) => select('wpuf-ud/directory-state'), []);
	const directoryStateDispatch = useDispatch('wpuf-ud/directory-state');

	// Get stored states from WordPress store with proper reactivity
	const preservedStates = useSelect((select) => {
		const states = select('wpuf-ud/directory-state').getAllStoredStates();
		return states;
	}, []);
	
	const storedLayoutNames = useSelect((select) => {
		const names = select('wpuf-ud/directory-state').getStoredLayoutNames();
		return names;
	}, []);

	        // Function to store previous state using WordPress store
    const storePreviousState = (currentState) => {
        if (!currentState) {
            return;
        }

        // Store as single "previous_state" in WordPress data store
        try {
            directoryStateDispatch.storeLayoutState('previous_state', currentState);
        } catch (error) {
            console.error('Directory: Error storing previous state:', error);
        }
    };

	// Get current variation from block attributes
	const currentVariation = useSelect(
		(select) => {
			const block = select(blockEditorStore).getBlock(clientId);
			return block?.attributes?.variation || null;
		},
		[clientId]
	);

	// Memoize the variation to prevent unnecessary re-renders and logging
	const memoizedVariation = useMemo(() => {
		return currentVariation;
	}, [currentVariation]);

	// Get user data from parent context if available
	const userData = useUserFromParent(clientId);

	// Get real users from the user directory store
	const { users, loading, error, fetchUsersPreview } = useUserDirectoryStore();

	    // Handle layout selection with selective block replacement
    const handleLayoutSelection = (layoutName, template) => {
        // Handle table layout differently - it's settings-driven without inner blocks
        if (layoutName === 'table') {
            // For table layout, proceed immediately without template processing
            applyLayoutSelection(layoutName, null);
            return;
        }

        // Check if we have stored previous state
        const previousState = getStoredStateForLayout('previous_state');

        if (previousState) {
            // Process template with selective block replacement
            const processedTemplate = processTemplateWithState(template, previousState);

            // Apply the processed template
            applyLayoutSelection(layoutName, processedTemplate);
        } else {
            // Check if there are existing inner blocks that would be replaced
            const innerBlocks = select(blockEditorStore).getBlocks(clientId);
            const hasExistingBlocks = innerBlocks && innerBlocks.length > 0;

            if (hasExistingBlocks && layoutName !== 'table') {
                // Show confirmation modal (except for table layout)
                setPendingLayout(layoutName);
                setPendingTemplate(template);
                setShowConfirmation(true);
                return;
            }

            // No existing blocks or table layout, proceed immediately
            applyLayoutSelection(layoutName, template);
        }
    };

	    // Apply layout selection (called after confirmation or when no existing blocks)
    const applyLayoutSelection = (layoutName, templateName) => {
        // Set template switching flag to prevent duplicate block creation
        isTemplateSwitchingRef.current = true;

        setAttributes({
            hasSelectedLayout: true,
            selectedLayout: layoutName,
            directory_layout: layoutName,
            isSwitchingLayout: false
        });

        // Reset switching layout flag
        setIsSwitchingLayout(false);

        // Handle table layout differently - it's settings-driven without inner blocks
        if (layoutName === 'table') {
            // For table layout, clear all inner blocks since it's settings-driven
            replaceInnerBlocks(clientId, [], false);
        } else {
            // Use the provided template if available, otherwise get from layout name
            const template = templateName || getLayoutTemplate(layoutName);

            // Replace inner blocks with the new template
            if (template && template.length > 0) {
                try {
                    const blocks = createBlocksSafely(template);
                    
                    if (blocks && blocks.length > 0) {
                        replaceInnerBlocks(clientId, blocks, false);
                    }
                } catch (error) {
                    console.error('UserDirectoryContent: Error creating blocks from template:', error);
                }
            } else if (layoutName === 'blank') {
                // For blank layout, clear all blocks
                replaceInnerBlocks(clientId, [], false);
            } else {
                // For layouts without templates, clear blocks
                replaceInnerBlocks(clientId, [], false);
            }
        }

        // Reset template switching flag after a short delay to allow React to process
        setTimeout(() => {
            isTemplateSwitchingRef.current = false;
        }, 100);
    };

		// Handle confirmation modal actions
	const handleConfirmLayoutChange = () => {
		if (pendingLayout === 'clear') {
			// Store the current layout before clearing
			// Priority: selectedLayout > directory_layout
			const currentLayout = attributes.selectedLayout || attributes.directory_layout;

			if (currentLayout) {
				setPreviousLayout(currentLayout);
			}

			// Clear blocks and show layout selection
			// Don't set hasSelectedLayout to false - keep it true so we stay in content component
			replaceInnerBlocks(clientId, []);
			setIsSwitchingLayout(true);
			setAttributes({ isSwitchingLayout: true });
		} else if (pendingLayout && pendingTemplate) {
			applyLayoutSelection(pendingLayout, pendingTemplate);
		} else if (pendingLayout === 'table') {
			// Handle table layout specifically
			applyLayoutSelection(pendingLayout, null);
		}
		setShowConfirmation(false);
		setPendingLayout(null);
		setPendingTemplate(null);
	};

	const handleCancelLayoutChange = () => {
		setShowConfirmation(false);
		setPendingLayout(null);
		setPendingTemplate(null);
	};

		// Handle going back to current layout
	const handleBackToCurrentLayout = () => {
		// Reset switching layout flag
		setIsSwitchingLayout(false);
		setAttributes({ isSwitchingLayout: false });

		// Try to restore the exact previous state first (preserves user customizations)
		const previousState = getStoredStateForLayout('previous_state');
		
		if (previousState) {
			// Restore the complete previous state including customizations
			const restoreResult = restoreCapturedState(previousState, replaceInnerBlocks, setAttributes);
			
			if (restoreResult) {
				// Successfully restored previous state with customizations
				return;
			}
		}

		// Fallback: restore just the layout template (loses customizations)
		const layoutToRestore = previousLayout || attributes.selectedLayout || attributes.directory_layout;

		if (layoutToRestore) {
			
			setAttributes({
				hasSelectedLayout: true,
				selectedLayout: layoutToRestore,
				directory_layout: layoutToRestore
			});

			const template = getLayoutTemplate(layoutToRestore);

			if (template && template.length > 0) {
				try {
					const blocks = createBlocksSafely(template);

					if (blocks && blocks.length > 0) {
						replaceInnerBlocks(clientId, blocks, false);
					}
				} catch (error) {
					console.error('Error creating blocks from template:', error);
				}
			}
		} else {
			// If no layout is available, just reset the switching flag
			// This allows the user to see whatever content was there before
		}
	};

	// Sync variation with layout dropdown (only when variation changes from user action)
	useEffect(() => {
		if (isUpdatingRef.current) {
			isUpdatingRef.current = false;
			return;
		}

		// Only sync if this is NOT a user-initiated change
		if (!userInitiatedChangeRef.current && memoizedVariation && attributes.directory_layout !== memoizedVariation) {
			isUpdatingRef.current = true;
			setAttributes({ directory_layout: memoizedVariation });
		}

		// Reset user initiated flag after processing
		if (userInitiatedChangeRef.current) {
			userInitiatedChangeRef.current = false;
		}
	}, [memoizedVariation, attributes.directory_layout, setAttributes]);

	// Sync layout dropdown with variation and update inner blocks (only when layout changes from user action)
	useEffect(() => {
		if (isUpdatingRef.current) {
			isUpdatingRef.current = false;
			return;
		}

		// Check if layout actually changed (not just initial load)
		const layoutChanged = previousLayoutRef.current &&
			previousLayoutRef.current !== attributes.directory_layout;

		if (layoutChanged && attributes.directory_layout) {
			const newVariation = attributes.directory_layout;

			// Mark this as a user-initiated change
			userInitiatedChangeRef.current = true;

			// Update the variation attribute
			isUpdatingRef.current = true;
			setAttributes({ variation: newVariation });

			// Only update inner blocks if this is NOT a template switching operation
			// Template switching is handled by applyLayoutSelection, so we skip it here
			if (!isTemplateSwitchingRef.current) {
				// Update inner blocks to match the new variation
				const newTemplate = getLayoutTemplate(newVariation);

				if (newTemplate && newTemplate.length > 0) {
					try {
						const newBlocks = createBlocksSafely(newTemplate);
						replaceInnerBlocks(clientId, newBlocks, false);
					} catch (error) {
						// Error replacing inner blocks
					}
				}
			}
		}

		// Update the previous layout ref
		previousLayoutRef.current = attributes.directory_layout;
	}, [attributes.directory_layout, memoizedVariation, setAttributes, replaceInnerBlocks, clientId]);

	// Debug effect to track all attribute changes
	useEffect(() => {
		updateCountRef.current++;
	}, [attributes]);

	// Fetch users when component mounts or attributes change
	useEffect(() => {
		// Only fetch users for table layout
		if (attributes.directory_layout === 'table') {
			// Build filters based on current attributes
			// Only include attributes that affect the actual user list data
			const filters = {
				roles: attributes.roles || 'all',
				exclude_roles: attributes.exclude_roles || '',
				exclude_users: attributes.exclude_users || '',
				max_item_per_page: attributes.max_item_per_page || 10,
				// Note: orderby and order are not included in filters as they don't affect the user list
				// They are only used for frontend sorting display
				per_page: attributes.max_item_per_page || 10,
				page: 1,
				isPreview: true
			};

			// Convert string arrays to actual arrays if needed
			if (typeof filters.roles === 'string' && filters.roles !== 'all') {
				filters.roles = filters.roles.split(',').map(r => r.trim()).filter(r => r);
			}
			if (typeof filters.exclude_roles === 'string' && filters.exclude_roles !== '') {
				filters.exclude_roles = filters.exclude_roles.split(',').map(r => r.trim()).filter(r => r);
			}
			if (typeof filters.exclude_users === 'string' && filters.exclude_users !== '') {
				filters.exclude_users = filters.exclude_users.split(',').map(u => u.trim()).filter(u => u);
			}

			// Fetch users with the current filters
			fetchUsersPreview(filters);
			
			// Mark as initialized after first fetch
			if (!hasInitializedRef.current) {
				hasInitializedRef.current = true;
			}
		}
	}, [
		// Only refresh user list when these core attributes change:
		// - directory_layout: Changes the display mode
		// - roles: Changes which users are included
		// - exclude_roles: Changes which users are excluded
		// - exclude_users: Changes which specific users are excluded
		// - max_item_per_page: Changes pagination
		// 
		// Attributes that DON'T trigger refresh (display/sorting options):
		// - orderby, order: Only affect frontend sorting display
		// - enable_search, searchable_fields: Only affect search functionality
		// - avatar_size, avatar_shape, avatar_fallback_type: Only affect avatar display
		// - table_columns: Only affect table column display
		attributes.directory_layout,
		attributes.roles,
		attributes.exclude_roles,
		attributes.exclude_users,
		attributes.max_item_per_page,
		// Note: fetchUsersPreview is stable and won't cause unnecessary re-renders
		fetchUsersPreview
	]);

	// Show layout selection if switching layout
	if (isSwitchingLayout) {
		return (
			<DirectoryLayoutSelection
				clientId={clientId}
				attributes={attributes}
				setAttributes={setAttributes}
				onBack={handleBackToCurrentLayout}
				onLayoutSelect={handleLayoutSelection}
			/>
		);
	}

	return (
		<>
			<InspectorControls>
				<SimpleInspectorControls
					attributes={attributes}
					setAttributes={setAttributes}
                    onLayoutSelectionClick={() => {
						                    // Capture the complete current state before making any changes
                    const innerBlocks = select(blockEditorStore).getBlocks(clientId);

                    const currentState = captureCurrentState(
                        clientId,
                        innerBlocks,
                        attributes.selectedLayout || attributes.directory_layout,
                        attributes
                    );

                    // Store the previous state before making changes
                    storePreviousState(currentState);

                    // Store the current layout before clearing
                    // Priority: selectedLayout > directory_layout
                    const currentLayout = attributes.selectedLayout || attributes.directory_layout;

                    if (currentLayout) {
                        setPreviousLayout(currentLayout);
                    }

                    // Check if there are existing inner blocks that would be cleared
                    const hasExistingBlocks = innerBlocks && innerBlocks.length > 0;

                    if (hasExistingBlocks) {
                        // Show confirmation modal for clearing blocks
                        setPendingLayout('clear');
                        setPendingTemplate(null);
                        setShowConfirmation(true);
                    } else {
                        // No existing blocks, proceed immediately
                        // Don't set hasSelectedLayout to false - keep it true so we stay in content component
                        replaceInnerBlocks(clientId, []);
                        setIsSwitchingLayout(true);
                        setAttributes({ isSwitchingLayout: true });
                    }
					}}
				/>


			</InspectorControls>
			
			{(attributes.enable_search || attributes.enable_frontend_sorting) && (
				<div className='wpuf-flex wpuf-gap-4 wpuf-mb-4'>
					{attributes.enable_search && (
						<div className="wpuf-search-wrapper">
							<SearchBarPreview
								enabled={true}
								placeholder={attributes.search_placeholder ?? __('Search Users', 'wpuf-pro')}
							/>
						</div>
					)}

					{attributes.enable_frontend_sorting && (
						<div className="wpuf-sorting-wrapper">
							<SortingFieldsPreview
								enabled={true}
								orderby={attributes.orderby ?? 'id'}
								order={attributes.order ?? 'desc'}
							/>
						</div>
					)}
				</div>
			)}

			{attributes.selectedLayout === 'blank' ? (
				<div className="wpuf-blank-directory-container">
					<div className="wpuf-blank-directory-notice">
						<p>{__('Add blocks from the WPUF category to build your directory layout.', 'wpuf-pro')}</p>
					</div>
					<div {...innerBlocksProps}>
						{/* Inner blocks will be rendered here */}
					</div>
				</div>
			) : attributes.directory_layout === 'table' ? (
				<div 
					{...blockProps} 
					className="wpuf-table-preview-container wpuf-bg-white wpuf-border wpuf-border-gray-200 wpuf-rounded-lg wpuf-cursor-pointer hover:wpuf-shadow-md hover:wpuf-border-blue-300 hover:wpuf-bg-blue-50 wpuf-transition-all wpuf-duration-200 focus:wpuf-outline-none focus:wpuf-ring-2 focus:wpuf-ring-blue-500 focus:wpuf-ring-opacity-50"
					onClick={(e) => {
						// Prevent event bubbling to avoid conflicts
						e.stopPropagation();
						// Select the block when table preview is clicked
						const { selectBlock } = wp.data.dispatch('core/block-editor');
						if (selectBlock) {
							selectBlock(clientId);
						}
					}}
					onKeyDown={(e) => {
						// Allow keyboard navigation (Enter/Space to select)
						if (e.key === 'Enter' || e.key === ' ') {
							e.preventDefault();
							const { selectBlock } = wp.data.dispatch('core/block-editor');
							if (selectBlock) {
								selectBlock(clientId);
							}
						}
					}}
					tabIndex={0}
					role="button"
					aria-label={__('Click to select User Directory block', 'wpuf-pro')}
					title={__('Click to select this block', 'wpuf-pro')}
				>
					<div className="wpuf-table-preview">
						{loading ? (
							<div className="wpuf-flex wpuf-justify-center wpuf-items-center wpuf-py-8">
								<div className="wpuf-animate-spin wpuf-w-8 wpuf-h-8 wpuf-border-4 wpuf-border-gray-300 wpuf-border-t-blue-600 wpuf-rounded-full"></div>
								<span className="wpuf-ml-3 wpuf-text-gray-600">{__('Loading users...', 'wpuf-pro')}</span>
							</div>
						) : error ? (
							<div className="wpuf-text-center wpuf-py-8">
								<div className="wpuf-text-red-600 wpuf-mb-2">{__('Error loading users:', 'wpuf-pro')}</div>
								<div className="wpuf-text-sm wpuf-text-gray-600">{error}</div>
								<Button 
									variant="secondary" 
									onClick={() => {
										const filters = {
											roles: attributes.roles || 'all',
											exclude_roles: attributes.exclude_roles || '',
											exclude_users: attributes.exclude_users || '',
											max_item_per_page: attributes.max_item_per_page || 10,
											orderby: attributes.orderby || 'id',
											order: attributes.order || 'desc',
											enable_search: attributes.enable_search || true,
											searchable_fields: attributes.searchable_fields || ['user_login', 'user_email', 'display_name'],
											avatar_size: attributes.avatar_size || 'medium',
											per_page: attributes.max_item_per_page || 10,
											page: 1,
											isPreview: true
										};
										fetchUsersPreview(filters);
									}}
									className="wpuf-mt-3"
								>
									{__('Retry', 'wpuf-pro')}
								</Button>
							</div>
						) : (
							<>
								{renderTablePreview(attributes, users)}
							</>
						)}
					</div>
				</div>
			) : (
				<div {...innerBlocksProps}>
					{/* Inner blocks will be rendered here */}
				</div>
			)}

			{/* Confirmation Modal */}
			<DirectoryConfirmationModal
				isOpen={showConfirmation}
				onConfirm={handleConfirmLayoutChange}
				onCancel={handleCancelLayoutChange}
				title={__('Switch Layout', 'wpuf-pro')}
				message={
					pendingLayout === 'clear'
						? __('Switching the layout will clear your current customization. Are you sure you want to continue?', 'wpuf-pro')
						: __('Switching the layout might reset your current customization. Are you sure you want to continue?', 'wpuf-pro')
				}
				confirmText={__('Continue', 'wpuf-pro')}
				cancelText={__('Cancel', 'wpuf-pro')}
			/>
		</>
	);
};

export default UserDirectoryContent;
