/**
 * Horizontal scroller with edge-aware left/right chevrons.
 * Left shows only when scrolled away from the start; right only when more content remains.
 */
import { useCallback, useEffect, useRef, useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';

/**
 * @param {object}   props
 * @param {import('@wordpress/element').WPElement} props.children
 * @param {string}   [props.className]
 * @param {string}   [props.trackClassName]
 * @param {object}   [props.trackProps]
 * @param {number}   [props.scrollFactor] Fraction of visible width to scroll per click.
 * @param {*}        [props.remeasureKey] Remeasure when this changes (e.g. item count / open).
 */
export default function HorizontalScrollRail( {
	children,
	className = '',
	trackClassName = '',
	trackProps = {},
	scrollFactor = 0.75,
	remeasureKey,
} ) {
	const trackRef = useRef( null );
	const [ canLeft, setCanLeft ] = useState( false );
	const [ canRight, setCanRight ] = useState( false );

	const updateEdges = useCallback( () => {
		const el = trackRef.current;
		if ( ! el ) {
			setCanLeft( false );
			setCanRight( false );
			return;
		}
		const { scrollLeft, scrollWidth, clientWidth } = el;
		const max = Math.max( 0, scrollWidth - clientWidth );
		const overflow = max > 2;
		setCanLeft( overflow && scrollLeft > 2 );
		setCanRight( overflow && scrollLeft < max - 2 );
	}, [] );

	useEffect( () => {
		const el = trackRef.current;
		if ( ! el ) {
			return undefined;
		}
		updateEdges();
		el.addEventListener( 'scroll', updateEdges, { passive: true } );
		const ro = new ResizeObserver( () => updateEdges() );
		ro.observe( el );
		Array.from( el.children ).forEach( ( child ) => ro.observe( child ) );
		const onWin = () => updateEdges();
		window.addEventListener( 'resize', onWin );
		const t1 = window.setTimeout( updateEdges, 50 );
		const t2 = window.setTimeout( updateEdges, 320 );
		return () => {
			el.removeEventListener( 'scroll', updateEdges );
			ro.disconnect();
			window.removeEventListener( 'resize', onWin );
			window.clearTimeout( t1 );
			window.clearTimeout( t2 );
		};
	}, [ updateEdges, remeasureKey, children ] );

	const scrollByDir = ( dir ) => {
		const el = trackRef.current;
		if ( ! el ) {
			return;
		}
		const amount = Math.max( 120, el.clientWidth * scrollFactor );
		el.scrollBy( { left: dir * amount, behavior: 'smooth' } );
	};

	const rootClass = [ 'bm-hscroll', className ].filter( Boolean ).join( ' ' );
	const trackClass = [ 'bm-hscroll__track', trackClassName ]
		.filter( Boolean )
		.join( ' ' );

	return (
		<div className={ rootClass }>
			{ canLeft ? (
				<button
					type="button"
					className="bm-hscroll__btn bm-hscroll__btn--left"
					aria-label={ __( 'Scroll left', 'joc-blockora-morph' ) }
					onClick={ () => scrollByDir( -1 ) }
				>
					<span
						className="dashicons dashicons-arrow-left-alt2"
						aria-hidden="true"
					/>
				</button>
			) : null }
			<div
				{ ...trackProps }
				ref={ trackRef }
				className={ trackClass }
			>
				{ children }
			</div>
			{ canRight ? (
				<button
					type="button"
					className="bm-hscroll__btn bm-hscroll__btn--right"
					aria-label={ __( 'Scroll right', 'joc-blockora-morph' ) }
					onClick={ () => scrollByDir( 1 ) }
				>
					<span
						className="dashicons dashicons-arrow-right-alt2"
						aria-hidden="true"
					/>
				</button>
			) : null }
		</div>
	);
}
