import { useState, useMemo, useEffect } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import {
	Button,
	Flex,
	FlexItem,
	SearchControl,
	TextHighlight,
	Composite,
	__experimentalText as WCText,
	__experimentalVStack as VStack,
} from '@wordpress/components';
import { useEntityRecords } from '@wordpress/core-data';
import { decodeEntities } from '@wordpress/html-entities';
import { useDebouncedInput } from '@wordpress/compose';
import { focus } from '@wordpress/dom';
import { safeDecodeURI } from '@wordpress/url';
import { mapToIHasNameAndId } from './utils';

const EMPTY_ARRAY = [];

function SuggestionListItem( {
	suggestion,
	search,
	onSelect,
	entityForSuggestions,
} ) {
	const baseCssClass =
		'edit-site-custom-template-modal__suggestions_list__list-item';
	return (
		<Composite.Item
			render={
				<Button
					__next40pxDefaultSize
					role="option"
					className={ baseCssClass }
					onClick={ () =>
						onSelect(
							entityForSuggestions.config.getSpecificTemplate(
								suggestion
							)
						)
					}
				/>
			}
		>
			<WCText
				size="body"
				lineHeight={ 1.53846153846 } // 20px
				weight="var(--wpds-typography-font-weight-emphasis)"
				className={ `${ baseCssClass }__title` }
			>
				<TextHighlight
					text={ decodeEntities( suggestion.name ) }
					highlight={ search }
				/>
			</WCText>
			{ suggestion.link && (
				<WCText
					size="body"
					lineHeight={ 1.53846153846 } // 20px
					className={ `${ baseCssClass }__info` }
				>
					{ safeDecodeURI( suggestion.link ) }
				</WCText>
			) }
		</Composite.Item>
	);
}

function useSearchSuggestions( entityForSuggestions, search ) {
	const { config } = entityForSuggestions;
	const query = useMemo(
		() => ( {
			order: 'asc',
			context: 'view',
			search,
			per_page: search ? 20 : 10,
			...config.queryArgs( search ),
		} ),
		[ search, config ]
	);
	const { records: searchResults, hasResolved: searchHasResolved } =
		useEntityRecords(
			entityForSuggestions.type,
			entityForSuggestions.slug,
			query
		);
	const [ suggestions, setSuggestions ] = useState( EMPTY_ARRAY );
	useEffect( () => {
		if ( ! searchHasResolved ) {
			return;
		}
		let newSuggestions = EMPTY_ARRAY;
		if ( searchResults?.length ) {
			newSuggestions = searchResults;
			if ( config.recordNamePath ) {
				newSuggestions = mapToIHasNameAndId(
					newSuggestions,
					config.recordNamePath
				);
			}
		}
		// Update suggestions only when the query has resolved, so as to keep
		// the previous results in the UI.
		setSuggestions( newSuggestions );
	}, [ searchResults, searchHasResolved ] );
	return suggestions;
}

function SuggestionList( { entityForSuggestions, onSelect } ) {
	const [ search, setSearch, debouncedSearch ] = useDebouncedInput();
	const suggestions = useSearchSuggestions(
		entityForSuggestions,
		debouncedSearch
	);
	const { labels } = entityForSuggestions;
	const [ showSearchControl, setShowSearchControl ] = useState( false );
	if ( ! showSearchControl && suggestions?.length > 9 ) {
		setShowSearchControl( true );
	}
	return (
		<>
			{ showSearchControl && (
				<SearchControl
					onChange={ setSearch }
					value={ search }
					label={ labels.search_items }
					placeholder={ labels.search_items }
				/>
			) }
			{ !! suggestions?.length && (
				<Composite
					orientation="vertical"
					role="listbox"
					className="edit-site-custom-template-modal__suggestions_list"
					aria-label={ __( 'Suggestions list' ) }
				>
					{ suggestions.map( ( suggestion ) => (
						<SuggestionListItem
							key={ suggestion.slug }
							suggestion={ suggestion }
							search={ debouncedSearch }
							onSelect={ onSelect }
							entityForSuggestions={ entityForSuggestions }
						/>
					) ) }
				</Composite>
			) }
			{ debouncedSearch && ! suggestions?.length && (
				<WCText
					as="p"
					className="edit-site-custom-template-modal__no-results"
				>
					{ labels.not_found }
				</WCText>
			) }
		</>
	);
}

function AddCustomTemplateModalContent( {
	onSelect,
	entityForSuggestions,
	onBack,
	containerRef,
} ) {
	const [ showSearchEntities, setShowSearchEntities ] = useState(
		entityForSuggestions.hasGeneralTemplate
	);

	// Focus on the first focusable element when the modal opens.
	// We handle focus management in the parent modal, just need to focus on the first focusable element.
	useEffect( () => {
		if ( containerRef.current ) {
			const [ firstFocusable ] = focus.focusable.find(
				containerRef.current
			);
			firstFocusable?.focus();
		}
	}, [ showSearchEntities ] );

	return (
		<VStack
			spacing={ 4 }
			className="edit-site-custom-template-modal__contents-wrapper"
			alignment="left"
		>
			{ ! showSearchEntities && (
				<>
					<WCText as="p">
						{ __(
							'Select whether to create a single template for all items or a specific one.'
						) }
					</WCText>
					<Flex
						className="edit-site-custom-template-modal__contents"
						gap="4"
						align="initial"
					>
						<FlexItem
							isBlock
							as={ Button }
							onClick={ () => {
								const {
									slug,
									title,
									description,
									templatePrefix,
								} = entityForSuggestions.template;
								onSelect( {
									slug,
									title,
									description,
									templatePrefix,
								} );
							} }
						>
							<WCText
								as="span"
								weight="var(--wpds-typography-font-weight-emphasis)"
								lineHeight={ 1.53846153846 } // 20px
							>
								{ entityForSuggestions.labels.all_items }
							</WCText>
							<WCText
								as="span"
								lineHeight={ 1.53846153846 } // 20px
							>
								{
									// translators: The user is given the choice to set up a template for all items of a post type or taxonomy, or just a specific one.
									__( 'For all items' )
								}
							</WCText>
						</FlexItem>
						<FlexItem
							isBlock
							as={ Button }
							onClick={ () => {
								setShowSearchEntities( true );
							} }
						>
							<WCText
								as="span"
								weight="var(--wpds-typography-font-weight-emphasis)"
								lineHeight={ 1.53846153846 } // 20px
							>
								{ entityForSuggestions.labels.singular_name }
							</WCText>
							<WCText
								as="span"
								lineHeight={ 1.53846153846 } // 20px
							>
								{
									// translators: The user is given the choice to set up a template for all items of a post type or taxonomy, or just a specific one.
									__( 'For a specific item' )
								}
							</WCText>
						</FlexItem>
					</Flex>
					<Flex justify="right">
						<Button
							__next40pxDefaultSize
							variant="tertiary"
							onClick={ onBack }
						>
							{ __( 'Back' ) }
						</Button>
					</Flex>
				</>
			) }
			{ showSearchEntities && (
				<>
					<WCText as="p">
						{ __(
							'This template will be used only for the specific item chosen.'
						) }
					</WCText>
					<SuggestionList
						entityForSuggestions={ entityForSuggestions }
						onSelect={ onSelect }
					/>
					<Flex justify="right">
						<Button
							__next40pxDefaultSize
							variant="tertiary"
							onClick={ () => {
								// If general template exists, go directly back to main screen
								// instead of showing the choice screen
								if ( entityForSuggestions.hasGeneralTemplate ) {
									onBack();
								} else {
									setShowSearchEntities( false );
								}
							} }
						>
							{ __( 'Back' ) }
						</Button>
					</Flex>
				</>
			) }
		</VStack>
	);
}

export default AddCustomTemplateModalContent;
