/**
 * WordPress dependencies
 */
import {
	BaseControl,
	SelectControl,
	ToggleControl,
} from '@safe-wordpress/components';
import { useInstanceId } from '@safe-wordpress/compose';
import { _x } from '@safe-wordpress/i18n';

/**
 * External dependencies
 */
import clsx from 'clsx';
import { ErrorText, PostSearcher } from '@nab/components';
import type {
	AllProducts,
	CAEditProps,
	ProductId,
	ProductSelection,
	SelectedProductIds,
	SomeProducts,
} from '@nab/types';

/**
 * Internal dependencies
 */
import type { Attributes } from './types';

export const Edit = ( {
	attributes: attrs,
	setAttributes: setAttrs,
	errors,
}: CAEditProps< Attributes > ): JSX.Element => {
	const { value: attributes } = attrs;
	const setAttributes = ( value: ProductSelection ): void =>
		setAttrs( {
			type: 'product-selection',
			value,
		} );

	return (
		<>
			<ToggleControl
				label={ _x(
					'Customize order tracking based on purchased products.',
					'command',
					'nelio-ab-testing'
				) }
				checked={ attributes.type === 'some-products' }
				onChange={ ( any ) =>
					setAttributes( any ? SOME_PRODUCTS : ALL_PRODUCTS )
				}
			/>

			{ attributes.type === 'some-products' && (
				<ProductSelectionView
					value={ attributes.value }
					onChange={ ( value ) =>
						setAttributes( { type: 'some-products', value } )
					}
					errors={ errors }
				/>
			) }
		</>
	);
};

// ============
// HELPER VIEWS
// ============

const ProductSelectionView = ( {
	value,
	onChange,
	errors,
}: {
	readonly value: SomeProducts[ 'value' ];
	readonly onChange: ( value: SelectedProductIds ) => void;
	readonly errors: CAEditProps< Attributes >[ 'errors' ];
} ): JSX.Element | null => {
	const instanceId = useInstanceId( Edit );

	if ( 'product-ids' !== value.type ) {
		return null;
	}

	return (
		<>
			<BaseControl
				id={ `nab-conversion-action__wc-add-to-cart-${ instanceId }` }
				className={ clsx( {
					'nab-conversion-action__field--has-errors': errors.type,
				} ) }
				label={ <Label value={ value } onChange={ onChange } /> }
				help={ <ErrorText value={ errors.type } /> }
			>
				<PostSearcher
					id={ `nab-conversion-action__wc-add-to-cart-${ instanceId }` }
					type="product"
					perPage={ 10 }
					isMultiple={ true }
					value={ value.productIds }
					onChange={ ( newProductIds ) =>
						onChange( {
							...value,
							productIds:
								newProductIds as ReadonlyArray< ProductId >,
						} )
					}
				/>
			</BaseControl>
		</>
	);
};

const Label = ( {
	value,
	onChange,
}: {
	readonly value: SomeProducts[ 'value' ];
	readonly onChange: ( value: SelectedProductIds ) => void;
} ): JSX.Element | null => {
	if ( 'product-taxonomies' === value.type ) {
		return null;
	}

	const getValue = () => {
		if ( ! value.excluded ) {
			return 'included' as const;
		}
		if ( value.mode === 'and' ) {
			return 'excluded-product-set' as const;
		}
		return 'excluded-products' as const;
	};

	return (
		<SelectControl
			value={ getValue() }
			options={ [
				{
					value: 'included' as const,
					label: _x( 'Products', 'text', 'nelio-ab-testing' ),
				},
				{
					value: 'excluded-products' as const,
					label: _x(
						'Excluded Products',
						'text',
						'nelio-ab-testing'
					),
				},
				{
					value: 'excluded-product-set' as const,
					label: _x(
						'Excluded Product Set',
						'text',
						'nelio-ab-testing'
					),
				},
			] }
			onChange={ ( v ) =>
				onChange( {
					...value,
					excluded: 'included' === v ? undefined : true,
					mode: 'excluded-products' === v ? 'or' : 'and',
				} )
			}
		/>
	);
};

// =========
// CONSTANTS
// =========

const ALL_PRODUCTS: AllProducts = {
	type: 'all-products',
};

const SOME_PRODUCTS: SomeProducts = {
	type: 'some-products',
	value: {
		type: 'product-ids',
		mode: 'and',
		productIds: [],
	},
};
