/**
 * WordPress dependencies
 */
import { TextControl } from '@safe-wordpress/components';
import { useSelect } from '@safe-wordpress/data';
import { useEffect, useState } from '@safe-wordpress/element';
import { _x, sprintf } from '@safe-wordpress/i18n';

/**
 * External dependencies
 */
import { PresetAlternative } from '@nab/components';
import type { ExperimentEditProps, TemplateId } from '@nab/types';

// NOTE. Dependency loop with @nab package.
import type { store as editorStore } from '@nab/editor';
const NAB_EDITOR = 'nab/editor' as unknown as typeof editorStore;

/**
 * Internal dependencies
 */
import type { ControlAttributes, AlternativeAttributes } from '../types';
import {
	areBuiltInTemplateAttributes,
	arePageBuilderTemplateAttributes,
} from './original';

export const Alternative = ( {
	attributes: { templateId, name },
	disabled,
	experimentType,
	setAttributes,
}: ExperimentEditProps< AlternativeAttributes > ): JSX.Element => {
	const context = useContext();
	const { id: controlTemplate, name: controlTemplateName } =
		useControlTemplate();
	const [ prevControlTemplate, setControlPrevTemplate ] =
		useState( controlTemplate );

	useEffect( () => {
		if ( prevControlTemplate === controlTemplate ) {
			return;
		}
		setControlPrevTemplate( controlTemplate );

		if ( '_nab_front_page_template' === controlTemplate ) {
			setAttributes( {
				name: '',
				templateId: '',
			} );
		} else if (
			! templateId ||
			'_nab_front_page_template' === prevControlTemplate
		) {
			setAttributes( {
				name: controlTemplateName,
				templateId: controlTemplate,
			} );
		}
	}, [
		controlTemplate,
		prevControlTemplate,
		controlTemplateName,
		templateId,
		setAttributes,
	] );

	if ( '_nab_front_page_template' === controlTemplate ) {
		return (
			<TextControl
				placeholder={ sprintf(
					/* translators: %s: File name. */
					_x(
						'Type in the file name of your template… (e.g. %s)',
						'user',
						'nelio-ab-testing'
					),
					'front-page-b.php'
				) }
				value={ templateId ?? '' }
				onChange={ ( id ) =>
					setAttributes( {
						templateId: id as TemplateId,
						name: id,
					} )
				}
			/>
		);
	}

	return (
		<PresetAlternative
			experimentType={ experimentType }
			collection={ context }
			value={ templateId }
			onChange={ ( t ) =>
				t
					? setAttributes( {
							templateId: t.value as TemplateId,
							name: t.label,
					  } )
					: undefined
			}
			disabled={ disabled }
			exclusions={
				'wp:page' === context
					? [ '_nab_front_page_template' ]
					: undefined
			}
			labels={ {
				selection: name,
				selectAction: _x(
					'Please select a template…',
					'user',
					'nelio-ab-testing'
				),
				loading: _x( 'Loading templates…', 'text', 'nelio-ab-testing' ),
				empty: _x(
					'No templates available',
					'text',
					'nelio-ab-testing'
				),
				unknownOption: _x(
					'Template not found',
					'text',
					'nelio-ab-testing'
				),
			} }
		/>
	);
};

// =====
// HOOKS
// =====

const useContext = () =>
	useSelect( ( select ) => {
		const { getAlternative } = select( NAB_EDITOR );
		const control = getAlternative< ControlAttributes >( 'control' );

		if ( ! control?.attributes ) {
			return;
		}

		if ( areBuiltInTemplateAttributes( control.attributes ) ) {
			return `wp:${ control.attributes.postType }`;
		} else if ( arePageBuilderTemplateAttributes( control.attributes ) ) {
			return `${ control.attributes.builder }:${ control.attributes.context }`;
		}

		return undefined;
	}, [] );

const useControlTemplate = (): Readonly< { id: TemplateId; name: string } > => {
	const control = useSelect(
		( select ) =>
			select( NAB_EDITOR ).getAlternative< ControlAttributes >(
				'control'
			),
		[]
	);
	return {
		id: control?.attributes.templateId ?? '',
		name: control?.attributes.name ?? '',
	};
};
