import clsx from '../../../utils/clsx';
import {
    createContext,
    useContext,
    useState,
    useEffect,
    useRef,
} from '@wordpress/element';
import { Icon, Text } from '../../atoms';
import { InlineStack } from '../InlineStack';

const DropdownContext = createContext(undefined);

const useDropdownContext = () => {
    const context = useContext(DropdownContext);

    if (!context) {
        throw new Error(
            'useDropdownContext must be used within a Dropdown component',
        );
    }

    return context;
};

const Dropdown = ({ children, style, className = '', outSideClick = true }) => {
    const [open, setOpen] = useState(false);
    const wrapperRef = useRef(null);

    useEffect(() => {
        if (!outSideClick) return;
        const handleClickOutside = (event) => {
            if (
                wrapperRef.current &&
                !wrapperRef.current.contains(event.target)
            ) {
                setOpen(false);
            }
        };

        document.addEventListener('mousedown', handleClickOutside);
        return () =>
            document.removeEventListener('mousedown', handleClickOutside);
    }, [outSideClick]);

    return (
        <DropdownContext.Provider value={{ open, setOpen }}>
            <div
                style={style}
                className={clsx('rbfb-dropdown', className)}
                ref={wrapperRef}
            >
                {children}
            </div>
        </DropdownContext.Provider>
    );
};

const Trigger = ({
    children,
    openStatus,
    style,
    className = '',
    disabled = false,
}) => {
    const { open, setOpen } = useDropdownContext();

    useEffect(() => {
        if (openStatus !== undefined) {
            setOpen(openStatus);
        }
    }, [openStatus]);

    return (
        <div
            style={style}
            className={clsx('rbfb-dropdown__trigger', className)}
            onClick={(e) => {
                e.stopPropagation();
                if (disabled) return;
                setOpen(!open);
            }}
        >
            {typeof children === 'function'
                ? children({ open, setOpen })
                : children}
        </div>
    );
};

const TriggerArrow = ({ style, arrowColor = 'black', arrowSize = 'lg' }) => {
    const { open } = useDropdownContext();

    return (
        <div
            style={style}
            className={clsx('rbfb-dropdown__trigger-arrow', {
                'rbfb-dropdown__trigger-arrow--active': open,
            })}
        >
            <Icon
                name="keyboard_arrow_down"
                color={arrowColor}
                fontSize={arrowSize}
                fontWeight="semibold"
            />
        </div>
    );
};

const Content = ({
    style,
    className = '',
    rounded = 'md',
    border = false,
    borderColor = 'primary-light',
    borderStyle = 'solid',
    shadow = true,
    fullWidth,
    children,
    position,
}) => {
    const { open, setOpen } = useDropdownContext();
    const contentRef = useRef(null);

    useEffect(() => {
        if (!open || !contentRef.current) return;

        if (position) return;

        const content = contentRef.current;
        const trigger = content.parentElement?.querySelector(
            '.rbfb-dropdown__trigger',
        );
        if (!trigger) return;

        const triggerRect = trigger.getBoundingClientRect();
        const contentRect = content.getBoundingClientRect();

        content.style.left = '0';
        content.style.right = 'auto';
        content.style.top = 'calc(100% + 5px)';
        content.style.bottom = 'auto';

        if (triggerRect.right + contentRect.width > window.innerWidth) {
            content.style.left = 'auto';
            content.style.right = '0';
        }

        if (triggerRect.bottom + contentRect.height > window.innerHeight) {
            content.style.top = 'auto';
            content.style.bottom = 'calc(100% + 5px)';
        }
    }, [open]);

    return (
        <div
            ref={contentRef}
            style={{ ...style, ...(position || {}) }}
            className={clsx(
                'rbfb-dropdown__content',
                `rounded-${rounded}`,
                border && `border border-${borderColor} border-${borderStyle}`,
                className,
                {
                    'rbfb-dropdown__content--active': open,
                    'rbfb-dropdown__content--full': fullWidth,
                    'rbfb-dropdown__content--shadow': shadow,
                },
            )}
        >
            {typeof children === 'function'
                ? children({ open, setOpen })
                : children}
        </div>
    );
};

const MenuLabel = ({ className = '', children, tag = 'p' }) => {
    const { open, setOpen } = useDropdownContext();

    return (
        <Text as={tag} className={clsx('rbfb-dropdown__menu-label', className)}>
            {typeof children === 'function'
                ? children({ open, setOpen })
                : children}
        </Text>
    );
};

const MenuSeparator = () => {
    return <div className="rbfb-dropdown__menu-separator"></div>;
};

const MenuItem = ({
    children,
    onClick,
    isActive,
    activeIcon = false,
    iconPosition = 'left',
    activeBg = false,
    style,
    className = '',
}) => {
    return (
        <div
            style={style}
            className={clsx('rbfb-dropdown__menu-item', className, {
                'rbfb-dropdown__menu-item--active': isActive,
                'rbfb-dropdown__menu-item--activeBg': activeBg,
            })}
            onClick={(e) => {
                e.stopPropagation();
                onClick && onClick();
            }}
        >
            {activeIcon ? (
                <InlineStack
                    gap={5}
                    align={iconPosition === 'left' ? 'start' : 'between'}
                    direction={iconPosition === 'left' ? 'row' : 'row-reverse'}
                    wrap={false}
                    className="w-full"
                >
                    <div className="rbfb-dropdown__menu-item-icon">
                        {isActive && <Icon name="check" fontSize="md" />}
                    </div>
                    {children}
                </InlineStack>
            ) : (
                children
            )}
        </div>
    );
};

Dropdown.Trigger = Trigger;
Dropdown.TriggerArrow = TriggerArrow;
Dropdown.Content = Content;
Dropdown.MenuLabel = MenuLabel;
Dropdown.MenuSeparator = MenuSeparator;
Dropdown.MenuItem = MenuItem;

export default Dropdown;
