import {
	Button,
	ButtonGroup,
	ComboboxControl,
	ToggleControl,
} from '@wordpress/components';
import { __, sprintf } from '@wordpress/i18n';

export const TEMPLATE_FIELDS = {
	card: [
		[ 'logo', __( 'Hero image', 'cliq-store-locator' ) ],
		[ 'name', __( 'Store name', 'cliq-store-locator' ) ],
		[ 'address', __( 'Address', 'cliq-store-locator' ) ],
		[ 'category', __( 'Category', 'cliq-store-locator' ) ],
		[ 'brand', __( 'Brand name', 'cliq-store-locator' ) ],
		[ 'brand_logo', __( 'Brand logo', 'cliq-store-locator' ) ],
		[ 'phone', __( 'Telephone', 'cliq-store-locator' ) ],
		[ 'email', __( 'Email', 'cliq-store-locator' ) ],
		[ 'website', __( 'Website', 'cliq-store-locator' ) ],
		[ 'opening_hours', __( 'Opening hours', 'cliq-store-locator' ) ],
		[ 'distance', __( 'Distance', 'cliq-store-locator' ) ],
		[ 'details', __( 'Details button', 'cliq-store-locator' ) ],
	],
	infobox: [
		[ 'logo', __( 'Hero image', 'cliq-store-locator' ) ],
		[ 'name', __( 'Store name', 'cliq-store-locator' ) ],
		[ 'address', __( 'Address', 'cliq-store-locator' ) ],
		[ 'category', __( 'Category', 'cliq-store-locator' ) ],
		[ 'phone', __( 'Telephone', 'cliq-store-locator' ) ],
		[ 'email', __( 'Email', 'cliq-store-locator' ) ],
		[ 'website', __( 'Website', 'cliq-store-locator' ) ],
		[ 'directions', __( 'Directions button', 'cliq-store-locator' ) ],
		[ 'details', __( 'Details button', 'cliq-store-locator' ) ],
	],
	detail: [
		[ 'logo', __( 'Hero image', 'cliq-store-locator' ) ],
		[ 'name', __( 'Store name', 'cliq-store-locator' ) ],
		[ 'address', __( 'Address', 'cliq-store-locator' ) ],
		[ 'category', __( 'Category', 'cliq-store-locator' ) ],
		[ 'brand', __( 'Brand name', 'cliq-store-locator' ) ],
		[ 'brand_logo', __( 'Brand logo', 'cliq-store-locator' ) ],
		[ 'description', __( 'Description', 'cliq-store-locator' ) ],
		[ 'phone', __( 'Telephone', 'cliq-store-locator' ) ],
		[ 'email', __( 'Email', 'cliq-store-locator' ) ],
		[ 'website', __( 'Website', 'cliq-store-locator' ) ],
		[ 'opening_hours', __( 'Opening hours', 'cliq-store-locator' ) ],
	],
};

const ICON_OPTIONS = [
	[ '', __( 'No icon', 'cliq-store-locator' ) ],
	[ 'phone', __( 'Telephone', 'cliq-store-locator' ) ],
	[ 'mail', __( 'Email', 'cliq-store-locator' ) ],
	[ 'smartphone', __( 'Mobile', 'cliq-store-locator' ) ],
	[ 'map-pin', __( 'Marker', 'cliq-store-locator' ) ],
	[ 'globe', __( 'Website', 'cliq-store-locator' ) ],
	[ 'link', __( 'Link', 'cliq-store-locator' ) ],
	[ 'external-link', __( 'External link', 'cliq-store-locator' ) ],
	[ 'clock', __( 'Opening hours', 'cliq-store-locator' ) ],
	[ 'wifi', __( 'Wi-Fi', 'cliq-store-locator' ) ],
	[ 'twitter', __( 'Twitter / X', 'cliq-store-locator' ) ],
	[ 'facebook', __( 'Facebook', 'cliq-store-locator' ) ],
	[ 'instagram', __( 'Instagram', 'cliq-store-locator' ) ],
	[ 'whatsapp', __( 'WhatsApp', 'cliq-store-locator' ) ],
	[ 'arrow-right', __( 'Arrow', 'cliq-store-locator' ) ],
	[ 'chevron-right', __( 'Chevron', 'cliq-store-locator' ) ],
	[ 'tag', __( 'Tag', 'cliq-store-locator' ) ],
];

const normaliseFields = ( fields, definitions ) => {
	const byField = new Map(
		( Array.isArray( fields ) ? fields : [] )
			.filter( ( item ) => item?.field )
			.map( ( item ) => [ item.field, item ] )
	);
	const ordered = [];
	( Array.isArray( fields ) ? fields : [] ).forEach( ( item ) => {
		if ( definitions.some( ( [ field ] ) => field === item?.field ) ) {
			ordered.push( {
				field: item.field,
				enabled: !! item.enabled,
				icon: item.icon || '',
				column: Number( item.column ) === 2 ? 2 : 1,
			} );
			byField.delete( item.field );
		}
	} );
	definitions.forEach( ( [ field ] ) => {
		if ( ! ordered.some( ( item ) => item.field === field ) ) {
			const item = byField.get( field );
			ordered.push( {
				field,
				enabled: !! item?.enabled,
				icon: item?.icon || '',
				column: Number( item?.column ) === 2 ? 2 : 1,
			} );
		}
	} );
	return ordered;
};

const ColumnArrow = ( { direction = 'right' } ) => (
	<svg
		aria-hidden="true"
		focusable="false"
		height="16"
		viewBox="0 0 24 24"
		width="16"
	>
		<path
			d={ direction === 'left' ? 'm14.5 6-6 6 6 6' : 'm9.5 6 6 6-6 6' }
			fill="none"
			stroke="currentColor"
			strokeLinecap="round"
			strokeLinejoin="round"
			strokeWidth="2"
		/>
	</svg>
);

export const TemplateEditor = ( {
	title,
	description,
	type,
	value,
	onChange,
	customFields = [],
	columns = 1,
	onColumnsChange,
} ) => {
	const definitions = [
		...( TEMPLATE_FIELDS[ type ] || [] ),
		...customFields.map( ( field ) => [
			`custom:${ field.field_key }`,
			field.label ||
				field.field_key ||
				__( 'Custom field', 'cliq-store-locator' ),
		] ),
	];
	const labels = Object.fromEntries( definitions );
	const items = normaliseFields( value, definitions );

	const patch = ( index, values ) => {
		onChange(
			items.map( ( item, itemIndex ) =>
				itemIndex === index ? { ...item, ...values } : item
			)
		);
	};

	const splitEvenly = () => {
		const splitAt = Math.ceil( items.length / 2 );
		onChange(
			items.map( ( item, index ) => ( {
				...item,
				column: index < splitAt ? 1 : 2,
			} ) )
		);
	};

	const move = ( field, direction, column = null ) => {
		const lane = items.filter(
			( item ) => column === null || Number( item.column || 1 ) === column
		);
		const laneIndex = lane.findIndex( ( item ) => item.field === field );
		const targetLaneIndex = laneIndex + direction;
		if (
			laneIndex < 0 ||
			targetLaneIndex < 0 ||
			targetLaneIndex >= lane.length
		) {
			return;
		}
		const sourceIndex = items.findIndex( ( item ) => item.field === field );
		const targetIndex = items.findIndex(
			( item ) => item.field === lane[ targetLaneIndex ].field
		);
		const next = [ ...items ];
		[ next[ sourceIndex ], next[ targetIndex ] ] = [
			next[ targetIndex ],
			next[ sourceIndex ],
		];
		onChange( next );
	};

	const renderItem = ( item, column = null ) => {
		const index = items.findIndex(
			( current ) => current.field === item.field
		);
		const lane = items.filter(
			( current ) =>
				column === null ||
				Number( current.column || 1 ) === Number( column )
		);
		const laneIndex = lane.findIndex(
			( current ) => current.field === item.field
		);

		return (
			<div
				className={ `cliq-sl-template__item ${
					Number( columns ) === 2 ? 'has-column-picker' : ''
				}` }
				key={ item.field }
			>
				<div className="cliq-sl-template__primary">
					<div className="cliq-sl-template__order">
						<Button
							variant="tertiary"
							size="small"
							disabled={ laneIndex === 0 }
							onClick={ () => move( item.field, -1, column ) }
							label={ __( 'Move up', 'cliq-store-locator' ) }
						>
							↑
						</Button>
						<Button
							variant="tertiary"
							size="small"
							disabled={ laneIndex === lane.length - 1 }
							onClick={ () => move( item.field, 1, column ) }
							label={ __( 'Move down', 'cliq-store-locator' ) }
						>
							↓
						</Button>
					</div>
					<ToggleControl
						__nextHasNoMarginBottom
						label={ labels[ item.field ] || item.field }
						checked={ item.enabled }
						onChange={ ( enabled ) => patch( index, { enabled } ) }
					/>
				</div>
				<div className="cliq-sl-template__controls">
					<div className="cliq-sl-template__select">
						<ComboboxControl
							__nextHasNoMarginBottom
							label={ __( 'Icon', 'cliq-store-locator' ) }
							hideLabelFromVision
							value={ item.icon }
							options={ ICON_OPTIONS.map(
								( [ optionValue, label ] ) => ( {
									value: optionValue,
									label,
								} )
							) }
							onChange={ ( icon ) =>
								patch( index, { icon: icon || '' } )
							}
						/>
					</div>
					{ Number( columns ) === 2 && (
						<Button
							className="cliq-sl-template__move-column"
							icon={
								<ColumnArrow
									direction={
										Number( item.column || 1 ) === 1
											? 'right'
											: 'left'
									}
								/>
							}
							iconPosition={
								Number( item.column || 1 ) === 1
									? 'right'
									: 'left'
							}
							onClick={ () =>
								patch( index, {
									column:
										Number( item.column || 1 ) === 1
											? 2
											: 1,
								} )
							}
							variant="secondary"
						>
							{ Number( item.column || 1 ) === 1
								? __( 'Move to column 2', 'cliq-store-locator' )
								: __(
										'Move to column 1',
										'cliq-store-locator'
								  ) }
						</Button>
					) }
				</div>
			</div>
		);
	};

	return (
		<div className="cliq-sl-template">
			<div className="cliq-sl-template__heading">
				<div>
					<h3>{ title }</h3>
					<p>{ description }</p>
				</div>
				{ typeof onColumnsChange === 'function' && (
					<ButtonGroup
						className="cliq-sl-template__columns"
						aria-label={ __(
							'Template columns',
							'cliq-store-locator'
						) }
					>
						{ [ 1, 2 ].map( ( count ) => (
							<Button
								key={ count }
								variant={
									Number( columns ) === count
										? 'primary'
										: 'secondary'
								}
								onClick={ () => onColumnsChange( count ) }
							>
								{ count === 1
									? __( '1 column', 'cliq-store-locator' )
									: __( '2 columns', 'cliq-store-locator' ) }
							</Button>
						) ) }
					</ButtonGroup>
				) }
			</div>
			{ Number( columns ) === 2 ? (
				<div className="cliq-sl-template__lanes">
					{ [ 1, 2 ].map( ( column ) => {
						const laneItems = items.filter(
							( item ) => Number( item.column || 1 ) === column
						);
						return (
							<section
								className="cliq-sl-template__lane"
								key={ column }
							>
								<header>
									<strong>
										{ sprintf(
											/* translators: %d: template column number. */
											__(
												'Column %d',
												'cliq-store-locator'
											),
											column
										) }
									</strong>
									<span>{ laneItems.length }</span>
								</header>
								<div className="cliq-sl-template__list">
									{ laneItems.length ? (
										laneItems.map( ( item ) =>
											renderItem( item, column )
										)
									) : (
										<div className="cliq-sl-template__empty">
											<strong>
												{ sprintf(
													/* translators: %d: template column number. */
													__(
														'Column %d is empty',
														'cliq-store-locator'
													),
													column
												) }
											</strong>
											<p>
												{ __(
													'Use the move button on any field, or distribute the fields automatically.',
													'cliq-store-locator'
												) }
											</p>
											<Button
												onClick={ splitEvenly }
												variant="secondary"
											>
												{ __(
													'Split fields evenly',
													'cliq-store-locator'
												) }
											</Button>
										</div>
									) }
								</div>
							</section>
						);
					} ) }
				</div>
			) : (
				<div className="cliq-sl-template__list">
					{ items.map( ( item ) => renderItem( item ) ) }
				</div>
			) }
		</div>
	);
};

const SLUG_FIELDS = [
	[ 'city', __( 'City', 'cliq-store-locator' ) ],
	[ 'name', __( 'Store name', 'cliq-store-locator' ) ],
	[ 'state', __( 'State / region', 'cliq-store-locator' ) ],
	[ 'postal_code', __( 'Postal code', 'cliq-store-locator' ) ],
	[ 'country', __( 'Country', 'cliq-store-locator' ) ],
];

export const SlugFieldsEditor = ( { value, onChange } ) => {
	const selected =
		Array.isArray( value ) && value.length ? value : [ 'city', 'name' ];
	const ordered = [
		...selected.filter( ( field ) =>
			SLUG_FIELDS.some( ( [ allowed ] ) => allowed === field )
		),
		...SLUG_FIELDS.map( ( [ field ] ) => field ).filter(
			( field ) => ! selected.includes( field )
		),
	];
	const labels = Object.fromEntries( SLUG_FIELDS );

	const toggle = ( field, enabled ) => {
		const next = enabled
			? [ ...selected, field ]
			: selected.filter( ( item ) => item !== field );
		onChange( next.length ? next : [ 'city', 'name' ] );
	};
	const move = ( field, direction ) => {
		const active = ordered.filter( ( item ) => selected.includes( item ) );
		const index = active.indexOf( field );
		const target = index + direction;
		if ( index < 0 || target < 0 || target >= active.length ) {
			return;
		}
		[ active[ index ], active[ target ] ] = [
			active[ target ],
			active[ index ],
		];
		onChange( active );
	};

	return (
		<div className="cliq-sl-slug-fields">
			<strong>
				{ __( 'Store URL parts', 'cliq-store-locator' ) }
			</strong>
			<p>
				{ __(
					'Enabled parts form every public store URL in this order. For example, City + Store name becomes london-flagship-store.',
					'cliq-store-locator'
				) }
			</p>
			{ ordered.map( ( field ) => {
				const enabled = selected.includes( field );
				const activeIndex = selected.indexOf( field );
				return (
					<div
						className="cliq-sl-slug-fields__item"
						key={ field }
					>
						<ToggleControl
							__nextHasNoMarginBottom
							label={ labels[ field ] }
							checked={ enabled }
							onChange={ ( next ) => toggle( field, next ) }
						/>
						<div>
							<Button
								variant="tertiary"
								size="small"
								disabled={ ! enabled || activeIndex <= 0 }
								onClick={ () => move( field, -1 ) }
							>
								↑
							</Button>
							<Button
								variant="tertiary"
								size="small"
								disabled={
									! enabled ||
									activeIndex >= selected.length - 1
								}
								onClick={ () => move( field, 1 ) }
							>
								↓
							</Button>
						</div>
					</div>
				);
			} ) }
		</div>
	);
};
