import { useEffect, useRef } from '@wordpress/element';
import { useSelect, useDispatch } from '@wordpress/data';
import { createBlock } from '@wordpress/blocks';

/**
 * Keeps the inner `axcelersblocks/column` children in sync with the
 * `columns` attribute of the parent `axcelersblocks/columns` block.
 *
 * Responsibilities:
 *   - ADD columns when the `columns` attribute is increased by the user.
 *   - REMOVE columns when the `columns` attribute is decreased by the user.
 *   - REDISTRIBUTE column widths across all columns when the count changes.
 *   - SYNC the `columns` attribute back when the user adds/removes a column
 *     directly via the block toolbar (two-way sync).
 *
 * Initial column creation (fresh insert) is handled separately via the
 * `template` prop on `useInnerBlocksProps` in edit.js. That approach is
 * synchronous and immune to React Strict Mode double-invoke timing issues
 * that would affect a useEffect-based first-run solution.
 */

/** Equal-width attributes for N columns. */
const getColumnWidthAttrs = ( count ) => {
	const pct = `${ Math.round( ( 100 / count ) * 100 ) / 100 }%`;
	return {
		width: {
			desktop: pct,
			tablet: pct,
			mobile: '100%',
		},
	};
};

const useColumnsChildrenSync = ( {
	clientId,
	columns = 2,
	childName = 'axcelersblocks/column',
	setColumnsAttribute,
} ) => {
	const childrenIds = useSelect(
		( select ) => select( 'core/block-editor' ).getBlockOrder( clientId ),
		[ clientId ]
	);

	const { insertBlocks, removeBlocks, updateBlockAttributes } = useDispatch( 'core/block-editor' );

	const prevColumnsRef = useRef( columns );
	const prevChildCountRef = useRef(
		Array.isArray( childrenIds ) ? childrenIds.length : 0
	);

	useEffect( () => {
		if ( ! Array.isArray( childrenIds ) ) {
			return;
		}

		const currentCount = childrenIds.length;
		const prevColumns = prevColumnsRef.current;
		const prevChildCount = prevChildCountRef.current;

		prevColumnsRef.current = columns;
		prevChildCountRef.current = currentCount;

		// Already in sync — nothing to do.
		if ( currentCount === columns ) {
			return;
		}

		const columnsAttrChanged = columns !== prevColumns;
		const childCountChanged = currentCount !== prevChildCount;

		// The `columns` attribute was deliberately changed by the user.
		// Add or remove column blocks to match, and redistribute widths.
		if ( columnsAttrChanged ) {
			const widthAttrs = getColumnWidthAttrs( columns );

			if ( currentCount < columns ) {
				const blocksToInsert = Array.from(
					{ length: columns - currentCount },
					() => createBlock( childName, widthAttrs )
				);
				insertBlocks( blocksToInsert, currentCount, clientId, false );
				// Redistribute widths on existing columns.
				childrenIds.forEach( ( id ) => updateBlockAttributes( id, widthAttrs ) );
			} else {
				removeBlocks( childrenIds.slice( columns ), false );
				childrenIds.slice( 0, columns ).forEach( ( id ) =>
					updateBlockAttributes( id, widthAttrs )
				);
			}
			return;
		}

		// The columns attribute didn't change but the inner block count did —
		// the user added, duplicated, or removed a column via the block toolbar.
		// Sync the attribute so the range control reflects reality.
		if ( childCountChanged && typeof setColumnsAttribute === 'function' ) {
			setColumnsAttribute( currentCount );
		}
	}, [
		columns,
		childrenIds,
		clientId,
		childName,
		insertBlocks,
		removeBlocks,
		updateBlockAttributes,
		setColumnsAttribute,
	] );
};

export default useColumnsChildrenSync;
