/**
 * Shared drag-reorder helpers — insertion slots between items.
 */
import { createElement } from '@wordpress/element';
import { __ } from '@wordpress/i18n';

/**
 * Move item from `from` so it lands at insertion slot `slot` (0…length).
 *
 * @param {string[]} list
 * @param {number}   from
 * @param {number}   slot
 * @return {string[]|null} Next list, or null when unchanged / invalid.
 */
export function moveToSlot( list, from, slot ) {
	if ( ! Array.isArray( list ) || list.length < 2 ) {
		return null;
	}
	if (
		from == null ||
		slot == null ||
		Number.isNaN( from ) ||
		Number.isNaN( slot )
	) {
		return null;
	}
	if ( from < 0 || from >= list.length ) {
		return null;
	}
	if ( slot < 0 || slot > list.length ) {
		return null;
	}
	// Dropping into the slot immediately before/after self is a no-op.
	if ( slot === from || slot === from + 1 ) {
		return null;
	}
	const next = [ ...list ];
	const [ item ] = next.splice( from, 1 );
	let insertAt = slot;
	if ( from < slot ) {
		insertAt -= 1;
	}
	next.splice( insertAt, 0, item );
	return next;
}

/**
 * Map pointer Y over an item to an insertion slot (before or after).
 *
 * @param {DragEvent|MouseEvent} event
 * @param {number}               index
 * @return {number}
 */
export function slotFromItemPointer( event, index ) {
	const el = event.currentTarget;
	if ( ! ( el instanceof HTMLElement ) ) {
		return index;
	}
	const rect = el.getBoundingClientRect();
	const mid = rect.top + rect.height / 2;
	return event.clientY < mid ? index : index + 1;
}

/**
 * Visible drop line between / around reorderable rows.
 *
 * @param {object}   props
 * @param {number}   props.slot
 * @param {boolean}  props.active
 * @param {boolean}  props.visible  Expand hit area while a drag is in progress
 * @param {Function} props.onHover
 * @param {Function} props.onDrop
 * @param {string}   [props.tagName]  'div' | 'li'
 */
export function DropSlot( {
	slot,
	active,
	visible,
	onHover,
	onDrop,
	tagName = 'div',
} ) {
	const Tag = tagName === 'li' ? 'li' : 'div';
	return createElement(
		Tag,
		{
			className: [
				'bm-drop-slot',
				visible ? 'is-visible' : '',
				active ? 'is-active' : '',
			]
				.filter( Boolean )
				.join( ' ' ),
			'aria-hidden': active ? 'false' : 'true',
			onDragOver: ( event ) => {
				event.preventDefault();
				event.stopPropagation();
				event.dataTransfer.dropEffect = 'move';
				onHover?.( slot );
			},
			onDrop: ( event ) => {
				event.preventDefault();
				event.stopPropagation();
				onDrop?.( event, slot );
			},
		},
		createElement( 'span', { className: 'bm-drop-slot__line' } ),
		active
			? createElement(
					'span',
					{ className: 'bm-drop-slot__label' },
					__( 'Drop here', 'joc-blockora-morph' )
			  )
			: null
	);
}
