/**
 * RSL JSON Layout Engine
 *
 * Enables declarative, JSON-driven layouts that integrate with RSL's slot-layout system.
 * Provides a powerful abstraction layer for creating, validating, and managing responsive
 * layouts through configuration objects instead of manual DOM manipulation.
 *
 * @fileoverview JSON-driven layout generator with schema validation and DOM synchronization
 * @version 1.0.0
 * @license MIT
 *
 * Key Features:
 * - JSON schema validation for layout configurations
 * - Declarative layout creation and updates
 * - Bidirectional DOM-to-JSON and JSON-to-DOM conversion
 * - Support for wrapper elements with standard or direct render modes
 * - Direct render mode for custom sections (footers, headers, navbars)
 * - Special component types (navbar, etc.)
 * - Diff-based layout updates for performance
 * - Import/export functionality
 * - Seamless integration with RSL grid system
 *
 * Usage:
 * // Basic layout rendering
 * const config = {
 *   version: 1,
 *   layoutId: "my-layout",
 *   breakpoints: { xs: 1, md: 3 },
 *   items: [
 *     { id: "item1", content: { type: "text", value: "Hello" } }
 *   ]
 * };
 * RSL.JSONLayout.renderLayout('#container', config);
 *
 * // Extract JSON from existing DOM
 * const config = RSL.JSONLayout.buildFromDOM('#container');
 *
 * // Update existing layout with diff
 * RSL.JSONLayout.updateLayoutFromJSON('#container', newConfig);
 *
 * Public API:
 * - RSL.JSONLayout.validateSchema(config) - Validate JSON configuration
 * - RSL.JSONLayout.renderLayout(container, config) - Create/update layout from JSON
 * - RSL.JSONLayout.buildFromDOM(container) - Extract JSON from DOM
 * - RSL.JSONLayout.updateLayoutFromJSON(container, config) - Diff-based update
 * - RSL.JSONLayout.exportJSON(config, pretty) - Serialize configuration
 * - RSL.JSONLayout.importJSON(jsonString) - Parse and validate JSON
 */

(function() {
    'use strict';

    /**
     * Current JSON schema version
     * @const {number}
     */
    const CURRENT_SCHEMA_VERSION = 1;

    /**
     * JSONLayoutEngine class
     * Manages JSON-driven layout creation and manipulation
     */
    class JSONLayoutEngine {
        constructor() {
            this.validateSchema = this.validateSchema.bind(this);
            this.renderLayout = this.renderLayout.bind(this);
            this.buildFromDOM = this.buildFromDOM.bind(this);
            this.updateLayoutFromJSON = this.updateLayoutFromJSON.bind(this);
        }

        /**
         * Validate a JSON layout configuration against the schema
         *
         * Checks for required fields, valid breakpoints, proper item structure,
         * and schema version compatibility.
         *
         * @param {Object} config - Layout configuration object
         * @param {number} config.version - Schema version (must be 1)
         * @param {string} config.layoutId - Unique identifier for the layout
         * @param {Object} config.breakpoints - Breakpoint definitions (xs, sm, md, lg, xl, xxl)
         * @param {Array<Object>} config.items - Array of layout item configurations
         * @param {Object} [config.wrapper] - Optional wrapper element configuration
         * @param {string} [config.wrapper.tag] - HTML tag for wrapper (default: 'div')
         * @param {Array<string>} [config.wrapper.classes] - CSS classes for wrapper
         * @param {string} [config.wrapper.renderMode] - Render mode: 'standard' (default) or 'direct' (skip slot-layout wrapper)
         * @param {string} [config.gap] - Optional gap size
         * @returns {Object} Validation result with { valid: boolean, errors: string[] }
         *
         * @example
         * const result = RSL.JSONLayout.validateSchema(config);
         * if (!result.valid) {
         *   console.error('Validation errors:', result.errors);
         * }
         */
        validateSchema(config) {
            const errors = [];

            if (!config || typeof config !== 'object') {
                errors.push('Configuration must be an object');
                return { valid: false, errors };
            }

            // Version check
            if (!config.version || config.version !== CURRENT_SCHEMA_VERSION) {
                errors.push(`Schema version must be ${CURRENT_SCHEMA_VERSION}`);
            }

            // LayoutId check
            if (!config.layoutId || typeof config.layoutId !== 'string') {
                errors.push('layoutId must be a non-empty string');
            }

            // Breakpoints check
            if (!config.breakpoints || typeof config.breakpoints !== 'object') {
                errors.push('breakpoints must be an object');
            } else {
                const validBreakpoints = ['xs', 'sm', 'md', 'lg', 'xl', 'xxl'];
                for (const bp in config.breakpoints) {
                    if (!validBreakpoints.includes(bp)) {
                        errors.push(`Invalid breakpoint: ${bp}`);
                    }
                    if (typeof config.breakpoints[bp] !== 'number' || config.breakpoints[bp] < 1) {
                        errors.push(`Breakpoint ${bp} must be a positive number`);
                    }
                }
            }

            // Items check
            if (!Array.isArray(config.items)) {
                errors.push('items must be an array');
            } else {
                config.items.forEach((item, index) => {
                    if (!item.id || typeof item.id !== 'string') {
                        errors.push(`Item ${index}: id is required and must be a string`);
                    }
                    if (item.classes && !Array.isArray(item.classes)) {
                        errors.push(`Item ${index}: classes must be an array`);
                    }
                    if (item.content && typeof item.content !== 'object') {
                        errors.push(`Item ${index}: content must be an object`);
                    }
                });
            }

            return {
                valid: errors.length === 0,
                errors
            };
        }

        /**
         * Render a layout from JSON configuration
         *
         * Creates a new layout or updates an existing one based on the provided
         * configuration. Handles wrapper elements, breakpoints, gaps, and item
         * creation. Automatically triggers RSL's layout calculation.
         *
         * @param {string|HTMLElement} container - Container selector or element
         * @param {Object} config - JSON layout configuration
         * @returns {HTMLElement} The created/updated layout element
         * @throws {Error} If configuration is invalid or container not found
         *
         * @example
         * const layoutEl = RSL.JSONLayout.renderLayout('#app', {
         *   version: 1,
         *   layoutId: "main-layout",
         *   breakpoints: { xs: 1, md: 2, lg: 3 },
         *   gap: "1rem",
         *   items: [...]
         * });
         */
        renderLayout(container, config) {
            // Check if this is a special component type
            if (config.componentType) {
                return this._renderComponent(container, config);
            }

            // Validate config
            const validation = this.validateSchema(config);
            if (!validation.valid) {
                console.error('Invalid layout configuration:', validation.errors);
                throw new Error('Invalid layout configuration: ' + validation.errors.join(', '));
            }

            // Get container element
            const containerEl = typeof container === 'string'
                ? document.querySelector(container)
                : container;

            if (!containerEl) {
                throw new Error('Container not found');
            }

            // Check if layout already exists
            let layoutEl = containerEl.querySelector(`#${config.layoutId}`);
            let wrapperEl = null;

            // Check for direct render mode (wrapper only, no slot-layout)
            const isDirectRender = config.wrapper && config.wrapper.renderMode === 'direct';

            if (!layoutEl) {
                // Create wrapper if specified in config
                if (config.wrapper) {
                    wrapperEl = document.createElement(config.wrapper.tag || 'div');

                    if (config.wrapper.id) {
                        wrapperEl.id = config.wrapper.id;
                    }

                    if (config.wrapper.classes && config.wrapper.classes.length > 0) {
                        wrapperEl.className = config.wrapper.classes.join(' ');
                    }

                    // Set wrapper data attributes
                    if (config.wrapper.data) {
                        Object.entries(config.wrapper.data).forEach(([key, value]) => {
                            wrapperEl.setAttribute(`data-${key}`, value);
                        });
                    }

                    if (isDirectRender) {
                        // Direct render mode: content goes directly in wrapper
                        wrapperEl.id = config.layoutId;
                        containerEl.appendChild(wrapperEl);
                        layoutEl = wrapperEl; // Use wrapper as the layout element
                    } else {
                        // Standard mode: Create slot-layout inside wrapper
                        layoutEl = document.createElement('div');
                        layoutEl.id = config.layoutId;
                        layoutEl.className = 'slot-layout';
                        wrapperEl.appendChild(layoutEl);
                        containerEl.appendChild(wrapperEl);
                    }
                } else {
                    // Create new layout without wrapper
                    layoutEl = document.createElement('div');
                    layoutEl.id = config.layoutId;
                    layoutEl.className = 'slot-layout';
                    containerEl.appendChild(layoutEl);
                }
            }

            // Set breakpoint attributes (only for non-direct render mode)
            if (!isDirectRender) {
                Object.entries(config.breakpoints).forEach(([bp, cols]) => {
                    layoutEl.setAttribute(`data-cols-${bp}`, cols);
                });

                // Set gap if provided
                if (config.gap) {
                    layoutEl.setAttribute('data-gap', config.gap);
                }

                // Calculate and set initial --dynamic-cols based on current viewport
                // This prevents the "squished" appearance before layout.js runs
                const initialCols = this._calculateInitialColumns(config.breakpoints);
                layoutEl.style.setProperty('--dynamic-cols', initialCols);

                // Mark as pending initialization (will be removed after RSL calculates layout)
                layoutEl.setAttribute('data-json-layout-pending', 'true');
            }

            // Clear existing items
            layoutEl.innerHTML = '';

            // Create items
            if (isDirectRender) {
                // Direct render: insert content directly without slot-item wrapper
                config.items.forEach(itemConfig => {
                    if (itemConfig.content && itemConfig.content.type === 'html') {
                        layoutEl.innerHTML = itemConfig.content.value;
                    } else {
                        const itemEl = this._createItemElement(itemConfig);
                        layoutEl.appendChild(itemEl);
                    }
                });
            } else {
                // Standard render: create slot-items
                config.items.forEach(itemConfig => {
                    const itemEl = this._createItemElement(itemConfig);
                    layoutEl.appendChild(itemEl);
                });
            }

            // Trigger RSL's layout calculation if available (only for slot-layout elements)
            if (!isDirectRender && window.RSL && window.RSL.recalculateLayout) {
                window.RSL.recalculateLayout(layoutEl);
            }

            // Remove pending initialization marker and show layout
            if (!isDirectRender) {
                layoutEl.removeAttribute('data-json-layout-pending');
            }

            // Auto-initialize RSL components after rendering
            // This ensures components like Select, Tooltip, etc. are properly initialized
            this._initializeComponents(containerEl);

            return layoutEl;
        }

        /**
         * Calculate initial column count based on viewport width and breakpoints
         *
         * Determines the appropriate number of columns for the current viewport
         * to prevent layout shift before RSL's layout.js calculates the final value.
         *
         * @private
         * @param {Object} breakpoints - Breakpoint configuration (xs, sm, md, lg, xl, xxl)
         * @returns {number} Number of columns for current viewport
         *
         * @example
         * // For config: { xs: 1, md: 2, lg: 3 }
         * // On mobile (320px): returns 1
         * // On tablet (768px): returns 2
         * // On desktop (1024px): returns 3
         */
        _calculateInitialColumns(breakpoints) {
            const width = window.innerWidth;
            let columns = breakpoints.xs || 1;

            // RSL breakpoints (matching layout.js):
            // XS: 0-479px, SM: 480-767px, MD: 768-992px, LG: 993-1200px, XL: 1201-1600px, XXL: 1601px+
            if (width >= 1601 && breakpoints.xxl) {
                columns = breakpoints.xxl;
            } else if (width >= 1201 && breakpoints.xl) {
                columns = breakpoints.xl;
            } else if (width >= 993 && breakpoints.lg) {
                columns = breakpoints.lg;
            } else if (width >= 768 && breakpoints.md) {
                columns = breakpoints.md;
            } else if (width >= 480 && breakpoints.sm) {
                columns = breakpoints.sm;
            }

            return columns;
        }

        /**
         * Initialize RSL components within a container
         *
         * Automatically calls init() methods for all available RSL components
         * after JSON layout rendering. This enables declarative component usage
         * through the JSON API without manual initialization.
         *
         * @private
         * @param {HTMLElement} container - Container element to scan for components
         *
         * @example
         * // Called automatically after renderLayout()
         * // Initializes: Select, Tooltip, Popover, Accordion, etc.
         */
        _initializeComponents(container) {
            // List of RSL components that support auto-initialization
            const components = [
                'Select',
                'Tooltip',
                'Popover',
                'Accordion',
                'Tabs',
                'Modal',
                'Toast',
                'Carousel',
                'OffCanvas',
                'Alerts',
                'Navbar',
                'Pagination',
                'Sidebar',
                'Cards',
                'Thumbnail',
                'Charts',
                'KPICards',
                'Gantt',
                'SmartTable',
                'Hero',
                'Announcements',
                'IconPicker',
                'Testimonial',
                'StarRating',
                'Timeline'
            ];

            components.forEach(function(componentName) {
                // Check if component exists and has init method
                if (window.RSL &&
                    window.RSL[componentName] &&
                    typeof window.RSL[componentName].init === 'function') {

                    // Call component's init method
                    // Most components scan for their data attributes automatically
                    window.RSL[componentName].init();
                }
            });
        }

        /**
         * Render special component types (navbar, etc.)
         *
         * @private
         * @param {string|HTMLElement} container - Container selector or element
         * @param {Object} config - Component configuration
         * @returns {HTMLElement} Created component element
         * @throws {Error} If container not found or component type unknown
         */
        _renderComponent(container, config) {
            const containerEl = typeof container === 'string'
                ? document.querySelector(container)
                : container;

            if (!containerEl) {
                throw new Error('Container not found');
            }

            // Handle different component types
            switch (config.componentType) {
                case 'navbar':
                    return this._renderNavbar(containerEl, config);
                default:
                    throw new Error(`Unknown component type: ${config.componentType}`);
            }
        }

        /**
         * Render RSL navbar from JSON configuration
         *
         * Creates a responsive navigation bar with brand, toggle button, and menu items.
         * Automatically initializes RSL navbar functionality if available.
         *
         * @private
         * @param {HTMLElement} containerEl - Container element
         * @param {Object} config - Navbar configuration
         * @param {string} [config.layoutId] - Navbar ID
         * @param {string} [config.ariaLabel] - Accessibility label
         * @param {Object} [config.brand] - Brand/logo configuration
         * @param {Array<Object>} [config.items] - Menu items
         * @returns {HTMLElement} Created navbar element
         */
        _renderNavbar(containerEl, config) {
            // Create nav element
            const nav = document.createElement('nav');
            nav.className = 'rsl-navbar';
            nav.id = config.layoutId || 'navbar-' + Date.now();

            if (config.ariaLabel) {
                nav.setAttribute('aria-label', config.ariaLabel);
            }

            // Add brand/logo if provided
            if (config.brand) {
                const brand = document.createElement('a');
                brand.className = 'rsl-navbar-brand';
                brand.href = config.brand.href || '#';

                if (config.brand.type === 'html') {
                    brand.innerHTML = config.brand.value;
                } else {
                    brand.textContent = config.brand.value || config.brand.text;
                }

                nav.appendChild(brand);
            }

            // Add mobile toggle button
            const toggle = document.createElement('button');
            toggle.className = 'rsl-navbar-toggle';
            toggle.setAttribute('aria-label', 'Toggle navigation menu');
            toggle.setAttribute('aria-expanded', 'false');
            toggle.innerHTML = '<span></span><span></span><span></span>';
            nav.appendChild(toggle);

            // Create menu
            const menu = document.createElement('ul');
            menu.className = 'rsl-navbar-menu';

            // Add menu items
            if (config.items && config.items.length > 0) {
                config.items.forEach(item => {
                    const li = document.createElement('li');
                    li.className = 'rsl-navbar-item';

                    const link = document.createElement('a');
                    link.className = 'rsl-navbar-link';
                    link.href = item.href || '#';

                    if (item.active) {
                        link.classList.add('active');
                    }

                    if (item.type === 'html') {
                        link.innerHTML = item.value;
                    } else {
                        link.textContent = item.text || item.value;
                    }

                    li.appendChild(link);
                    menu.appendChild(li);
                });
            }

            nav.appendChild(menu);

            // Clear container and append navbar
            containerEl.innerHTML = '';
            containerEl.appendChild(nav);

            // Initialize RSL navbar if the script is loaded
            if (window.RSL && window.RSL.initNavbar) {
                window.RSL.initNavbar();
            }

            return nav;
        }

        /**
         * Create an item element from configuration
         *
         * Constructs a slot-item element with classes, grid positioning,
         * content, data attributes, and visibility settings.
         *
         * @private
         * @param {Object} itemConfig - Item configuration object
         * @param {string} itemConfig.id - Item ID
         * @param {Array<string>} [itemConfig.classes] - Additional CSS classes
         * @param {Object} [itemConfig.grid] - Grid positioning (rowStart, rowEnd, columnStart, columnEnd)
         * @param {number} [itemConfig.order] - Flex order
         * @param {boolean} [itemConfig.visible] - Visibility flag (default: true)
         * @param {Object} [itemConfig.content] - Content configuration
         * @param {Object} [itemConfig.data] - Data attributes
         * @returns {HTMLElement} Created item element
         */
        _createItemElement(itemConfig) {
            const itemEl = document.createElement('div');

            // Set ID
            itemEl.id = itemConfig.id;

            // Set classes (always include slot-item)
            const classes = ['slot-item', ...(itemConfig.classes || [])];
            itemEl.className = classes.join(' ');

            // Set grid positioning via CSS custom properties
            if (itemConfig.grid) {
                if (itemConfig.grid.rowStart) {
                    itemEl.style.setProperty('--row-start', itemConfig.grid.rowStart);
                }
                if (itemConfig.grid.rowEnd) {
                    itemEl.style.setProperty('--row-end', itemConfig.grid.rowEnd);
                }
                if (itemConfig.grid.columnStart) {
                    itemEl.style.setProperty('--column-start', itemConfig.grid.columnStart);
                }
                if (itemConfig.grid.columnEnd) {
                    itemEl.style.setProperty('--column-end', itemConfig.grid.columnEnd);
                }
            }

            // Set order
            if (itemConfig.order !== undefined) {
                itemEl.style.order = itemConfig.order;
            }

            // Set visibility
            if (itemConfig.visible === false) {
                itemEl.classList.add('hidden');
            }

            // Set content
            if (itemConfig.content) {
                this._setItemContent(itemEl, itemConfig.content);
            }

            // Set data attributes
            if (itemConfig.data) {
                Object.entries(itemConfig.data).forEach(([key, value]) => {
                    itemEl.setAttribute(`data-${key}`, value);
                });
            }

            return itemEl;
        }

        /**
         * Set item content based on content configuration
         *
         * Supports multiple content types: HTML, text, template slots, and components.
         *
         * @private
         * @param {HTMLElement} itemEl - Item element to populate
         * @param {Object} contentConfig - Content configuration
         * @param {string} contentConfig.type - Content type: 'html', 'text', 'slot', or 'component'
         * @param {string} [contentConfig.value] - Content value for 'html' and 'text' types
         * @param {string} [contentConfig.selector] - Template selector for 'slot' type
         * @param {string} [contentConfig.component] - Component name for 'component' type
         * @param {Object} [contentConfig.props] - Component props for 'component' type
         */
        _setItemContent(itemEl, contentConfig) {
            switch (contentConfig.type) {
                case 'html':
                    itemEl.innerHTML = contentConfig.value || '';
                    break;

                case 'text':
                    itemEl.textContent = contentConfig.value || '';
                    break;

                case 'slot':
                    // Clone content from a template element
                    const template = document.querySelector(contentConfig.selector);
                    if (template) {
                        const clone = template.content
                            ? template.content.cloneNode(true)
                            : template.cloneNode(true);
                        itemEl.appendChild(clone);
                    } else {
                        console.warn(`Template not found: ${contentConfig.selector}`);
                    }
                    break;

                case 'component':
                    // Reference to a custom component (user's responsibility to render)
                    itemEl.setAttribute('data-component', contentConfig.component);
                    if (contentConfig.props) {
                        itemEl.setAttribute('data-props', JSON.stringify(contentConfig.props));
                    }
                    break;

                default:
                    console.warn(`Unknown content type: ${contentConfig.type}`);
            }
        }

        /**
         * Build JSON configuration from existing DOM layout
         *
         * Extracts layout configuration including wrapper, breakpoints, gap settings,
         * and all items with their properties. Useful for converting hand-authored
         * HTML into JSON format.
         *
         * @param {string|HTMLElement} container - Container with .slot-layout
         * @returns {Object} JSON layout configuration
         * @throws {Error} If container or layout not found
         *
         * @example
         * const config = RSL.JSONLayout.buildFromDOM('#main-container');
         * console.log(JSON.stringify(config, null, 2));
         */
        buildFromDOM(container) {
            const containerEl = typeof container === 'string'
                ? document.querySelector(container)
                : container;

            if (!containerEl) {
                throw new Error('Container not found');
            }

            const layoutEl = containerEl.querySelector('.slot-layout');
            if (!layoutEl) {
                throw new Error('No .slot-layout found in container');
            }

            // Build config object
            const config = {
                version: CURRENT_SCHEMA_VERSION,
                layoutId: layoutEl.id || 'layout-' + Date.now(),
                breakpoints: {},
                items: []
            };

            // Check if layout has a parent wrapper we should preserve
            const wrapper = layoutEl.parentElement;
            if (wrapper && wrapper !== containerEl && wrapper !== document.body) {
                // Store wrapper information
                config.wrapper = {
                    id: wrapper.id || null,
                    classes: Array.from(wrapper.classList),
                    tag: wrapper.tagName.toLowerCase()
                };

                // Store any data attributes from wrapper
                const wrapperDataAttrs = Array.from(wrapper.attributes)
                    .filter(attr => attr.name.startsWith('data-'))
                    .reduce((acc, attr) => {
                        acc[attr.name.replace('data-', '')] = attr.value;
                        return acc;
                    }, {});

                if (Object.keys(wrapperDataAttrs).length > 0) {
                    config.wrapper.data = wrapperDataAttrs;
                }
            }

            // Extract breakpoints
            const breakpoints = ['xs', 'sm', 'md', 'lg', 'xl', 'xxl'];
            breakpoints.forEach(bp => {
                const value = layoutEl.getAttribute(`data-cols-${bp}`);
                if (value) {
                    config.breakpoints[bp] = parseInt(value, 10);
                }
            });

            // Extract gap
            const gap = layoutEl.getAttribute('data-gap');
            if (gap) {
                config.gap = gap;
            }

            // Extract items
            const items = layoutEl.querySelectorAll(':scope > .slot-item, :scope > .nested-slot-item');
            items.forEach((itemEl, index) => {
                const itemConfig = {
                    id: itemEl.id || `item-${index}`,
                    classes: Array.from(itemEl.classList).filter(c => c !== 'slot-item'),
                    visible: !itemEl.classList.contains('hidden')
                };

                // Extract grid positioning
                const rowStart = itemEl.style.getPropertyValue('--row-start');
                const rowEnd = itemEl.style.getPropertyValue('--row-end');
                const columnStart = itemEl.style.getPropertyValue('--column-start');
                const columnEnd = itemEl.style.getPropertyValue('--column-end');

                if (rowStart || rowEnd || columnStart || columnEnd) {
                    itemConfig.grid = {};
                    if (rowStart) itemConfig.grid.rowStart = parseInt(rowStart, 10);
                    if (rowEnd) itemConfig.grid.rowEnd = parseInt(rowEnd, 10);
                    if (columnStart) itemConfig.grid.columnStart = parseInt(columnStart, 10);
                    if (columnEnd) itemConfig.grid.columnEnd = parseInt(columnEnd, 10);
                }

                // Extract order
                const order = itemEl.style.order;
                if (order && order !== 'auto') {
                    itemConfig.order = parseInt(order, 10);
                }

                // Extract data attributes
                const dataAttrs = Array.from(itemEl.attributes)
                    .filter(attr => attr.name.startsWith('data-'))
                    .reduce((acc, attr) => {
                        const key = attr.name.replace('data-', '');
                        if (key !== 'component' && key !== 'props') {
                            acc[key] = attr.value;
                        }
                        return acc;
                    }, {});

                if (Object.keys(dataAttrs).length > 0) {
                    itemConfig.data = dataAttrs;
                }

                // Extract content (simplified - just store inner HTML)
                if (itemEl.innerHTML.trim()) {
                    itemConfig.content = {
                        type: 'html',
                        value: itemEl.innerHTML
                    };
                }

                config.items.push(itemConfig);
            });

            return config;
        }

        /**
         * Update existing layout from JSON (diff-based)
         *
         * Performs efficient incremental updates by comparing current DOM state
         * with new configuration. Only adds, updates, or removes items as needed.
         * Preserves DOM elements when possible to maintain state.
         *
         * @param {string|HTMLElement} container - Container with layout
         * @param {Object} config - New JSON configuration
         * @returns {Object} Update statistics: { added: number, updated: number, removed: number }
         * @throws {Error} If configuration is invalid or container not found
         *
         * @example
         * const stats = RSL.JSONLayout.updateLayoutFromJSON('#app', newConfig);
         * console.log(`Added: ${stats.added}, Updated: ${stats.updated}, Removed: ${stats.removed}`);
         */
        updateLayoutFromJSON(container, config) {
            const validation = this.validateSchema(config);
            if (!validation.valid) {
                throw new Error('Invalid configuration: ' + validation.errors.join(', '));
            }

            const containerEl = typeof container === 'string'
                ? document.querySelector(container)
                : container;

            if (!containerEl) {
                throw new Error('Container not found');
            }

            let layoutEl = containerEl.querySelector(`#${config.layoutId}`);
            if (!layoutEl) {
                // Layout doesn't exist, just render it
                this.renderLayout(container, config);
                return { added: config.items.length, updated: 0, removed: 0 };
            }

            const stats = { added: 0, updated: 0, removed: 0 };

            // Update breakpoints
            Object.entries(config.breakpoints).forEach(([bp, cols]) => {
                layoutEl.setAttribute(`data-cols-${bp}`, cols);
            });

            // Update gap
            if (config.gap) {
                layoutEl.setAttribute('data-gap', config.gap);
            }

            // Get existing items
            const existingItems = new Map();
            layoutEl.querySelectorAll(':scope > .slot-item, :scope > .nested-slot-item').forEach(item => {
                existingItems.set(item.id, item);
            });

            // Track items from config
            const configItemIds = new Set(config.items.map(i => i.id));

            // Update or add items
            config.items.forEach((itemConfig, index) => {
                const existingItem = existingItems.get(itemConfig.id);

                if (existingItem) {
                    // Update existing item
                    this._updateItemElement(existingItem, itemConfig);
                    existingItems.delete(itemConfig.id);
                    stats.updated++;
                } else {
                    // Add new item
                    const newItem = this._createItemElement(itemConfig);
                    if (index < layoutEl.children.length) {
                        layoutEl.insertBefore(newItem, layoutEl.children[index]);
                    } else {
                        layoutEl.appendChild(newItem);
                    }
                    stats.added++;
                }
            });

            // Remove items not in config
            existingItems.forEach(item => {
                item.remove();
                stats.removed++;
            });

            // Trigger recalculation
            if (window.RSL && window.RSL.recalculateLayout) {
                window.RSL.recalculateLayout(layoutEl);
            }

            return stats;
        }

        /**
         * Update an existing item element from configuration
         *
         * @private
         * @param {HTMLElement} itemEl - Item element to update
         * @param {Object} itemConfig - New item configuration
         */
        _updateItemElement(itemEl, itemConfig) {
            // Update classes
            const classes = ['slot-item', ...(itemConfig.classes || [])];
            itemEl.className = classes.join(' ');

            // Update grid positioning
            if (itemConfig.grid) {
                ['rowStart', 'rowEnd', 'columnStart', 'columnEnd'].forEach(prop => {
                    if (itemConfig.grid[prop]) {
                        itemEl.style.setProperty(`--${prop.replace(/[A-Z]/g, m => '-' + m.toLowerCase())}`,
                                                itemConfig.grid[prop]);
                    }
                });
            }

            // Update order
            if (itemConfig.order !== undefined) {
                itemEl.style.order = itemConfig.order;
            } else {
                itemEl.style.order = '';
            }

            // Update visibility
            if (itemConfig.visible === false) {
                itemEl.classList.add('hidden');
            } else {
                itemEl.classList.remove('hidden');
            }

            // Update content if provided
            if (itemConfig.content) {
                itemEl.innerHTML = '';
                this._setItemContent(itemEl, itemConfig.content);
            }
        }

        /**
         * Export layout configuration as JSON string
         *
         * @param {Object} config - Layout configuration
         * @param {boolean} [pretty=true] - Whether to format JSON with indentation
         * @returns {string} JSON string representation
         *
         * @example
         * const jsonString = RSL.JSONLayout.exportJSON(config);
         * // Download or save the JSON string
         */
        exportJSON(config, pretty = true) {
            return pretty ? JSON.stringify(config, null, 2) : JSON.stringify(config);
        }

        /**
         * Import layout configuration from JSON string
         *
         * Parses JSON string and validates against schema.
         *
         * @param {string} jsonString - JSON string to parse
         * @returns {Object} Parsed and validated configuration
         * @throws {Error} If JSON is invalid or schema validation fails
         *
         * @example
         * try {
         *   const config = RSL.JSONLayout.importJSON(jsonString);
         *   RSL.JSONLayout.renderLayout('#app', config);
         * } catch (error) {
         *   console.error('Invalid JSON:', error);
         * }
         */
        importJSON(jsonString) {
            try {
                const config = JSON.parse(jsonString);
                const validation = this.validateSchema(config);

                if (!validation.valid) {
                    throw new Error('Invalid schema: ' + validation.errors.join(', '));
                }

                return config;
            } catch (error) {
                console.error('Failed to import JSON:', error);
                throw error;
            }
        }
    }

    // Initialize and expose global API
    window.RSL = window.RSL || {};
    window.RSL.JSONLayout = new JSONLayoutEngine();

    // Emit ready event
    window.dispatchEvent(new CustomEvent('rsl:jsonlayout:ready'));

})();
