import { Button, BaseControl } from '@wordpress/components';
import { useInstanceId } from '@wordpress/compose';
import { __ } from '@wordpress/i18n';
import { Plus, Trash2 } from 'lucide-react';
import { slugify } from '../../slug';

const slugSources = ( field ) => {
	if ( Array.isArray( field?.slugFrom ) ) {
		return field.slugFrom.filter( Boolean );
	}

	return field?.slugFrom ? [ field.slugFrom ] : [];
};

const composedSlug = ( field, values ) =>
	slugify(
		slugSources( field )
			.map( ( source ) => values?.[ source ] )
			.filter(
				( value ) =>
					value !== undefined &&
					value !== null &&
					String( value ).trim() !== ''
			)
			.join( '-' )
	);

const createEmptyItem = ( fields = [] ) => {
	return fields.reduce( ( acc, field ) => {
		if (
			field &&
			field.name !== undefined &&
			field.default !== undefined
		) {
			acc[ field.name ] = field.default;
		}

		return acc;
	}, {} );
};

const RepeaterField = ( {
	field,
	value,
	onChange,
	renderField,
	errors = {},
	formValues,
} ) => {
	const items = Array.isArray( value ) ? value : [];
	const subFields = field.fields ?? [];
	const instanceId = useInstanceId( RepeaterField, 'repeater-field' );
	const controlId = field?.id ?? field?.name ?? instanceId;
	// Inline (itemColumns) repeaters are compact: one row per item + icon controls.
	const isInline = Number.isFinite( field.itemColumns ) && field.itemColumns > 0;

	const handleAdd = () => {
		const newItem = createEmptyItem( subFields );
		onChange( [ ...items, newItem ] );
	};

	const handleRemove = ( index ) => {
		const nextItems = items.filter(
			( _, itemIndex ) => itemIndex !== index
		);
		onChange( nextItems );
	};

	const handleItemChange = ( index, fieldName, fieldValue ) => {
		const nextItems = items.map( ( item, itemIndex ) => {
			if ( itemIndex !== index ) {
				return item;
			}

			const updated = { ...item, [ fieldName ]: fieldValue };

			// Slug-follow within the row accepts a source or ordered source list.
			subFields.forEach( ( subField ) => {
				if (
					! subField ||
					! slugSources( subField ).includes( fieldName )
				) {
					return;
				}
				const current = updated[ subField.name ] ?? '';
				const previousSlug = composedSlug( subField, item );
				if ( current === '' || current === previousSlug ) {
					updated[ subField.name ] = composedSlug(
						subField,
						updated
					);
				}
			} );

			return updated;
		} );

		onChange( nextItems );
	};

	const renderItem = ( item, index ) => {
		const itemErrors = Array.isArray( errors?.items )
			? errors.items[ index ]
			: undefined;

		const itemColumns = Number.isFinite( field.itemColumns )
			? field.itemColumns
			: null;
		const fieldsStyle = itemColumns
			? {
					display: 'grid',
					gridTemplateColumns: `repeat(${ itemColumns }, minmax(0, 1fr))`,
					gap: '12px',
					alignItems: 'end',
			  }
			: undefined;

		return (
			<div
				key={ `${ field.name }-${ index }` }
				className={ `cliq-ui-repeater-item${ itemColumns ? ' is-inline' : '' }` }
			>
				<div className="cliq-ui-repeater-item-fields" style={ fieldsStyle }>
					{ subFields.map( ( subField ) =>
						renderField( subField, {
							key: `${ field.name }-${ index }-${
								subField.name ?? subField.id ?? index
							}`,
							values: item,
							value: item?.[ subField.name ],
							onChange: ( nextValue ) =>
								handleItemChange(
									index,
									subField.name,
									nextValue
								),
							wrap: true,
							errors: itemErrors?.[ subField.name ],
							formValues,
						} )
					) }
				</div>
				<div className="cliq-ui-repeater-item-actions">
					<Button
						variant="tertiary"
						onClick={ () => handleRemove( index ) }
						isDestructive={ ! itemColumns }
						className={ itemColumns ? 'cliq-ui-repeater-remove--icon' : '' }
						aria-label={ __( 'Remove', 'cliq-store-locator' ) }
					>
						{ itemColumns ? (
							<Trash2 size={ 15 } />
						) : (
							field.removeButtonLabel ??
							__( 'Remove', 'cliq-store-locator' )
						) }
					</Button>
				</div>
			</div>
		);
	};

	const maxItems = Number.isFinite( field.maxItems )
		? field.maxItems
		: undefined;
	const canAddMore = maxItems === undefined || items.length < maxItems;

	return (
		<BaseControl
			id={ controlId }
			label={ field.label }
			help={ field.help }
			required={ field.required }
		>
			<div className={ `cliq-ui-repeater-field${ isInline ? ' is-inline' : '' }` }>
				{ isInline && field.showColumnHeaders && (
					<div
						className="cliq-ui-repeater-columns-head"
						style={ { gridTemplateColumns: `repeat(${ field.itemColumns }, minmax(0, 1fr)) 32px` } }
					>
						{ subFields.map( ( subField ) => (
							<span key={ subField.name ?? subField.id }>{ subField.label }</span>
						) ) }
						<span aria-hidden="true" />
					</div>
				) }
				<div className={ `cliq-ui-repeater-items${ isInline ? ' is-inline' : '' }` }>
					{ items.length === 0 && (
						<div className="cliq-ui-repeater-empty">
							{ field.emptyMessage ??
								__( 'No items added yet.', 'cliq-store-locator' ) }
						</div>
					) }
					{ items.map( renderItem ) }
				</div>
				{ errors?._error && (
					<div className="cliqthemes-ui-field-error">
						{ errors._error }
					</div>
				) }
				{ canAddMore &&
					( isInline && field.compactAddIcon !== false ? (
						<Button
							variant="tertiary"
							onClick={ handleAdd }
							className="cliq-ui-repeater-add--icon"
							aria-label={
								field.addButtonLabel ??
								__( 'Add', 'cliq-store-locator' )
							}
							title={
								field.addButtonLabel ??
								__( 'Add', 'cliq-store-locator' )
							}
						>
							<Plus size={ 18 } />
						</Button>
					) : (
						<Button variant="secondary" icon={ <Plus size={ 16 } /> } onClick={ handleAdd }>
							{ field.addButtonLabel ??
								__( 'Add item', 'cliq-store-locator' ) }
						</Button>
					) ) }
			</div>
		</BaseControl>
	);
};

export default RepeaterField;
