import { __ } from '@wordpress/i18n';
import { InspectorControls, useBlockProps, InnerBlocks } from '@wordpress/block-editor';
import {
	PanelBody,
	SelectControl,
	TextControl,
	ToggleControl,
	RangeControl,
	ColorPalette,
	Notice,
	CheckboxControl,
	Button,
	__experimentalDivider as Divider,
	Icon,
} from '@wordpress/components';
import { useSelect, dispatch, select } from '@wordpress/data';
import { useEffect, useState, useMemo, useCallback, useRef } from '@wordpress/element';
import { createBlock } from '@wordpress/blocks';
import apiFetch from '@wordpress/api-fetch';
import { DragDropContext, Droppable, Draggable } from '@hello-pangea/dnd';
import './editor.scss';

function isSearchableContentPostType( postType ) {
	const visibility = postType?.visibility || {};
	const publicFlag = visibility?.public ?? postType?.public;
	const showUiFlag = visibility?.show_ui ?? postType?.show_ui;
	const excludeFromSearchFlag = visibility?.exclude_from_search ?? postType?.exclude_from_search;
	const showInNavMenusFlag = visibility?.show_in_nav_menus ?? postType?.show_in_nav_menus;

	return Boolean(
		postType?.slug &&
		publicFlag !== false &&
		showUiFlag === true &&
		excludeFromSearchFlag !== true &&
		showInNavMenusFlag === true
	);
}

const ALLOWED_INNER_BLOCKS = [
	'wlc-algolia/result-title',
	'wlc-algolia/result-image',
	'wlc-algolia/result-excerpt',
	'wlc-algolia/result-meta',
	'wlc-algolia/result-field',
	'wlc-algolia/result-button',
];

function presetTemplateByPostType( postType ) {
	const pt = String( postType || 'post' );
	if ( pt === 'product' ) {
		return [
			[ 'wlc-algolia/result-image', { fieldPath: 'images.thumbnail.url', linkType: 'permalink' } ],
			[ 'wlc-algolia/result-title', { fieldPath: 'post_title', linkType: 'permalink' } ],
			[ 'wlc-algolia/result-field', { label: 'Price', fieldPath: '_price' } ],
			[ 'wlc-algolia/result-field', { label: 'Stock Status', fieldPath: '_stock_status' } ],
			[ 'wlc-algolia/result-button', { label: 'Add to cart', linkType: 'add_to_cart' } ],
		];
	}
	if ( pt === 'page' ) {
		return [
			[ 'wlc-algolia/result-title', { fieldPath: 'post_title', linkType: 'permalink' } ],
			[ 'wlc-algolia/result-excerpt', { fieldPath: 'post_excerpt' } ],
			[ 'wlc-algolia/result-button', { label: 'View page', linkType: 'permalink' } ],
		];
	}
	// post + generic
	return [
		[ 'wlc-algolia/result-image', { fieldPath: 'images.thumbnail.url', linkType: 'permalink' } ],
		[ 'wlc-algolia/result-title', { fieldPath: 'post_title', linkType: 'permalink' } ],
		[ 'wlc-algolia/result-meta', { metaDate: true, metaAuthor: true } ],
		[ 'wlc-algolia/result-excerpt', { fieldPath: 'post_excerpt' } ],
		[ 'wlc-algolia/result-button', { label: 'Read more', linkType: 'permalink' } ],
	];
}

export default function Edit( props ) {
	const { attributes, setAttributes, clientId } = props;
	const {
		selectedPostType,
		hitsPerPage,
		placeholder,
		showFilters,
		showPagination,
		showResultsCount,
		paginationMode,
		paginationMaxPages,
		viewMode,
		gridColumns,
		gap,
		accentColor,
		indexNameOverride,
		facetsSelected,
		facetLabels,
		showFacetCounts,
		facetCountStyle,
		showActiveFilters,
		enableFacetSearch,
		stickyFilters,
		showSort,
		enableUrlSync,
		sortDefault,
		sortIndexSuffixes,
	} = attributes;

	const [ showPreview, setShowPreview ] = useState( false );
	const [ previewUrl, setPreviewUrl ] = useState( '' );
	const normalizeGridColumns = useCallback( ( value ) => {
		const parsed = parseInt( value, 10 );
		const next = Number.isFinite( parsed ) ? parsed : 3;
		return Math.max( 2, Math.min( 4, next ) );
	}, [] );
	const normalizePaginationMaxPages = useCallback( ( value ) => {
		const parsed = parseInt( value, 10 );
		let next = Number.isFinite( parsed ) ? parsed : 9;
		next = Math.max( 3, Math.min( 20, next ) );
		if ( next % 2 === 0 ) {
			next = Math.max( 3, next - 1 );
		}
		return next;
	}, [] );

	const postTypes = useSelect( ( s ) => {
		const data = s( 'core' ).getEntityRecords( 'root', 'postType', { per_page: -1 } );
		return data?.filter( isSearchableContentPostType );
	}, [] );

	const postTypeOptions = postTypes
		? postTypes.map( ( pt ) => ( { label: pt.labels?.singular_name || pt.slug, value: pt.slug } ) )
		: [];

	const innerCount = useSelect( ( s ) => {
		const block = s( 'core/block-editor' ).getBlock( clientId );
		return block?.innerBlocks?.length || 0;
	}, [ clientId ] );
	const innerBlocks = useSelect( ( s ) => {
		const block = s( 'core/block-editor' ).getBlock( clientId );
		return block?.innerBlocks || [];
	}, [ clientId ] );
	const selectedBlockClientId = useSelect(
		( s ) => s( 'core/block-editor' ).getSelectedBlockClientId(),
		[]
	);

	const replaceTemplateBlocks = useCallback( ( postType ) => {
		const currentPostType = String( postType || 'post' );
		const template = presetTemplateByPostType( currentPostType );
		const blocks = template.map( ( t ) => createBlock( t[ 0 ], t[ 1 ] || {} ) );
		const blockEditorDispatch = dispatch( 'core/block-editor' );

		if ( typeof blockEditorDispatch.replaceInnerBlocks === 'function' ) {
			blockEditorDispatch.replaceInnerBlocks( clientId, blocks, false );
			return;
		}

		const existingBlockClientIds = ( innerBlocks || [] ).map( ( block ) => block.clientId );
		if ( existingBlockClientIds.length ) {
			blockEditorDispatch.removeBlocks( existingBlockClientIds, false );
		}
		blockEditorDispatch.insertBlocks( blocks, 0, clientId );
	}, [ clientId, innerBlocks ] );

	// Auto-seed defaults on first insert when template is empty.
	useEffect( () => {
		if ( innerCount ) return;
		replaceTemplateBlocks( selectedPostType );
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [ selectedPostType, innerCount, replaceTemplateBlocks ] );

	// Keep image block first to match frontend rendering behavior.
	useEffect( () => {
		if ( ! Array.isArray( innerBlocks ) || innerBlocks.length < 2 ) return;
		const imageIndex = innerBlocks.findIndex( ( block ) => block?.name === 'wlc-algolia/result-image' );
		if ( imageIndex <= 0 ) return;
		const imageBlockClientId = innerBlocks[ imageIndex ]?.clientId;
		if ( ! imageBlockClientId ) return;
		dispatch( 'core/block-editor' ).moveBlocksToPosition( [ imageBlockClientId ], clientId, clientId, 0 );
	}, [ innerBlocks, clientId ] );

	// Fields/key management for quick insertion
	const [ keysLoading, setKeysLoading ] = useState( false );
	const [ keysError, setKeysError ] = useState( '' );
	const [ keysQuery, setKeysQuery ] = useState( '' );
	const [ availableKeys, setAvailableKeys ] = useState( [] );
	const keysQueryRef = useRef( keysQuery );

	// Facets management
	const [ facetsLoading, setFacetsLoading ] = useState( false );
	const [ facetsError, setFacetsError ] = useState( '' );
	const [ availableFacets, setAvailableFacets ] = useState( [] );
	const [ baseIndexName, setBaseIndexName ] = useState( '' );
	const [ algoliaIndices, setAlgoliaIndices ] = useState( [] );
	const [ indicesLoaded, setIndicesLoaded ] = useState( false );

	// Load available index keys
	useEffect( () => {
		let cancelled = false;
		async function loadKeys() {
			setKeysLoading( true );
			setKeysError( '' );
			try {
				const data = await apiFetch( {
					path: `/wlc-algolia/v1/index-keys/?post_type=${ encodeURIComponent( selectedPostType || 'post' ) }`,
				} );
				if ( cancelled ) return;
				const keys = Array.isArray( data?.keys ) ? data.keys : [];
				setAvailableKeys( keys );
			} catch ( e ) {
				if ( cancelled ) return;
				setAvailableKeys( [] );
				setKeysError( e?.message || 'Failed to load keys.' );
			} finally {
				if ( ! cancelled ) setKeysLoading( false );
			}
		}
		loadKeys();
		return () => {
			cancelled = true;
		};
	}, [ selectedPostType ] );

	// Reset search query when post type changes
	useEffect( () => {
		keysQueryRef.current = '';
		setKeysQuery( '' );
	}, [ selectedPostType ] );

	// Load facets
	useEffect( () => {
		let cancelled = false;
		async function loadFacets() {
			setFacetsLoading( true );
			setFacetsError( '' );
			try {
				const data = await apiFetch( {
					path: `/wlc-algolia/v1/facets/?post_type=${ encodeURIComponent( selectedPostType || 'post' ) }`,
				} );
				if ( cancelled ) return;
				setAvailableFacets( Array.isArray( data?.facets ) ? data.facets : [] );
			} catch ( e ) {
				if ( cancelled ) return;
				setAvailableFacets( [] );
				setFacetsError( e?.message || e?.data?.message || 'Failed to load facets.' );
			} finally {
				if ( ! cancelled ) setFacetsLoading( false );
			}
		}
		loadFacets();
		return () => {
			cancelled = true;
		};
	}, [ selectedPostType ] );

	// Load base index and list of indices to detect available replicas for sorting.
	useEffect( () => {
		let cancelled = false;
		async function loadIndices() {
			try {
				const [ apiKeysData, indicesData ] = await Promise.all( [
					apiFetch( { path: '/wlc-algolia/v1/api-keys/' } ),
					apiFetch( { path: '/wlc-algolia/v1/indices/' } ),
				] );
				if ( cancelled ) return;
				const baseName = String( apiKeysData?.api_keys?.indexName || '' ).trim();
				const names = Array.isArray( indicesData?.indices )
					? indicesData.indices
							.map( ( item ) => String( item?.name || '' ).trim() )
							.filter( Boolean )
					: [];
				setBaseIndexName( baseName );
				setAlgoliaIndices( names );
			} catch ( e ) {
				if ( cancelled ) return;
				setBaseIndexName( '' );
				setAlgoliaIndices( [] );
			} finally {
				if ( ! cancelled ) setIndicesLoaded( true );
			}
		}
		loadIndices();
		return () => {
			cancelled = true;
		};
	}, [] );

	// Filter keys by query
	const filteredKeys = useMemo( () => {
		const q = String( keysQuery || '' ).toLowerCase().trim();
		if ( ! q ) return availableKeys.slice( 0, 100 );
		return availableKeys.filter( ( k ) => String( k?.path || '' ).toLowerCase().includes( q ) ).slice( 0, 150 );
	}, [ availableKeys, keysQuery ] );

	const handleKeysQueryChange = useCallback( ( value ) => {
		const newValue = value || '';
		keysQueryRef.current = newValue;
		setKeysQuery( newValue );
	}, [] );

	const resolvedIndexName = useMemo( () => {
		if ( indexNameOverride ) {
			return String( indexNameOverride ).trim();
		}
		if ( ! baseIndexName ) {
			return '';
		}
		return `${ baseIndexName }_${ selectedPostType || 'post' }`;
	}, [ indexNameOverride, baseIndexName, selectedPostType ] );

	const sortOptions = useMemo( () => {
		const options = [ { label: __( 'Relevance', 'wlc-search-integration-with-algolia' ), value: 'relevance' } ];

		if ( selectedPostType === 'product' ) {
			options.push( { label: __( 'Price: High to Low', 'wlc-search-integration-with-algolia' ), value: 'price_desc' } );
			options.push( { label: __( 'Price: Low to High', 'wlc-search-integration-with-algolia' ), value: 'price_asc' } );
			options.push( { label: __( 'Newest', 'wlc-search-integration-with-algolia' ), value: 'newest' } );
		} else {
			options.push( { label: __( 'Alphabetical: A to Z', 'wlc-search-integration-with-algolia' ), value: 'title_asc' } );
			options.push( { label: __( 'Alphabetical: Z to A', 'wlc-search-integration-with-algolia' ), value: 'title_desc' } );
			options.push( { label: __( 'Newest', 'wlc-search-integration-with-algolia' ), value: 'newest' } );
			options.push( { label: __( 'Oldest', 'wlc-search-integration-with-algolia' ), value: 'oldest' } );
		}

		return options;
	}, [ selectedPostType ] );

	useEffect( () => {
		if ( ! showSort ) return;
		if ( ! indicesLoaded || ! resolvedIndexName ) return;
		const values = sortOptions.map( ( option ) => option.value );
		if ( ! values.includes( sortDefault || 'relevance' ) ) {
			setAttributes( { sortDefault: 'relevance' } );
		}
	}, [ showSort, indicesLoaded, resolvedIndexName, sortOptions, sortDefault, setAttributes ] );

	useEffect( () => {
		const normalized = normalizePaginationMaxPages( paginationMaxPages );
		if ( normalized !== paginationMaxPages ) {
			setAttributes( { paginationMaxPages: normalized } );
		}
	}, [ paginationMaxPages, normalizePaginationMaxPages, setAttributes ] );

	useEffect( () => {
		const normalized = normalizeGridColumns( gridColumns );
		if ( normalized !== gridColumns ) {
			setAttributes( { gridColumns: normalized } );
		}
	}, [ gridColumns, normalizeGridColumns, setAttributes ] );

	// Insert field block helper
	function insertFieldBlock( path ) {
		const p = String( path || '' ).trim();
		if ( ! p ) return;
		const label = p.split( '.' ).slice( -1 )[ 0 ] || p;
		const block = createBlock( 'wlc-algolia/result-field', { fieldPath: p, label } );
		const selectedBlockClientId = select( 'core/block-editor' ).getSelectedBlockClientId();
		const index = selectedBlockClientId
			? select( 'core/block-editor' ).getBlockIndex( selectedBlockClientId, clientId )
			: -1;
		dispatch( 'core/block-editor' ).insertBlocks( block, index >= 0 ? index + 1 : undefined, clientId );
	}

	function removeTemplateBlock( blockClientId ) {
		if ( ! blockClientId ) return;
		dispatch( 'core/block-editor' ).removeBlocks( blockClientId, false );
	}

	function moveTemplateBlock( blockClientId, direction ) {
		if ( ! blockClientId || ! direction ) return;
		const blocks = select( 'core/block-editor' ).getBlock( clientId )?.innerBlocks || [];
		const fromIndex = blocks.findIndex( ( b ) => b.clientId === blockClientId );
		if ( fromIndex < 0 ) return;
		if ( blocks[ fromIndex ]?.name === 'wlc-algolia/result-image' ) return;
		const toIndex = direction === 'up' ? fromIndex - 1 : fromIndex + 1;
		if ( toIndex < 0 || toIndex >= blocks.length ) return;
		dispatch( 'core/block-editor' ).moveBlocksToPosition( [ blockClientId ], clientId, clientId, toIndex );
	}

	function selectTemplateBlock( blockClientId ) {
		if ( ! blockClientId ) return;
		dispatch( 'core/block-editor' ).selectBlock( blockClientId );
	}

	function getTemplateBlockTitle( block ) {
		if ( ! block?.name ) return __( 'Block', 'wlc-search-integration-with-algolia' );
		const blockName = String( block.name );
		if ( blockName === 'wlc-algolia/result-title' ) return __( 'Title', 'wlc-search-integration-with-algolia' );
		if ( blockName === 'wlc-algolia/result-image' ) return __( 'Image', 'wlc-search-integration-with-algolia' );
		if ( blockName === 'wlc-algolia/result-excerpt' ) return __( 'Excerpt', 'wlc-search-integration-with-algolia' );
		if ( blockName === 'wlc-algolia/result-meta' ) return __( 'Meta', 'wlc-search-integration-with-algolia' );
		if ( blockName === 'wlc-algolia/result-field' ) return __( 'Field', 'wlc-search-integration-with-algolia' );
		if ( blockName === 'wlc-algolia/result-button' ) return __( 'Button', 'wlc-search-integration-with-algolia' );
		return blockName.replace( /^wlc-algolia\//, '' );
	}

	function getTemplateBlockMeta( block ) {
		if ( ! block?.attributes ) return '';
		if ( block.name === 'wlc-algolia/result-field' ) {
			return block.attributes.fieldPath || '';
		}
		if ( block.name === 'wlc-algolia/result-title' ) {
			return block.attributes.fieldPath || 'post_title';
		}
		if ( block.name === 'wlc-algolia/result-image' ) {
			return block.attributes.fieldPath || 'images.thumbnail.url';
		}
		if ( block.name === 'wlc-algolia/result-button' ) {
			return block.attributes.label || '';
		}
	if ( block.name === 'wlc-algolia/result-meta' ) {
		const parts = [];
		if ( block.attributes.metaDate !== false ) parts.push( 'Date' );
		if ( block.attributes.metaAuthor !== false ) parts.push( 'Author' );
		return parts.join( ' + ' );
	}
	if ( block.name === 'wlc-algolia/result-excerpt' ) {
		return block.attributes.fieldPath || 'post_excerpt';
	}
		return '';
	}

	function toggleFacet( attr, label, enabled ) {
		const next = Array.isArray( facetsSelected ) ? [ ...facetsSelected ] : [];
		const cleanAttr = String( attr || '' ).trim();
		if ( ! cleanAttr ) return;
		const idx = next.indexOf( cleanAttr );
		if ( enabled && idx === -1 ) next.push( cleanAttr );
		if ( ! enabled && idx !== -1 ) next.splice( idx, 1 );

		const nextLabels = { ...( facetLabels || {} ) };
		if ( enabled && ! nextLabels[ cleanAttr ] ) nextLabels[ cleanAttr ] = String( label || cleanAttr );
		setAttributes( { facetsSelected: next, facetLabels: nextLabels } );
	}

	function handleFacetDragEnd( result ) {
		if ( ! result.destination ) return;

		const items = Array.from( facetsSelected || [] );
		const [ reorderedItem ] = items.splice( result.source.index, 1 );
		items.splice( result.destination.index, 0, reorderedItem );

		setAttributes( { facetsSelected: items } );
	}

	function removeFacet( attr ) {
		const next = Array.isArray( facetsSelected ) ? [ ...facetsSelected ] : [];
		const idx = next.indexOf( attr );
		if ( idx !== -1 ) {
			next.splice( idx, 1 );
			const nextLabels = { ...( facetLabels || {} ) };
			delete nextLabels[ attr ];
			setAttributes( { facetsSelected: next, facetLabels: nextLabels } );
		}
	}

	function updateFacetLabel( attr, newLabel ) {
		const nextLabels = { ...( facetLabels || {} ) };
		nextLabels[ attr ] = String( newLabel || attr );
		setAttributes( { facetLabels: nextLabels } );
	}

	// Get selected facets with their labels in order
	const selectedFacetsOrdered = useMemo( () => {
		if ( ! Array.isArray( facetsSelected ) || facetsSelected.length === 0 ) return [];
		return facetsSelected.map( ( attr ) => {
			const facet = availableFacets.find( ( f ) => f.value === attr );
			return {
				attribute: attr,
				label: facetLabels[ attr ] || facet?.label || attr,
				originalLabel: facet?.label || attr,
			};
		} );
	}, [ facetsSelected, availableFacets, facetLabels ] );

	// Generate preview URL when showPreview is enabled
	useEffect( () => {
		if ( ! showPreview ) {
			setPreviewUrl( '' );
			return;
		}

		// Build preview URL - use frontend URL with preview parameter
		// Get the frontend URL by removing wp-admin path
		const currentUrl = window.location.href;
		const frontendUrl = currentUrl.replace( /\/wp-admin\/.*$/, '' ).replace( /\/post\.php.*$/, '' ).replace( /\/post-new\.php.*$/, '' );
		const url = frontendUrl + '/?algolia-preview=1&block-id=' + encodeURIComponent( clientId );
		setPreviewUrl( url );
	}, [ showPreview, clientId ] );

	return (
		<>
			<InspectorControls>
				<PanelBody title={ __( 'Preview', 'wlc-search-integration-with-algolia' ) } initialOpen={ false }>
					<ToggleControl
						label={ __( 'Show live preview', 'wlc-search-integration-with-algolia' ) }
						checked={ showPreview }
						onChange={ setShowPreview }
						help={ __( 'Preview the search page as it will appear on the frontend. This may take a moment to load.', 'wlc-search-integration-with-algolia' ) }
					/>
					{ showPreview && (
						<div style={ { marginTop: 12, padding: 12, background: '#f0f0f0', borderRadius: 4, fontSize: 12 } }>
							<strong>{ __( 'Note:', 'wlc-search-integration-with-algolia' ) }</strong>{ ' ' }
							{ __( 'If filters show "No values", you may need to update Algolia index settings. Go to Algolia settings and click "Update Faceting Settings" for your post type.', 'wlc-search-integration-with-algolia' ) }
						</div>
					) }
				</PanelBody>

				<PanelBody title={ __( 'Content', 'wlc-search-integration-with-algolia' ) } initialOpen={ true }>
					<SelectControl
						label={ __( 'Post type', 'wlc-search-integration-with-algolia' ) }
						value={ selectedPostType }
						options={ postTypeOptions }
						onChange={ ( v ) => {
							setAttributes( { selectedPostType: v } );
							replaceTemplateBlocks( v );
						} }
					/>
					<TextControl
						label={ __( 'Search placeholder', 'wlc-search-integration-with-algolia' ) }
						value={ placeholder }
						onChange={ ( v ) => setAttributes( { placeholder: v } ) }
					/>
					<TextControl
						label={ __( 'Results per page', 'wlc-search-integration-with-algolia' ) }
						type="number"
						min={ 1 }
						max={ 100 }
						value={ hitsPerPage }
						onChange={ ( v ) => setAttributes( { hitsPerPage: parseInt( v || '10', 10 ) || 10 } ) }
					/>
					<TextControl
						label={ __( 'Index name override', 'wlc-search-integration-with-algolia' ) }
						help={ __( 'Optional: Override the default index name pattern. Leave empty to use {base}_{postType}.', 'wlc-search-integration-with-algolia' ) }
						value={ indexNameOverride }
						onChange={ ( v ) => setAttributes( { indexNameOverride: v } ) }
					/>
				</PanelBody>

				<PanelBody title={ __( 'Display', 'wlc-search-integration-with-algolia' ) } initialOpen={ true }>
					<SelectControl
						label={ __( 'Layout', 'wlc-search-integration-with-algolia' ) }
						value={ viewMode }
						options={ [
							{ label: __( 'List', 'wlc-search-integration-with-algolia' ), value: 'list' },
							{ label: __( 'Grid', 'wlc-search-integration-with-algolia' ), value: 'grid' },
						] }
						onChange={ ( v ) => setAttributes( { viewMode: v } ) }
					/>
					{ viewMode === 'grid' && (
						<RangeControl
							label={ __( 'Columns', 'wlc-search-integration-with-algolia' ) }
							min={ 2 }
							max={ 4 }
							value={ gridColumns }
							onChange={ ( v ) => setAttributes( { gridColumns: normalizeGridColumns( v ) } ) }
						/>
					) }
					<RangeControl
						label={ __( 'Gap', 'wlc-search-integration-with-algolia' ) }
						min={ 8 }
						max={ 40 }
						value={ gap }
						onChange={ ( v ) => setAttributes( { gap: v || 16 } ) }
					/>
					<div style={ { marginTop: 12 } }>
						<div style={ { marginBottom: 8, fontWeight: 600 } }>{ __( 'Accent color', 'wlc-search-integration-with-algolia' ) }</div>
						<ColorPalette
							value={ accentColor }
							onChange={ ( v ) => setAttributes( { accentColor: v || '#DB002F' } ) }
						/>
					</div>
					<ToggleControl
						label={ __( 'Show results count', 'wlc-search-integration-with-algolia' ) }
						checked={ !! showResultsCount }
						onChange={ ( v ) => setAttributes( { showResultsCount: !! v } ) }
					/>
				</PanelBody>

				<PanelBody title={ __( 'Filters', 'wlc-search-integration-with-algolia' ) } initialOpen={ false }>
					<ToggleControl
						label={ __( 'Show filters sidebar', 'wlc-search-integration-with-algolia' ) }
						checked={ !! showFilters }
						onChange={ ( v ) => setAttributes( { showFilters: !! v } ) }
					/>
					{ showFilters && (
						<>
							{ facetsError && <Notice status="error" isDismissible={ false }>{ facetsError }</Notice> }
							<div style={ { marginTop: 12, marginBottom: 8, fontWeight: 600 } }>
								{ __( 'Available facets', 'wlc-search-integration-with-algolia' ) }
							</div>
							<div style={ { fontSize: 12, color: '#757575', marginBottom: 12 } }>
								{ facetsLoading
									? __( 'Loading facets…', 'wlc-search-integration-with-algolia' )
									: __( 'Select which facets to display in the filters sidebar.', 'wlc-search-integration-with-algolia' ) }
							</div>
							<div
								style={ {
									maxHeight: 240,
									overflowY: 'auto',
									border: '1px solid #ddd',
									borderRadius: 4,
									padding: 8,
									background: '#f9f9f9',
								} }
							>
								{ ( availableFacets || [] ).map( ( f ) => {
									const value = f?.value;
									const label = f?.label || value;
									const checked = Array.isArray( facetsSelected ) ? facetsSelected.includes( value ) : false;
									return (
										<CheckboxControl
											key={ value }
											label={ label }
											checked={ checked }
											onChange={ ( v ) => toggleFacet( value, label, v ) }
										/>
									);
								} ) }
								{ ! facetsLoading && ! facetsError && ( availableFacets || [] ).length === 0 && (
									<div style={ { fontSize: 12, color: '#757575', padding: '8px 0' } }>
										{ __( 'No facets available. Enable "Facet" for fields in CPT settings.', 'wlc-search-integration-with-algolia' ) }
									</div>
								) }
							</div>
							<ToggleControl
								label={ __( 'Show facet counts', 'wlc-search-integration-with-algolia' ) }
								checked={ showFacetCounts !== false }
								onChange={ ( v ) => setAttributes( { showFacetCounts: !! v } ) }
							/>
							<SelectControl
								label={ __( 'Count style', 'wlc-search-integration-with-algolia' ) }
								value={ facetCountStyle || 'paren' }
								options={ [
									{ label: __( '(123)', 'wlc-search-integration-with-algolia' ), value: 'paren' },
									{ label: __( '123', 'wlc-search-integration-with-algolia' ), value: 'plain' },
								] }
								onChange={ ( v ) => setAttributes( { facetCountStyle: v } ) }
							/>
							<ToggleControl
								label={ __( 'Show active filters', 'wlc-search-integration-with-algolia' ) }
								checked={ showActiveFilters !== false }
								onChange={ ( v ) => setAttributes( { showActiveFilters: !! v } ) }
							/>
							<ToggleControl
								label={ __( 'Enable facet search', 'wlc-search-integration-with-algolia' ) }
								checked={ enableFacetSearch !== false }
								onChange={ ( v ) => setAttributes( { enableFacetSearch: !! v } ) }
							/>
							<ToggleControl
								label={ __( 'Sticky filters', 'wlc-search-integration-with-algolia' ) }
								checked={ stickyFilters !== false }
								onChange={ ( v ) => setAttributes( { stickyFilters: !! v } ) }
							/>
						</>
					) }
				</PanelBody>

				<PanelBody title={ __( 'Pagination', 'wlc-search-integration-with-algolia' ) } initialOpen={ false }>
					<ToggleControl
						label={ __( 'Show pagination', 'wlc-search-integration-with-algolia' ) }
						checked={ !! showPagination }
						onChange={ ( v ) => setAttributes( { showPagination: !! v } ) }
					/>
					{ showPagination && (
						<>
							<SelectControl
								label={ __( 'Pagination style', 'wlc-search-integration-with-algolia' ) }
								value={ paginationMode }
								options={ [
									{ label: __( 'Simple (Prev/Next)', 'wlc-search-integration-with-algolia' ), value: 'simple' },
									{ label: __( 'Page numbers', 'wlc-search-integration-with-algolia' ), value: 'numbers' },
								] }
								onChange={ ( v ) => setAttributes( { paginationMode: v } ) }
							/>
							{ paginationMode === 'numbers' && (
								<RangeControl
									label={ __( 'Max pages to show', 'wlc-search-integration-with-algolia' ) }
									min={ 3 }
									max={ 19 }
									step={ 2 }
									value={ paginationMaxPages }
									help={ __( 'Only odd values are allowed to keep pagination centered (e.g. 7, 9, 11).', 'wlc-search-integration-with-algolia' ) }
									onChange={ ( v ) =>
										setAttributes( {
											paginationMaxPages: normalizePaginationMaxPages( v ),
										} )
									}
								/>
							) }
						</>
					) }
				</PanelBody>

				<PanelBody title={ __( 'Advanced', 'wlc-search-integration-with-algolia' ) } initialOpen={ false }>
					<ToggleControl
						label={ __( 'Show sort options', 'wlc-search-integration-with-algolia' ) }
						checked={ showSort !== false }
						onChange={ ( v ) => setAttributes( { showSort: !! v } ) }
					/>
					{ showSort && (
						<SelectControl
							label={ __( 'Default sort', 'wlc-search-integration-with-algolia' ) }
							value={ sortDefault || 'relevance' }
							options={ sortOptions }
							onChange={ ( v ) => setAttributes( { sortDefault: v } ) }
						/>
					) }
					<ToggleControl
						label={ __( 'URL sync', 'wlc-search-integration-with-algolia' ) }
						help={ __( 'Synchronize search query and filters with URL parameters.', 'wlc-search-integration-with-algolia' ) }
						checked={ enableUrlSync !== false }
						onChange={ ( v ) => setAttributes( { enableUrlSync: !! v } ) }
					/>
				</PanelBody>
			</InspectorControls>

			<div { ...useBlockProps() }>
				{ showPreview && previewUrl ? (
					<div className="wp-block-wlc-algolia-search-page__preview-wrapper">
						<div className="wp-block-wlc-algolia-search-page__preview-header">
							<h3>{ __( 'Live Preview', 'wlc-search-integration-with-algolia' ) }</h3>
							<Button
								variant="secondary"
								isSmall
								onClick={ () => setShowPreview( false ) }
							>
								{ __( 'Close Preview', 'wlc-search-integration-with-algolia' ) }
							</Button>
						</div>
						<iframe
							src={ previewUrl }
							className="wp-block-wlc-algolia-search-page__preview-iframe"
							title={ __( 'Search page preview', 'wlc-search-integration-with-algolia' ) }
						/>
					</div>
				) : (
					<div className="wp-block-wlc-algolia-search-page-v2__editor-wrapper">
					<div className="wp-block-wlc-algolia-search-page-v2__editor-header">
						<div>
							<h3 className="wp-block-wlc-algolia-search-page-v2__editor-title">
								{ __( 'Result Template', 'wlc-search-integration-with-algolia' ) }
							</h3>
							<p className="wp-block-wlc-algolia-search-page-v2__editor-description">
								{ __(
									'Build your search result template by adding blocks below. Each block maps to an Algolia field or UI element.',
									'wlc-search-integration-with-algolia'
								) }
							</p>
						</div>
						<div className="wp-block-wlc-algolia-search-page-v2__editor-post-type">
							<span>{ __( 'Post type:', 'wlc-search-integration-with-algolia' ) }</span>
							<strong>{ selectedPostType }</strong>
						</div>
					</div>

					<div
						className={ `wp-block-wlc-algolia-search-page-v2__editor-layout ${
							showFilters ? 'has-filters-sidebar' : ''
						}` }
					>
						{ showFilters && (
							<div className="wp-block-wlc-algolia-search-page-v2__editor-panel">
								<h4 className="wp-block-wlc-algolia-search-page-v2__editor-panel-title">
									{ __( 'Filters Sidebar', 'wlc-search-integration-with-algolia' ) }
								</h4>
								<div className="wp-block-wlc-algolia-search-page-v2__editor-hint">
									{ __( 'Drag to reorder filters. The order here determines the order in the filters sidebar.', 'wlc-search-integration-with-algolia' ) }
								</div>
								{ selectedFacetsOrdered.length > 0 ? (
									<DragDropContext onDragEnd={ handleFacetDragEnd }>
										<Droppable droppableId="facets-list">
											{ ( provided, snapshot ) => (
												<div
													{ ...provided.droppableProps }
													ref={ provided.innerRef }
													className={ `wp-block-wlc-algolia-search-page-v2__editor-facets-list ${ snapshot.isDraggingOver ? 'is-dragging-over' : '' }` }
												>
													{ selectedFacetsOrdered.map( ( facet, index ) => (
														<Draggable key={ facet.attribute } draggableId={ facet.attribute } index={ index }>
															{ ( provided, snapshot ) => (
																<div
																	ref={ provided.innerRef }
																	{ ...provided.draggableProps }
																	className={ `wp-block-wlc-algolia-search-page-v2__editor-facet-item ${ snapshot.isDragging ? 'is-dragging' : '' }` }
																>
																	<div className="wp-block-wlc-algolia-search-page-v2__editor-facet-handle" { ...provided.dragHandleProps }>
																		<Icon icon="move" />
																	</div>
																	<div className="wp-block-wlc-algolia-search-page-v2__editor-facet-content">
																		<TextControl
																			value={ facet.label }
																			onChange={ ( v ) => updateFacetLabel( facet.attribute, v ) }
																			placeholder={ facet.originalLabel }
																		/>
																		<div className="wp-block-wlc-algolia-search-page-v2__editor-facet-attribute">
																			{ facet.attribute }
																		</div>
																	</div>
																	<Button
																		variant="tertiary"
																		isDestructive
																		isSmall
																		onClick={ () => removeFacet( facet.attribute ) }
																		icon="trash"
																		label={ __( 'Remove filter', 'wlc-search-integration-with-algolia' ) }
																	/>
																</div>
															) }
														</Draggable>
													) ) }
													{ provided.placeholder }
												</div>
											) }
										</Droppable>
									</DragDropContext>
								) : (
									<div className="wp-block-wlc-algolia-search-page-v2__editor-empty-state">
										<p>{ __( 'No filters selected. Select filters from the panel on the right.', 'wlc-search-integration-with-algolia' ) }</p>
									</div>
								) }
							</div>
						) }

						<div className="wp-block-wlc-algolia-search-page-v2__editor-panel">
							<h4 className="wp-block-wlc-algolia-search-page-v2__editor-panel-title">
								{ __( 'Available Fields', 'wlc-search-integration-with-algolia' ) }
							</h4>
							<div className="wp-block-wlc-algolia-search-page-v2__editor-search">
								<input
									type="search"
									className="wp-block-wlc-algolia-search-page-v2__editor-search-input"
									placeholder={ __( 'Search fields…', 'wlc-search-integration-with-algolia' ) }
									value={ String( keysQuery || '' ) }
									onChange={ ( e ) => handleKeysQueryChange( e.target.value ) }
								/>
							</div>
							{ keysError && (
								<Notice status="error" isDismissible={ false }>
									{ keysError }
								</Notice>
							) }
							<div className="wp-block-wlc-algolia-search-page-v2__editor-hint">
								{ keysLoading
									? __( 'Loading fields…', 'wlc-search-integration-with-algolia' )
									: __( 'Click "Add" to insert a Result Field block into your template.', 'wlc-search-integration-with-algolia' ) }
							</div>
							<div className="wp-block-wlc-algolia-search-page-v2__editor-field-list">
								{ filteredKeys.map( ( k ) => (
									<div key={ k.path } className="wp-block-wlc-algolia-search-page-v2__editor-field-item">
										<div className="wp-block-wlc-algolia-search-page-v2__editor-field-info">
											<div className="wp-block-wlc-algolia-search-page-v2__editor-field-path">{ k.path }</div>
											{ k.sample !== undefined && (
												<div className="wp-block-wlc-algolia-search-page-v2__editor-field-sample">
													{ String( k.sample ) }
												</div>
											) }
										</div>
										<Button variant="secondary" isSmall onClick={ () => insertFieldBlock( k.path ) }>
											{ __( 'Add', 'wlc-search-integration-with-algolia' ) }
										</Button>
									</div>
								) ) }
							</div>
						</div>

						<div className="wp-block-wlc-algolia-search-page-v2__editor-panel">
							<h4 className="wp-block-wlc-algolia-search-page-v2__editor-panel-title">
								{ __( 'Template Blocks', 'wlc-search-integration-with-algolia' ) }
							</h4>
							<div className="wp-block-wlc-algolia-search-page-v2__editor-hint">
								{ __(
									'Use arrows to reorder blocks. Image is always pinned to the first position (but can be removed).',
									'wlc-search-integration-with-algolia'
								) }
							</div>
							{ innerBlocks.length > 0 && (
								<div className="wp-block-wlc-algolia-search-page-v2__editor-template-list">
									{ innerBlocks.map( ( block, index ) => (
										<div
											key={ block.clientId }
											className={ `wp-block-wlc-algolia-search-page-v2__editor-template-item ${
												selectedBlockClientId === block.clientId ? 'is-selected' : ''
											}` }
											role="button"
											tabIndex={ 0 }
											onClick={ () => selectTemplateBlock( block.clientId ) }
											onKeyDown={ ( event ) => {
												if ( event.key === 'Enter' || event.key === ' ' ) {
													event.preventDefault();
													selectTemplateBlock( block.clientId );
												}
											} }
										>
											<div className="wp-block-wlc-algolia-search-page-v2__editor-template-item-info">
												<div className="wp-block-wlc-algolia-search-page-v2__editor-template-item-title">
													{ index + 1 }. { getTemplateBlockTitle( block ) }
												</div>
												{ !! getTemplateBlockMeta( block ) && (
													<div className="wp-block-wlc-algolia-search-page-v2__editor-template-item-meta">
														{ getTemplateBlockMeta( block ) }
													</div>
												) }
											</div>
											<div className="wp-block-wlc-algolia-search-page-v2__editor-template-item-actions">
												<Button
													variant="secondary"
													isSmall
													disabled={ index === 0 || block.name === 'wlc-algolia/result-image' }
													onClick={ ( event ) => {
														event.stopPropagation();
														moveTemplateBlock( block.clientId, 'up' );
													} }
												>
													{ __( 'Up', 'wlc-search-integration-with-algolia' ) }
												</Button>
												<Button
													variant="secondary"
													isSmall
													disabled={ index === innerBlocks.length - 1 || block.name === 'wlc-algolia/result-image' }
													onClick={ ( event ) => {
														event.stopPropagation();
														moveTemplateBlock( block.clientId, 'down' );
													} }
												>
													{ __( 'Down', 'wlc-search-integration-with-algolia' ) }
												</Button>
												<Button
													variant="tertiary"
													isDestructive
													isSmall
													onClick={ ( event ) => {
														event.stopPropagation();
														removeTemplateBlock( block.clientId );
													} }
												>
													{ __( 'Remove', 'wlc-search-integration-with-algolia' ) }
												</Button>
											</div>
										</div>
									) ) }
								</div>
							) }
							<div className="wp-block-wlc-algolia-search-page-v2__editor-template">
								<InnerBlocks allowedBlocks={ ALLOWED_INNER_BLOCKS } renderAppender={ InnerBlocks.ButtonBlockAppender } />
							</div>
						</div>
					</div>
				</div>
				) }
			</div>
		</>
	);
}
