import React, { useState, useLayoutEffect, useCallback } from 'react';

interface RippleProps {
    color?: string;
    duration?: number;
}

interface RippleState {
    x: number;
    y: number;
    size: number;
    key: number;
}

/**
 * A Material 3 Ripple effect component.
 * Usage: Place it inside a relatively positioned container.
 * The parent container needs to handle the click event or you need to
 * pass a ref to trigger it?
 * 
 * Actually, to keep it simple and non-intrusive:
 * This component just renders the ripples. The PARENT component (Button/Card)
 * must call `addRipple(e)` which is exposed via Ref?
 * 
 * OR easier:
 * <Ripple /> automatically attaches a click listener to its parentNode?
 * That's a bit "magical" but works well for drop-in.
 */
export const Ripple: React.FC<RippleProps> = ({ color = 'rgba(255, 255, 255, 0.3)', duration = 600 }) => {
    const [ripples, setRipples] = useState<RippleState[]>([]);
    const containerRef = React.useRef<HTMLDivElement>(null);

    useLayoutEffect(() => {
        const container = containerRef.current?.parentElement;
        if (!container) return;

        const handleMouseDown = (e: MouseEvent | TouchEvent) => {
            // Get coordinates
            const rect = container.getBoundingClientRect();
            let clientX, clientY;

            if ('touches' in e) {
                // Touch
                clientX = e.touches[0].clientX;
                clientY = e.touches[0].clientY;
            } else {
                // Mouse
                clientX = (e as MouseEvent).clientX;
                clientY = (e as MouseEvent).clientY;
            }

            const size = Math.max(container.offsetWidth, container.offsetHeight);
            const x = clientX - rect.left;
            const y = clientY - rect.top;

            const newRipple = {
                x,
                y,
                size,
                key: Date.now()
            };

            setRipples(prev => [...prev, newRipple]);
        };

        // Attach listeners to parent
        // 'mousedown' covers desktop. 'touchstart' might be needed for mobile/instant feedback but often conflicts with scrolling.
        // Let's stick to mousedown for now, or click? Mousedown feels snappier.
        container.addEventListener('mousedown', handleMouseDown);

        // Ensure parent is relative and overflow hidden if possible? 
        // We shouldn't force styles that break layout, but user must know.
        const style = window.getComputedStyle(container);
        if (style.position === 'static') {
            container.style.position = 'relative';
        }
        if (style.overflow !== 'hidden') {
            container.style.overflow = 'hidden';
        }

        return () => {
            container.removeEventListener('mousedown', handleMouseDown);
        };
    }, []);

    return (
        <div
            ref={containerRef}
            className="absolute inset-0 pointer-events-none z-0 rounded-[inherit]"
        >
            {ripples.map((ripple) => (
                <span
                    key={ripple.key}
                    style={{
                        top: ripple.y,
                        left: ripple.x,
                        width: ripple.size,
                        height: ripple.size,
                        backgroundColor: color,
                        animationDuration: `${duration}ms`
                    }}
                    className="absolute rounded-full animate-ripple transform -translate-x-1/2 -translate-y-1/2 opacity-30"
                    onAnimationEnd={() => setRipples(prev => prev.filter(i => i.key !== ripple.key))}
                />
            ))}
        </div>
    );
};
