/**
 * Design → Slides list: branded rows with delete, drag-reorder, and up/down.
 */
import { useState } from '@wordpress/element';
import { Button } from '@wordpress/components';
import { __, sprintf } from '@wordpress/i18n';
import { slideLayoutLabel } from '../shared/sliderElements';
import { MIN_HERO_SLIDES } from '../shared/sliderHelpers';
import { stripListPreviewText } from '../shared/collectionRepeater';
/**
 * @param {Array} slides
 * @param {number} from
 * @param {number} to
 * @return {Array}
 */
export function reorderSlidesArray( slides, from, to ) {
	if (
		! Array.isArray( slides ) ||
		from === to ||
		from == null ||
		to == null ||
		from < 0 ||
		to < 0 ||
		from >= slides.length ||
		to >= slides.length
	) {
		return slides;
	}
	const next = [ ...slides ];
	const [ item ] = next.splice( from, 1 );
	next.splice( to, 0, item );
	return next;
}

/**
 * Keep focused slide index in sync after a reorder.
 *
 * @param {number|null} focusIndex
 * @param {number} from
 * @param {number} to
 * @return {number|null}
 */
export function remapFocusSlideIndex( focusIndex, from, to ) {
	if ( focusIndex == null || from === to ) {
		return focusIndex;
	}
	if ( focusIndex === from ) {
		return to;
	}
	if ( from < to && focusIndex > from && focusIndex <= to ) {
		return focusIndex - 1;
	}
	if ( from > to && focusIndex >= to && focusIndex < from ) {
		return focusIndex + 1;
	}
	return focusIndex;
}

/**
 * @param {EventTarget|null} target
 * @return {boolean}
 */
function isInteractiveTarget( target ) {
	if ( ! ( target instanceof Element ) ) {
		return false;
	}
	return Boolean(
		target.closest(
			'button, a, input, select, textarea, [role="button"], .components-button'
		)
	);
}

/**
 * @param {object}   props
 * @param {Array}    props.slides
 * @param {Function} props.onReorder  (nextSlides, { from, to }) => void
 * @param {Function} props.onOpen     (slideIndex) => void
 * @param {Function} props.onRemove   (slideIndex) => void
 * @param {number}   [props.minSlides]
 */
export default function SlidesList( {
	slides = [],
	onReorder,
	onOpen,
	onRemove,
	minSlides = MIN_HERO_SLIDES,
} ) {
	const [ dragIndex, setDragIndex ] = useState( null );
	const [ overIndex, setOverIndex ] = useState( null );
	const canRemove = slides.length > minSlides;
	const canDrag = slides.length > 1;

	const move = ( index, dir ) => {
		const target = index + dir;
		if ( target < 0 || target >= slides.length ) {
			return;
		}
		const next = reorderSlidesArray( slides, index, target );
		onReorder?.( next, { from: index, to: target } );
	};

	const reorder = ( from, to ) => {
		const next = reorderSlidesArray( slides, from, to );
		if ( next === slides ) {
			return;
		}
		onReorder?.( next, { from, to } );
	};

	return (
		<div className="bm-slides-list-wrap">
			{ canDrag ? (
				<p className="bm-slides-list__hint">
					{ __(
						'Drag a slide to reorder, or use the arrows.',
						'joc-blockora-morph'
					) }
				</p>
			) : null }
			<ul className="bm-slides-list" role="list">
				{ slides.map( ( slide, index ) => {
					const isDragging = dragIndex === index;
					const isOver = overIndex === index && dragIndex !== index;
					const title = sprintf(
						/* translators: %d: slide number */
						__( 'Slide %d', 'joc-blockora-morph' ),
						index + 1
					);
					const layout = slideLayoutLabel( slide?.layout );
					const header =
						stripListPreviewText( slide?.header || '' ) ||
						stripListPreviewText( slide?.subheader || '' ) ||
						'';

					return (
						<li
							key={ `slide-row-${ index }` }
							className={ [
								'bm-slides-list__item',
								canDrag ? 'is-draggable' : '',
								isDragging ? 'is-dragging' : '',
								isOver ? 'is-drop-target' : '',
							]
								.filter( Boolean )
								.join( ' ' ) }
							draggable={ canDrag }
							onMouseDown={ ( e ) => {
								// Keep Gutenberg from treating this as block/sidebar chrome drag.
								if ( ! isInteractiveTarget( e.target ) ) {
									e.stopPropagation();
								}
							} }
							onDragStart={ ( e ) => {
								if ( ! canDrag || isInteractiveTarget( e.target ) ) {
									e.preventDefault();
									return;
								}
								e.stopPropagation();
								setDragIndex( index );
								e.dataTransfer.effectAllowed = 'move';
								e.dataTransfer.setData(
									'text/plain',
									String( index )
								);
								if ( e.currentTarget instanceof HTMLElement ) {
									e.dataTransfer.setDragImage(
										e.currentTarget,
										24,
										24
									);
								}
							} }
							onDragEnd={ () => {
								setDragIndex( null );
								setOverIndex( null );
							} }
							onDragOver={ ( e ) => {
								if ( ! canDrag ) {
									return;
								}
								e.preventDefault();
								e.stopPropagation();
								e.dataTransfer.dropEffect = 'move';
								if ( overIndex !== index ) {
									setOverIndex( index );
								}
							} }
							onDragLeave={ () => {
								if ( overIndex === index ) {
									setOverIndex( null );
								}
							} }
							onDrop={ ( e ) => {
								if ( ! canDrag ) {
									return;
								}
								e.preventDefault();
								e.stopPropagation();
								const fromRaw =
									e.dataTransfer.getData( 'text/plain' );
								const from =
									fromRaw !== ''
										? parseInt( fromRaw, 10 )
										: dragIndex;
								reorder( from, index );
								setDragIndex( null );
								setOverIndex( null );
							} }
						>
							<span
								className="bm-slides-list__handle"
								title={ __(
									'Drag to reorder',
									'joc-blockora-morph'
								) }
								aria-hidden="true"
							>
								<span className="dashicons dashicons-menu" />
							</span>

							<span
								className="bm-slides-list__index"
								aria-hidden="true"
							>
								{ index + 1 }
							</span>

							{ canRemove ? (
								<Button
									size="small"
									variant="tertiary"
									isDestructive
									className="bm-slides-list__delete"
									icon="trash"
									draggable={ false }
									onClick={ ( e ) => {
										e.preventDefault();
										e.stopPropagation();
										onRemove?.( index );
									} }
									aria-label={ sprintf(
										/* translators: %d: slide number */
										__(
											'Delete slide %d',
											'joc-blockora-morph'
										),
										index + 1
									) }
								/>
							) : (
								<span
									className="bm-slides-list__delete-spacer"
									aria-hidden="true"
								/>
							) }

							<button
								type="button"
								className="bm-slides-list__main"
								draggable={ false }
								onClick={ () => onOpen?.( index ) }
							>
								<span className="bm-slides-list__title-block">
									<span className="bm-slides-list__title-row">
										<span className="bm-slides-list__title">
											{ title }
										</span>
										<span className="bm-slides-list__layout">
											{ layout }
										</span>
									</span>
									{ header ? (
										<span className="bm-slides-list__preview">
											{ header }
										</span>
									) : null }
								</span>
								<span
									className="dashicons dashicons-arrow-right-alt2 bm-slides-list__chevron"
									aria-hidden="true"
								/>
							</button>

							<div className="bm-slides-list__move">
								<Button
									size="small"
									variant="tertiary"
									className="bm-slides-list__icon-btn"
									disabled={ index === 0 }
									draggable={ false }
									onClick={ ( e ) => {
										e.stopPropagation();
										move( index, -1 );
									} }
									aria-label={ __(
										'Move up',
										'joc-blockora-morph'
									) }
									icon="arrow-up-alt2"
								/>
								<Button
									size="small"
									variant="tertiary"
									className="bm-slides-list__icon-btn"
									disabled={ index === slides.length - 1 }
									draggable={ false }
									onClick={ ( e ) => {
										e.stopPropagation();
										move( index, 1 );
									} }
									aria-label={ __(
										'Move down',
										'joc-blockora-morph'
									) }
									icon="arrow-down-alt2"
								/>
							</div>
						</li>
					);
				} ) }
			</ul>
		</div>
	);
}
