import {useEffect, useMemo, useRef, useState} from "@wordpress/element";
import {marked} from "marked";
import TurndownService from 'turndown';
import Copilot from "../../button/copilot";
import Emoji from "../../button/emoji";

export default function BlockEditable({
                                          className,
                                          value,
                                          setValue,
                                          label,
                                          placeholder,
                                          validate,
                                          errorMessage,
                                          emoji,
                                          copilot = true,
                                          opened,
                                          disabled,
                                          notifications,
                                          blockeditableRef,
                                          onInteraction,
                                          extraActions
                                      }) {
    const turndown = useMemo(() => new TurndownService(), []);

    const [height, setHeight] = useState(48);
    const [isOpened, setIsOpened] = useState(opened);
    const contentRef = useRef(null);
    const prevValue = useRef(null);
    const savedRangeRef = useRef(null);
    const savedCursorOffsetRef = useRef(null);
    const isEmpty = value === undefined || value === null || value === '';
    const getRootElement = () => blockeditableRef?.current ?? contentRef.current?.closest('.lbaic-settings-blockeditable');

    useEffect(() => {
        updateHeight();

        const observer = new MutationObserver(updateHeight);

        if (contentRef.current) {
            observer.observe(contentRef.current, {
                childList: true,
                subtree: true,
                characterData: true,
            });
        }

        return () => observer.disconnect();
    }, []);

    useEffect(() => {
        const handleLinkClick = (e) => {
            // Find if the clicked element is an anchor tag or is within an anchor tag
            const anchor = e.target.closest('a');

            if (anchor && anchor.href) {
                e.preventDefault();
                window.open(anchor.href, '_blank', 'noopener,noreferrer');
            }
        };

        const currentRef = contentRef.current;
        if (currentRef) {
            currentRef.addEventListener('click', handleLinkClick);
        }

        return () => {
            if (currentRef) {
                currentRef.removeEventListener('click', handleLinkClick);
            }
        };
    }, []);

    useEffect(() => {
        // Fix the height when opening
        updateHeight();
    }, [opened]);

    useEffect(() => {
        if (!isOpened) {
            const rootElement = getRootElement();
            if (contentRef.current) {
                contentRef.current.blur();
            }
            const activeElement = document.activeElement;
            if (activeElement && rootElement?.contains(activeElement)) {
                activeElement.blur();
            }
        }
    }, [isOpened]);

    useEffect(() => {
        updateContent(value);
    }, [value]);

    /**
     * On open
     */
    const onOpen = () => {
        if (!contentRef.current) {
            return;
        }
        // Focus the element
        contentRef.current.focus();
        // Move the cursor to the end
        const range = document.createRange();
        range.selectNodeContents(contentRef.current);
        range.collapse(false);

        const selection = window.getSelection();
        selection.removeAllRanges();
        selection.addRange(range);

        // Fix the height when opening
        updateHeight();
    }

    /**
     * Toggle the block editable
     */
    const handleToggle = () => {
        if (disabled) {
            return;
        }

        // Call onInteraction callback if provided
        if (typeof onInteraction === 'function') {
            onInteraction();
        }

        setIsOpened(prev => {
            if (prev) {
                return false;
            }
            onOpen();
            return true;
        });
    }

    /**
     * Open the block editable
     */
    const handleOpen = () => {
        setIsOpened(true);

        onOpen();
    }

    /**
     * Update the content height
     */
    const updateHeight = () => {
        if (contentRef.current) {
            setHeight(contentRef.current.scrollHeight || 48);
        }
    }

    /**
     * Update the content
     *
     * @param {string} value Value
     */
    const updateContent = (value) => {
        if (contentRef.current && prevValue.current !== value) {
            // Don't update if user is actively editing (prevents overwriting while typing)
            const isFocused = document.activeElement === contentRef.current;

            if (!isFocused) {
                contentRef.current.innerHTML = marked.parse(value);
            }
            // Always update prevValue to prevent infinite loops
            prevValue.current = value;
        }
    }

    /**
     * Handle key down
     *
     * @param {Event} e Event
     */
    const handleKeyDown = (e) => {
        if (disabled) {
            return;
        }
        if (e.key === 'Enter' && !e.shiftKey) {
            e.preventDefault();
            // Add br instead of div/p tags
            document.execCommand('defaultParagraphSeparator', false, 'p');
            document.execCommand('insertParagraph', false);
        }
    }

    /**
     * Handle focus on contentEditable
     */
    const handleFocus = () => {
        // Call onInteraction callback if provided
        if (typeof onInteraction === 'function') {
            onInteraction();
        }
        handleOpen();
    }

    /**
     * Handle blur on contentEditable
     */
    const handleBlur = (e) => {
        // Save cursor position when component is open (before focus moves away)
        if (isOpened && contentRef.current) {
            saveCursorPosition();
        }
    }

    /**
     * Clean up empty content (remove empty paragraphs and br tags)
     *
     * @param {HTMLElement} element ContentEditable element
     * @returns {boolean} True if content was cleaned (was effectively empty)
     */
    const cleanupEmptyContent = (element) => {
        if (!element) {
            return false;
        }

        // Get text content without HTML tags
        const textContent = element.textContent || element.innerText || '';
        const trimmedText = textContent.trim();

        // Check if content is effectively empty
        if (!trimmedText || trimmedText.length === 0) {
            // Clear the element completely
            element.innerHTML = '';
            return true;
        }

        return false;
    }

    /**
     * Wrap root-level text nodes and inline elements in paragraph tags
     *
     * @param {HTMLElement} element ContentEditable element
     */
    const wrapRootLevelContent = (element) => {
        if (!element) {
            return;
        }

        // Block-level elements that don't need wrapping
        const blockElements = ['P', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'HR', 'UL', 'OL', 'LI', 'BLOCKQUOTE', 'PRE', 'TABLE', 'THEAD', 'TBODY', 'TR', 'TD', 'TH'];

        // Quick check: only process if there are direct text nodes or inline elements that need wrapping
        const needsWrapping = Array.from(element.childNodes).some(node => {
            if (node.nodeType === Node.TEXT_NODE) {
                return node.textContent.trim() !== '';
            }
            if (node.nodeType === Node.ELEMENT_NODE) {
                return !blockElements.includes(node.tagName);
            }
            return false;
        });

        if (!needsWrapping) {
            return;
        }

        // Save cursor position
        const selection = window.getSelection();
        const range = selection.rangeCount > 0 ? selection.getRangeAt(0) : null;
        let cursorOffset = range ? range.startOffset : 0;
        let cursorNode = range ? range.startContainer : null;

        // Wrap direct text nodes and inline elements
        let cursorRestored = false;
        Array.from(element.childNodes).forEach(node => {
            // Skip block elements
            if (node.nodeType === Node.ELEMENT_NODE && blockElements.includes(node.tagName)) {
                return;
            }

            // Wrap text nodes with content
            if (node.nodeType === Node.TEXT_NODE && node.textContent.trim() !== '') {
                const p = document.createElement('p');
                p.textContent = node.textContent;
                element.replaceChild(p, node);

                // Restore cursor if this was the node we were typing in (only once)
                if (!cursorRestored && node === cursorNode && range) {
                    const textNode = p.firstChild;
                    if (textNode && textNode.nodeType === Node.TEXT_NODE) {
                        const newRange = document.createRange();
                        newRange.setStart(textNode, Math.min(cursorOffset, textNode.textContent.length));
                        newRange.collapse(true);
                        selection.removeAllRanges();
                        selection.addRange(newRange);
                        cursorRestored = true;
                    }
                }
            }
            // Wrap inline elements (like <span>, <strong>, etc.)
            else if (node.nodeType === Node.ELEMENT_NODE && !blockElements.includes(node.tagName)) {
                const p = document.createElement('p');
                const nextSibling = node.nextSibling;

                // Check if cursor is inside this inline element
                const cursorInside = cursorNode && (node === cursorNode || node.contains(cursorNode));

                // appendChild automatically moves the node from its current position
                p.appendChild(node);
                // Insert the paragraph where the node was
                element.insertBefore(p, nextSibling);

                // Restore cursor if it was inside this inline element (only once)
                if (!cursorRestored && cursorInside && range) {
                    // Since the node was moved (not cloned), the cursorNode should still be the same object
                    // Check if it's now inside the paragraph we created
                    let targetNode = null;

                    if (cursorNode && cursorNode.nodeType === Node.TEXT_NODE && p.contains(cursorNode)) {
                        // The exact text node is inside the paragraph - use it directly
                        targetNode = cursorNode;
                    } else {
                        // Fallback: find first text node in the paragraph
                        const walker = document.createTreeWalker(p, NodeFilter.SHOW_TEXT, null);
                        targetNode = walker.nextNode();
                    }

                    if (targetNode) {
                        const newRange = document.createRange();
                        const maxOffset = targetNode.textContent ? targetNode.textContent.length : 0;
                        newRange.setStart(targetNode, Math.min(cursorOffset, maxOffset));
                        newRange.collapse(true);
                        selection.removeAllRanges();
                        selection.addRange(newRange);
                        cursorRestored = true;
                    }
                }
            }
        });
    }

    /**
     * Update value and validate
     *
     * @param {string} text Value
     */
    const updateValue = (text) => {
        if (disabled) {
            return;
        }
        // trim -> fixed the "\n" empty string issue
        let preparedText = text.trim() ? turndown.turndown(text) : '';

        // Remove unnecessary backslashes before underscores within variable patterns (e.g., {planets\_search} -> {planets_search})
        // This prevents Turndown from escaping underscores in variables which should remain as-is
        preparedText = preparedText.replace(/\{([^}]*?)\}/g, (match, varContent) => {
            // Remove backslashes before underscores within the variable content
            const cleanedContent = varContent.replace(/\\_/g, '_');
            return `{${cleanedContent}}`;
        });

        setValue(preparedText);
        // Update the previous value
        prevValue.current = preparedText;
        // Update the height
        updateHeight();
        // Validate
        if (typeof validate === 'function') {
            validate(preparedText);
        }
    }

    /**
     * Handle text generation
     *
     * @param {string} text Text
     */
    const handleTextGeneration = (text) => {
        if (disabled) {
            return;
        }
        const preparedText = text.trim();
        setValue(preparedText);
        // Update the previous value
        prevValue.current = preparedText;
        // Update content HTML
        if (contentRef.current) {
            contentRef.current.innerHTML = marked.parse(preparedText);
        }
        // Update the height
        updateHeight();
        // Validate
        if (typeof validate === 'function') {
            validate(preparedText);
        }
    }

    /**
     * Get character offset from the start of the contentEditable
     */
    const getCursorOffset = (range) => {
        if (!contentRef.current || !range) {
            return null;
        }

        try {
            // Verify range is within contentEditable
            if (!contentRef.current.contains(range.commonAncestorContainer)) {
                return null;
            }
            const preCaretRange = range.cloneRange();
            preCaretRange.selectNodeContents(contentRef.current);
            preCaretRange.setEnd(range.endContainer, range.endOffset);
            return preCaretRange.toString().length;
        } catch (e) {
            return null;
        }
    }

    /**
     * Set cursor position from character offset
     */
    const setCursorFromOffset = (offset) => {
        if (!contentRef.current || offset === null || offset < 0) {
            return null;
        }

        try {
            const range = document.createRange();
            const walker = document.createTreeWalker(
                contentRef.current,
                NodeFilter.SHOW_TEXT,
                null
            );

            let currentOffset = 0;
            let node;
            let lastNode = null;

            while (node = walker.nextNode()) {
                const nodeLength = node.textContent.length;
                if (currentOffset + nodeLength >= offset) {
                    range.setStart(node, offset - currentOffset);
                    range.setEnd(node, offset - currentOffset);
                    return range;
                }
                currentOffset += nodeLength;
                lastNode = node;
            }

            // If offset is beyond content, place at end
            if (lastNode) {
                range.setStart(lastNode, lastNode.textContent.length);
                range.setEnd(lastNode, lastNode.textContent.length);
            } else {
                range.selectNodeContents(contentRef.current);
                range.collapse(false);
            }
            return range;
        } catch (e) {
            return null;
        }
    }

    /**
     * Save the current cursor position
     */
    const saveCursorPosition = () => {
        if (!contentRef.current) {
            return;
        }

        const selection = window.getSelection();
        if (selection.rangeCount > 0) {
            const range = selection.getRangeAt(0);
            // Save both range and offset for redundancy
            savedRangeRef.current = range.cloneRange();
            savedCursorOffsetRef.current = getCursorOffset(range);
        } else {
            // Save position at the end if no selection
            const range = document.createRange();
            range.selectNodeContents(contentRef.current);
            range.collapse(false);
            savedRangeRef.current = range;
            savedCursorOffsetRef.current = getCursorOffset(range);
        }
    }

    /**
     * Restore the saved cursor position
     *
     * @returns {Range|null} Restored range or null
     */
    const restoreCursorPosition = () => {
        if (!contentRef.current) {
            return null;
        }

        // First try to restore using saved range
        if (savedRangeRef.current) {
            try {
                const range = savedRangeRef.current;
                const startContainer = range.startContainer;
                const endContainer = range.endContainer;

                // Verify nodes are still connected to the DOM
                const isStartValid = startContainer === contentRef.current ||
                    contentRef.current.contains(startContainer);
                const isEndValid = endContainer === contentRef.current ||
                    contentRef.current.contains(endContainer);

                if (isStartValid && isEndValid) {
                    const selection = window.getSelection();
                    selection.removeAllRanges();
                    selection.addRange(range);
                    return range;
                }
            } catch (e) {
                // Range restoration failed, try offset method
            }
        }

        // Fallback to offset method if range method failed
        if (savedCursorOffsetRef.current !== null && savedCursorOffsetRef.current !== undefined) {
            const range = setCursorFromOffset(savedCursorOffsetRef.current);
            if (range) {
                const selection = window.getSelection();
                selection.removeAllRanges();
                selection.addRange(range);
                return range;
            }
        }

        return null;
    }

    /**
     * Ensure cursor is inside a paragraph tag, wrap if needed
     *
     * @param {Range} range Current cursor range
     * @returns {Range} Updated range with cursor in paragraph
     */
    const ensureParagraphWrapper = (range) => {
        if (!range || !contentRef.current) {
            return range;
        }

        const blockElements = ['P', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'HR', 'UL', 'OL', 'LI', 'BLOCKQUOTE', 'PRE', 'TABLE', 'THEAD', 'TBODY', 'TR', 'TD', 'TH'];

        // Find the current container
        let container = range.commonAncestorContainer;
        if (container.nodeType === Node.TEXT_NODE) {
            container = container.parentElement;
        }

        // Walk up to find if we're inside a block element
        let currentElement = container;
        while (currentElement && currentElement !== contentRef.current) {
            if (currentElement.nodeType === Node.ELEMENT_NODE && blockElements.includes(currentElement.tagName)) {
                // Already in a block element, return original range
                return range;
            }
            currentElement = currentElement.parentElement;
        }

        // We're at root level or in an inline element - need to wrap in paragraph
        // Find the root-level node that contains the cursor
        let rootNode = container;
        while (rootNode && rootNode.parentElement !== contentRef.current) {
            rootNode = rootNode.parentElement;
        }

        // Handle text node at root level
        if (rootNode && rootNode.nodeType === Node.TEXT_NODE) {
            // Text node is direct child of contentEditable - wrap it in paragraph
            const p = document.createElement('p');
            const nextSibling = rootNode.nextSibling;

            // Save cursor offset before DOM manipulation
            const savedOffset = range.startContainer === rootNode ? range.startOffset : 0;

            // Move text content to paragraph
            p.textContent = rootNode.textContent;
            contentRef.current.replaceChild(p, rootNode);

            // Update range to point inside the paragraph
            const selection = window.getSelection();
            const newRange = document.createRange();
            const textNode = p.firstChild;
            if (textNode && textNode.nodeType === Node.TEXT_NODE) {
                // Preserve cursor offset if possible
                const offset = Math.min(savedOffset, textNode.textContent.length);
                newRange.setStart(textNode, offset);
            } else {
                newRange.setStart(p, 0);
            }
            newRange.collapse(true);
            selection.removeAllRanges();
            selection.addRange(newRange);

            return newRange;
        }

        // If we're at root level (container is contentEditable or rootNode is null), create paragraph
        if (container === contentRef.current || !rootNode) {
            // Create a new paragraph at the cursor position
            const p = document.createElement('p');
            const selection = window.getSelection();

            // Insert paragraph at cursor position
            range.deleteContents();
            range.insertNode(p);

            // Move cursor inside the new paragraph
            const newRange = document.createRange();
            newRange.setStart(p, 0);
            newRange.collapse(true);
            selection.removeAllRanges();
            selection.addRange(newRange);

            return newRange;
        }

        // We're in an inline element at root level - wrap it
        if (rootNode && rootNode.nodeType === Node.ELEMENT_NODE && !blockElements.includes(rootNode.tagName)) {
            const p = document.createElement('p');
            const nextSibling = rootNode.nextSibling;

            // Move the inline element into paragraph
            p.appendChild(rootNode);
            contentRef.current.insertBefore(p, nextSibling);

            // Update range to point to the same position (which is now inside the paragraph)
            const selection = window.getSelection();
            const newRange = document.createRange();

            // Try to find the text node where cursor was
            if (range.startContainer.nodeType === Node.TEXT_NODE && p.contains(range.startContainer)) {
                newRange.setStart(range.startContainer, range.startOffset);
                newRange.collapse(true);
            } else {
                // Fallback: find first text node in paragraph
                const walker = document.createTreeWalker(p, NodeFilter.SHOW_TEXT, null);
                const textNode = walker.nextNode();
                if (textNode) {
                    newRange.setStart(textNode, 0);
                    newRange.collapse(true);
                } else {
                    newRange.setStart(p, 0);
                    newRange.collapse(true);
                }
            }

            selection.removeAllRanges();
            selection.addRange(newRange);
            return newRange;
        }

        return range;
    }

    /**
     * Handle emoji insertion
     *
     * @param {object} emojiData Emoji data object with emoji property
     */
    const handleEmojiInsert = (emojiData) => {
        if (disabled || !contentRef.current) {
            return;
        }

        // Ensure editor is opened (don't call onOpen which moves cursor to end)
        if (!isOpened) {
            setIsOpened(true);
        }

        contentRef.current.focus();

        // Restore saved cursor position immediately (before browser can change it)
        let range = restoreCursorPosition();

        // If restoration failed, try current selection
        if (!range) {
            const selection = window.getSelection();
            if (selection.rangeCount > 0) {
                range = selection.getRangeAt(0);
                // Validate range is within our contentEditable
                if (!range.commonAncestorContainer || !contentRef.current.contains(range.commonAncestorContainer)) {
                    range = null;
                }
            }
        }

        // Fallback to end if no valid range found
        if (!range) {
            const newRange = document.createRange();
            newRange.selectNodeContents(contentRef.current);
            newRange.collapse(false);
            range = newRange;
        }

        // Ensure cursor is inside a paragraph tag
        range = ensureParagraphWrapper(range);

        // Insert emoji at the determined cursor position
        range.deleteContents();
        const textNode = document.createTextNode(emojiData.emoji);
        range.insertNode(textNode);

        // Move cursor after the inserted emoji
        range.setStartAfter(textNode);
        range.collapse(true);
        const selection = window.getSelection();
        selection.removeAllRanges();
        selection.addRange(range);

        // Update value from the updated HTML
        updateValue(contentRef.current.innerHTML);

        // Clear saved range and offset after use
        savedRangeRef.current = null;
        savedCursorOffsetRef.current = null;
    }

    /**
     * Handle variable insertion
     * Inserts variable at cursor position, preserving whitespace
     *
     * @param {string} variable Variable text to insert
     */
    const handleVariableInsert = (variable) => {
        if (disabled || !contentRef.current || !variable) {
            return;
        }

        // Ensure editor is opened (don't call onOpen which moves cursor to end)
        if (!isOpened) {
            setIsOpened(true);
        }

        contentRef.current.focus();

        // Restore saved cursor position immediately (before browser can change it)
        let range = restoreCursorPosition();

        // If restoration failed, try current selection
        if (!range) {
            const selection = window.getSelection();
            if (selection.rangeCount > 0) {
                range = selection.getRangeAt(0);
                // Validate range is within our contentEditable
                if (!range.commonAncestorContainer || !contentRef.current.contains(range.commonAncestorContainer)) {
                    range = null;
                }
            }
        }

        // Fallback to end if no valid range found
        if (!range) {
            const newRange = document.createRange();
            newRange.selectNodeContents(contentRef.current);
            newRange.collapse(false);
            range = newRange;
        }

        // Ensure cursor is inside a paragraph tag
        range = ensureParagraphWrapper(range);

        // Insert variable at the determined cursor position
        range.deleteContents();
        const textNode = document.createTextNode(variable);
        range.insertNode(textNode);

        // Move cursor after the inserted variable
        range.setStartAfter(textNode);
        range.collapse(true);
        const selection = window.getSelection();
        selection.removeAllRanges();
        selection.addRange(range);

        // Update value from the updated HTML (preserves whitespace)
        updateValue(contentRef.current.innerHTML);

        // Clear saved range and offset after use
        savedRangeRef.current = null;
        savedCursorOffsetRef.current = null;
    }

    return <>
        {extraActions?.length > 0 && (
            <div className='lbaic-settings-extra-actions'>
                {extraActions.map((item, i) => {
                    const CurrentAction = item.component;
                    // Use disabled from extraAction props if provided, otherwise use BlockEditable's disabled
                    const actionDisabled = item.props?.disabled !== undefined ? item.props.disabled : disabled;
                    // Wrap chosen callback to pass insertVariable as second parameter
                    const originalChosen = item.props?.chosen;
                    const wrappedChosen = originalChosen ? (variable) => {
                        originalChosen(variable, handleVariableInsert);
                    } : undefined;
                    return <CurrentAction
                        key={i}
                        {...item.props}
                        chosen={wrappedChosen}
                        contentEditableRef={contentRef}
                        insertVariable={handleVariableInsert}
                        disabled={actionDisabled}
                    />;
                })}
            </div>
        )}
        <label
            className='lbaic-settings-blockeditable-title-in'
            onClick={handleToggle}
        >{label}</label>
        <div
            ref={blockeditableRef}
            className={`lbaic-settings-blockeditable${className ? ' ' + className : ''}${isOpened ? ' opened' : ''}${disabled ? ' lbaic-settings-blockeditable-disabled' : ''}${errorMessage ? ' lbaic-settings-blockeditable-error' : ''}`}
            style={{'--lbaic-settings-blockeditable-content-height': `${height}px`}}
        >
            <div className='lbaic-settings-blockeditable-header'>
                <button type='button'
                        className='lbaic-settings-blockeditable-title lbaic-settings-button-reset'
                        onClick={handleToggle}
                        tabIndex='-1'>
                    <span className='lbaic-settings-blockeditable-preview'>{value}</span>
                </button>
                <div className='lbaic-settings-blockeditable-header-actions'>
                    {emoji &&
                        <div className='lbaic-settings-blockeditable-header-actions-in'>
                            <Emoji
                                chosen={handleEmojiInsert}
                                inputRef={contentRef}
                                disabled={disabled}
                            />
                        </div>}
                    {copilot &&
                        <div className='lbaic-settings-blockeditable-header-actions-in'>
                            <Copilot
                                text={value}
                                generated={handleTextGeneration}
                                disabled={disabled}
                                notifications={notifications}
                            />
                        </div>}
                    <div
                        className='lbaic-settings-blockeditable-header-actions-in lbaic-settings-blockeditable-header-actions-arrow'>
                        <button type='button'
                                onClick={handleToggle}
                                className={`lbaic-settings-button-reset lbaic-settings-blockeditable-header-actions-item${disabled ? ' lbaic-settings-button-disabled' : ''}`}
                                tabIndex='-1'>
                            <svg className='lbaic-settings-blockeditable-header-actions-i'
                                 xmlns='http://www.w3.org/2000/svg'
                                 fill='none' viewBox='0 0 24 24'>
                                <use href='#lbaic-settings-arrow'/>
                            </svg>
                        </button>
                    </div>
                </div>
            </div>
            <div className='lbaic-settings-blockeditable-body'>
                <div
                    ref={contentRef}
                    className={`lbaic-settings-blockeditable-body-in${isEmpty ? ' empty' : ''}`}
                    onInput={e => {
                        // Clean up empty content first
                        const wasCleaned = cleanupEmptyContent(e.target);
                        // Wrap root-level text nodes in paragraph tags (skip if content was cleaned)
                        if (!wasCleaned) {
                            wrapRootLevelContent(e.target);
                        }
                        // Update value with cleaned content
                        updateValue(e.target.innerHTML);
                    }}
                    onKeyDown={handleKeyDown}
                    onFocus={handleFocus}
                    onBlur={handleBlur}
                    contentEditable={!disabled}
                    data-placeholder={placeholder}
                    tabIndex='0'
                />
            </div>
        </div>
        {errorMessage &&
            <div className='lbaic-settings-blockeditable-error-message'>
                <p className='lbaic-settings-blockeditable-error-message-in'>{errorMessage}</p>
            </div>}
    </>
}