import { useBlockProps, InspectorControls } from '@wordpress/block-editor';
import { useEffect, useMemo } from '@wordpress/element';
import { compose } from '@wordpress/compose';
import { __ } from '@wordpress/i18n';

import { BlockStyles, withUniqueId } from '@edge22/block-styles';

import { BlockSettings } from './components/BlockSettings';
import { withStyles } from '@hoc/withStyles';
import { BlockStylesBuilder } from '@components/index';
import { withHtmlAttributes } from '@hoc/withHtmlAttributes.js';
import { getBlockClasses } from '@utils/getBlockClasses';

const createPaginationItem = ( content, Tag = 'a', extraClass = '', key = content ) => (
	<Tag key={ key } className={ `page-numbers ${ extraClass }` }>
		{ content }
	</Tag>
);

const previewPaginationNumbers = ( midSize, totalPages, currentPage ) => {
	const paginationItems = [];

	// First set of pagination items (from page 1 to currentPage - midSize).
	const startPage = Math.max( 1, currentPage - midSize );
	const endPage = Math.min( currentPage + midSize, totalPages );

	// Add first page if it's not within the range.
	if ( startPage > 1 ) {
		paginationItems.push( createPaginationItem( 1, 'a', '', 'page-1' ) );
		if ( startPage > 2 ) {
			// Add dots if there's a gap between the first page and the range.
			paginationItems.push( createPaginationItem( '...', 'span', 'dots', 'dots-start' ) );
		}
	}

	// Loop through the pages in the calculated range.
	for ( let i = startPage; i <= endPage; i++ ) {
		if ( i === currentPage ) {
			// Current page
			paginationItems.push( createPaginationItem( i, 'span', 'current', `current-${ i }` ) );
		} else {
			paginationItems.push( createPaginationItem( i, 'a', '', `page-${ i }` ) );
		}
	}

	// Add last page if it's not within the range.
	if ( endPage < totalPages ) {
		if ( endPage < totalPages - 1 ) {
			// Add dots if there's a gap between the last page in the range and totalPages.
			paginationItems.push( createPaginationItem( '...', 'span', 'dots', 'dots-end' ) );
		}
		paginationItems.push( createPaginationItem( totalPages, 'a', '', `last-${ totalPages }` ) );
	}

	return <>{ paginationItems }</>;
};

function EditBlock( props ) {
	const {
		attributes,
		setAttributes,
		onStyleChange,
		editorHtmlAttributes,
		styles,
		name,
	} = props;

	const {
		tagName,
		midSize,
	} = attributes;

	const classNames = getBlockClasses(
		'gb-query-page-numbers',
		{
			...attributes,
			styles,
		}
	);

	useEffect( () => {
		if ( ! tagName ) {
			setAttributes( { tagName: 'nav' } );
		}
	}, [ tagName ] );

	const blockProps = useBlockProps(
		{
			className: classNames.join( ' ' ).trim(),
			...editorHtmlAttributes,
		}
	);

	const TagName = tagName || 'div';

	const shortcuts = useMemo( () => {
		const visibleSelectors = [
			{
				label: __( 'Main', 'generateblocks' ),
				value: '',
			},
		];

		return {
			selectorShortcuts: {
				default: {
					label: __( 'Numbers', 'generateblocks' ),
					items: [
						{ label: __( 'Page Number', 'generateblocks' ), value: '.page-numbers' },
						{ label: __( 'Hovered Page Number', 'generateblocks' ), value: '.page-numbers:is(:hover, :focus)' },
						{ label: __( 'Current Page Number', 'generateblocks' ), value: '.page-numbers.current' },
						{ label: __( 'Dots', 'generateblocks' ), value: '.page-numbers.dots' },
					],
				},
			},
			visibleShortcuts: visibleSelectors,
		};
	}, [] );

	return (
		<>
			<InspectorControls>
				<BlockStyles
					settingsTab={ (
						<BlockSettings
							{ ...props }
						/>
					) }
					stylesTab={ (
						<BlockStylesBuilder
							attributes={ attributes }
							setAttributes={ setAttributes }
							shortcuts={ shortcuts }
							onStyleChange={ onStyleChange }
							name={ name }
						/>
					) }
				/>
			</InspectorControls>
			<TagName { ...blockProps }>
				{ previewPaginationNumbers( midSize, 6, 1 ) }
			</TagName>
		</>
	);
}

const Edit = compose(
	withHtmlAttributes,
	withStyles,
	withUniqueId
)( EditBlock );

export { Edit };
