import {useState, useRef, useEffect, useCallback} from "@wordpress/element";
import {ChromePicker} from 'react-color';

const DEFAULT_COLOR = '#000000';
const PICKER_HEIGHT = 221;
const PADDING = 8;

export default function ColorPicker({value, pickerOpened, colorPicked, positionAbove = false}) {
    const [displayColorPicker, setDisplayColorPicker] = useState(false);
    const [color, setColor] = useState(DEFAULT_COLOR);
    const [pickerPosition, setPickerPosition] = useState({top: 0, left: 0});
    const pickerRef = useRef(null);
    const buttonRef = useRef(null);

    /**
     * Get display color for button style
     */
    const getDisplayColor = () => {
        if (typeof color === 'string') {
            return color;
        }
        if (color && color.rgb) {
            return color.rgb.a < 1
                ? `rgba(${color.rgb.r}, ${color.rgb.g}, ${color.rgb.b}, ${color.rgb.a})`
                : color.hex;
        }
        return value;
    }

    /**
     * Calculate picker position based on button and container positions
     */
    const calculatePickerPosition = useCallback(() => {
        if (!buttonRef.current) {
            return null;
        }

        const rect = buttonRef.current.getBoundingClientRect();

        // If positionAbove is true (onboarding), check if picker would go off-screen at bottom
        if (positionAbove) {
            // Check if picker would go off the bottom of the screen
            const bottomPosition = rect.bottom + PICKER_HEIGHT + PADDING;
            const wouldGoOffBottom = bottomPosition > window.innerHeight;

            // If picker would go off bottom, try to position above
            if (wouldGoOffBottom) {
                // Find parent container with class lbaic-settings-cb-a-row-in
                let containerElement = buttonRef.current.closest('.lbaic-settings-cb-a-row-in');

                // If not found, try to find it by traversing up the DOM tree
                if (!containerElement) {
                    let parent = buttonRef.current.parentElement;
                    while (parent && !containerElement) {
                        if (parent.classList && parent.classList.contains('lbaic-settings-cb-a-row-in')) {
                            containerElement = parent;
                            break;
                        }
                        parent = parent.parentElement;
                    }
                }

                // If still not found, use button's parent
                if (!containerElement) {
                    containerElement = buttonRef.current.parentElement;
                }

                if (!containerElement) {
                    // Fallback: check if there's space above button
                    const topPosition = rect.top - PICKER_HEIGHT - PADDING;
                    if (topPosition >= PADDING) {
                        // Enough space above, position above button
                        return {
                            top: topPosition,
                            left: rect.left
                        };
                    } else {
                        // Not enough space above, position below anyway
                        return {
                            top: rect.bottom + PADDING,
                            left: rect.left
                        };
                    }
                }

                // Get container position
                const containerRect = containerElement.getBoundingClientRect();

                // Calculate position above container
                const topPosition = containerRect.top - PICKER_HEIGHT - PADDING;

                // Check if there's enough space above
                if (topPosition >= PADDING) {
                    // Position picker above the container
                    return {
                        top: topPosition,
                        left: containerRect.left // Align with left edge of container
                    };
                } else {
                    // Not enough space above, position below anyway
                    return {
                        top: rect.bottom + PADDING,
                        left: rect.left
                    };
                }
            } else {
                // Picker fits below, use default behavior
                return {
                    top: rect.bottom + PADDING,
                    left: rect.left
                };
            }
        } else {
            // Default behavior: position below the button
            return {
                top: rect.bottom + PADDING,
                left: rect.left
            };
        }
    }, [positionAbove]);

    /**
     * Open picker
     */
    const openPicker = () => {
        pickerOpened();

        const position = calculatePickerPosition();
        if (position) {
            setPickerPosition(position);
        }

        setDisplayColorPicker(true);
    }

    /**
     * Handle window resize to recalculate picker position
     */
    useEffect(() => {
        if (!displayColorPicker) {
            return;
        }

        const handleResize = () => {
            const position = calculatePickerPosition();
            if (position) {
                setPickerPosition(position);
            }
        };

        // Use debounce to avoid too many recalculations
        let timeoutId;
        const debouncedHandleResize = () => {
            clearTimeout(timeoutId);
            timeoutId = setTimeout(handleResize, 100);
        };

        window.addEventListener('resize', debouncedHandleResize);

        return () => {
            window.removeEventListener('resize', debouncedHandleResize);
            clearTimeout(timeoutId);
        };
    }, [displayColorPicker, calculatePickerPosition]);

    /**
     * Close picker
     */
    const closePicker = () => {
        setDisplayColorPicker(false);
        setColor(DEFAULT_COLOR);
    }

    /**
     * Handle color change
     */
    const handleColorChange = (color) => {
        // Use rgba if alpha is less than 1, otherwise use hex
        const colorValue = color.rgb.a < 1
            ? `rgba(${color.rgb.r}, ${color.rgb.g}, ${color.rgb.b}, ${color.rgb.a})`
            : color.hex;

        setColor(color);

        // Create synthetic event to match expected format
        const syntheticEvent = {
            target: {
                value: colorValue
            }
        };
        colorPicked(syntheticEvent);
    }

    return <>
        <div style={{position: 'relative'}} ref={pickerRef}>
            <button
                ref={buttonRef}
                type='button'
                className='lbaic-settings-radio-m lbaic-settings-radio-m-color lbaic-settings-radio-m-h-40 lbaic-settings-radio-m-pi-8'
                onClick={openPicker}>
                <i className='lbaic-settings-radio-m-color-in lbaic-settings-radio-m-multicolor'
                   style={{'--lbaic-settings-radio-m-color-bg': getDisplayColor()}}/>
            </button>
        </div>
        {displayColorPicker && (
            <>
                <div style={{
                    position: 'fixed',
                    top: 0,
                    left: 0,
                    right: 0,
                    bottom: 0,
                    zIndex: 999
                }} onClick={closePicker}></div>
                <div style={{
                    position: 'fixed',
                    zIndex: 1000,
                    top: `${pickerPosition.top}px`,
                    left: `${pickerPosition.left}px`
                }}>
                    <ChromePicker
                        color={color}
                        onChange={handleColorChange}
                        disableAlpha={true}
                        defaultView="hex"
                    />
                </div>
            </>
        )}
    </>
}