import {createPortal, useRef, useState} from "@wordpress/element";
import {__} from "@wordpress/i18n";
import useClickOutside from "../../../../components/hooks/use-click-outside";

/**
 * Insert variable button
 *
 * @param {string} label The button label
 * @param {object} variables Variables to insert
 * @param {string} className Class name
 * @param {function} chosen Chosen variable callback
 * @param {object} inputRef Input ref
 * @param {boolean} disabled Disabled state
 * @return {JSX.Element|null}
 * @constructor
 */
export default function InsertVariable({variables, className, chosen, inputRef, disabled}) {
    const [opened, setOpened] = useState(false);
    const [position, setPosition] = useState({
        top: 0,
        right: 0,
        bottom: 'unset',
    });

    // Elements refs
    const menuRef = useRef(null);
    const openerRef = useRef(null);
    const metaBoxRef = useRef(document.getElementById('chatbot-meta-box'));
    const fieldMenuRef = useRef(document.getElementById('lbaic-settings-field-menu'));

    const inCloseTimeout = useRef(null);

    useClickOutside([menuRef, openerRef], () => setOpened(false));

    const toggleMenu = (e) => {
        if (disabled || !openerRef.current) {
            return;
        }
        if (opened) {
            setOpened(false);
            return;
        }

        const rect = openerRef.current.getBoundingClientRect();
        const metaBoxRect = metaBoxRef.current ? metaBoxRef.current.getBoundingClientRect() : null;
        const topMenuHeight = document.getElementById('wpadminbar').offsetHeight;

        // Menu position
        let top = (rect.top - (metaBoxRect ? -2 : (topMenuHeight ? topMenuHeight - 36 : 0)) - (metaBoxRect?.top || 0)) + 3;
        // Calculate the right position more precisely - use document width to avoid scrollbar issues
        let right = metaBoxRect ? (metaBoxRect.right - rect.right) : (document.documentElement.clientWidth - rect.right);
        let bottom = 'unset';

        // Check if the menu will overflow the bottom of the viewport
        const maxMenuHeight = 300; // Max menu height
        const viewportHeight = window.innerHeight;
        const spaceBelow = viewportHeight - rect.bottom;

        if (spaceBelow < maxMenuHeight) {
            // Not enough space below, position from bottom instead
            top = 'unset';
            bottom = 0;
        }

        setPosition({
            top: typeof top === 'number' ? top + 'px' : top,
            right: typeof right === 'number' ? right + 'px' : right,
            bottom: typeof bottom === 'number' ? bottom + 'px' : bottom,
        });

        // Open menu
        setOpened(true);
    };

    /**
     * Keep the menu opened if intend to close it within 400 ms
     */
    const inMouseEnter = () => {
        if (inCloseTimeout.current) {
            clearTimeout(inCloseTimeout.current);
            inCloseTimeout.current = null;
        }
    }

    /**
     * Close menu on mouse leave after 400 ms
     */
    const inMouseLeave = () => {
        inCloseTimeout.current = setTimeout(() => {
            setOpened(false);
        }, 400);
    }

    /**
     * Handle variable click
     *
     * @param {string} variable Variable name
     */
    const handleVariableClick = (variable) => {
        if (disabled) {
            return;
        }
        chosen(variable);
        setOpened(false);
        // Focus the input
        if (inputRef?.current) {
            inputRef.current.focus();
        }
    };

    return <>
        <div className={`lbaic-settings-insert-variable${className ? ' ' + className : ''}`}>
            <button
                ref={openerRef}
                type="button"
                className={`lbaic-settings-button lbaic-settings-button-center lbaic-settings-button-h-32 lbaic-settings-button-secondary-colored${disabled ? ' lbaic-settings-button-disabled' : ''}`}
                onClick={toggleMenu}
                title={__("+ Insert variable", 'limb-chatbot')}
            >
                <span className='lbaic-settings-button-label'>{__("+ Insert variable", 'limb-chatbot')}</span>
            </button>
        </div>
        {opened && createPortal(
            <div
                ref={menuRef}
                className='lbaic-settings-insert-variable-dropdown active'
                style={{
                    '--lbaic-settings-iv-menu-top': position.top,
                    '--lbaic-settings-iv-menu-right': position.right,
                    '--lbaic-settings-iv-menu-bottom': position.bottom,
                }}
                onMouseEnter={inMouseEnter}
                onMouseLeave={inMouseLeave}
            >
                <div className="lbaic-settings-insert-variable-dropdown-content">
                    {variables && Object.keys(variables).map((groupKey) => {
                        const group = variables[groupKey];
                        if (!group) {
                            return null;
                        }

                        // Handle groups structure (for Previous Handlers with nested groups)
                        if (group.groups && Array.isArray(group.groups)) {
                            return (
                                <div key={groupKey} className="lbaic-settings-insert-variable-group">
                                    <div className="lbaic-settings-insert-variable-group-header">
                                        <p className="lbaic-settings-insert-variable-group-label">{group.label}</p>
                                    </div>
                                    {group.groups.map((subGroup, subIndex) => (
                                        <div key={subIndex} className="lbaic-settings-insert-variable-subgroup">
                                            {subGroup.items && subGroup.items.length > 0 && (
                                                <div className="lbaic-settings-insert-variable-group-items">
                                                    {subGroup.items.map((item, itemIndex) => (
                                                        <button
                                                            key={itemIndex}
                                                            type="button"
                                                            className="lbaic-settings-insert-variable-item"
                                                            onClick={() => handleVariableClick(item.value)}
                                                        >
                                                            <div
                                                                className="lbaic-settings-insert-variable-item-content">
                                                                <p className="lbaic-settings-insert-variable-item-label">{item.label}</p>
                                                                <p className="lbaic-settings-insert-variable-item-value">{item.value}</p>
                                                            </div>
                                                            <svg
                                                                className="lbaic-settings-insert-variable-item-icon"
                                                                aria-hidden="true"
                                                            >
                                                                <use href="#lbaic-settings-plus-stroke"/>
                                                            </svg>
                                                        </button>
                                                    ))}
                                                </div>
                                            )}
                                        </div>
                                    ))}
                                </div>
                            );
                        }

                        // Handle simple items structure (for Parameters)
                        if (group.items && Array.isArray(group.items) && group.items.length > 0) {
                            return (
                                <div key={groupKey} className="lbaic-settings-insert-variable-group">
                                    <div className="lbaic-settings-insert-variable-group-header">
                                        <p className="lbaic-settings-insert-variable-group-label">{group.label}</p>
                                    </div>
                                    <div className="lbaic-settings-insert-variable-group-items">
                                        {group.items.map((item, index) => (
                                            <button
                                                key={index}
                                                type="button"
                                                className="lbaic-settings-insert-variable-item"
                                                onClick={() => handleVariableClick(item.value)}
                                            >
                                                <div className="lbaic-settings-insert-variable-item-content">
                                                    <p className="lbaic-settings-insert-variable-item-label">{item.label}</p>
                                                    <p className="lbaic-settings-insert-variable-item-value">{item.value}</p>
                                                </div>
                                                <svg
                                                    className="lbaic-settings-insert-variable-item-icon"
                                                    aria-hidden="true"
                                                >
                                                    <use href="#lbaic-settings-plus-stroke"/>
                                                </svg>
                                            </button>
                                        ))}
                                    </div>
                                </div>
                            );
                        }

                        return null;
                    })}
                </div>
            </div>
            , fieldMenuRef.current || document.body)}
    </>
}