/**
 * WordPress dependencies
 */
import { useDispatch, useSelect } from '@wordpress/data';
import { _x } from '@wordpress/i18n';

/**
 * External dependencies
 */
import { trim } from 'lodash';
import { ReusableEntitiesDialog } from '@nab/components';
import { store as NAB_DATA } from '@nab/data';
import type { Segment, ReusableSegment } from '@nab/types';

/**
 * Internal dependencies
 */
import { store as NAB_EDITOR } from '../../store';
import { createSegment, isDefined } from '@nab/utils';
import { createSegmentationRule } from '@nab/segmentation-rules';

export const ReusableSegmentDialog = (): JSX.Element | null => {
	const dialog = useReusableDialog();
	const { closeReusableDialog: onClose } = useDispatch( NAB_EDITOR );

	const {
		activeSegment,
		areThereSegmentationRules,
		currentSegments,
		isSaving,
		reusableSegments,
	} = useSelect(
		( select ) => ( {
			activeSegment: select( NAB_EDITOR ).getActiveSegment(),
			areThereSegmentationRules: select( NAB_EDITOR )
				.getSegments()
				.some(
					( s ) =>
						!! select( NAB_EDITOR ).getSegmentationRules( s.id )
							.length
				),
			currentSegments: select( NAB_EDITOR ).getSegments(),
			isSaving: select( NAB_DATA ).isSavingReusableEntities(),
			reusableSegments: select( NAB_DATA ).getReusableSegments(),
		} ),
		[]
	);
	const segmentationRules = useSelect(
		( select ) =>
			activeSegment?.id
				? select( NAB_EDITOR ).getSegmentationRules( activeSegment.id )
				: [],
		[ activeSegment ]
	);

	const { saveReusableSegments } = useDispatch( NAB_DATA );
	const {
		addSegmentationRulesIntoSegment,
		addSegments,
		removeSegments,
		setActiveSegment,
	} = useDispatch( NAB_EDITOR );

	const mustUseReplace =
		currentSegments.every( ( g ) => ! trim( g.attributes.name ) ) &&
		! areThereSegmentationRules;

	if ( 'manage-segments' === dialog ) {
		return (
			<ReusableEntitiesDialog< ReusableSegment >
				mode="manage"
				labels={ {
					title: _x(
						'Reusable Segments',
						'text',
						'nelio-ab-testing'
					),
					manageElements: _x(
						'Edit or delete the following reusable segments:',
						'user',
						'nelio-ab-testing'
					),
					replace: mustUseReplace
						? _x( 'Import', 'command', 'nelio-ab-testing' )
						: undefined,
					selectMultiple: _x(
						'Select one or more reusable segments:',
						'user',
						'nelio-ab-testing'
					),
				} }
				items={ reusableSegments }
				saving={ isSaving }
				onAdd={
					mustUseReplace
						? undefined
						: ( selection ) => {
								const newSegments = selection.map( segmentify );
								void addSegments( newSegments );
								newSegments.forEach(
									( s ) =>
										void addSegmentationRulesIntoSegment(
											s.id,
											s.segmentationRules
										)
								);
								if ( newSegments[ 0 ] ) {
									void setActiveSegment(
										newSegments[ 0 ].id
									);
								}
						  }
				}
				onReplace={ ( selection ) => {
					void removeSegments( currentSegments.map( ( g ) => g.id ) );
					const newSegments = selection.map( segmentify );
					void addSegments( newSegments );
					if ( newSegments[ 0 ] ) {
						void setActiveSegment( newSegments[ 0 ].id );
					}
					newSegments.forEach( ( s ) =>
						addSegmentationRulesIntoSegment(
							s.id,
							s.segmentationRules
						)
					);
				} }
				onSave={ saveReusableSegments }
				onClose={ onClose }
			/>
		);
	}

	if ( activeSegment && 'save-segment' === dialog ) {
		return (
			<ReusableEntitiesDialog< ReusableSegment >
				mode="save"
				labels={ {
					title: _x(
						'Reusable Segments',
						'text',
						'nelio-ab-testing'
					),
					collectionName: _x(
						'Reusable Segments',
						'text',
						'nelio-ab-testing'
					),
					nameField: _x( 'Name', 'text', 'nelio-ab-testing' ),
					newItemOption: _x(
						'New Reusable Segment',
						'text',
						'nelio-ab-testing'
					),
				} }
				item={ { ...activeSegment, segmentationRules } }
				items={ reusableSegments }
				saving={ isSaving }
				onSave={ saveReusableSegments }
				onClose={ onClose }
			/>
		);
	}

	return null;
};

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

const useReusableDialog = () =>
	useSelect( ( select ) => select( NAB_EDITOR ).getReusableDialog(), [] );

const segmentify = ( rs: ReusableSegment ): Segment => ( {
	...createSegment(),
	attributes: rs.attributes,
	segmentationRules: rs.segmentationRules
		.map( ( r ) => {
			const newRule = createSegmentationRule( r.type );
			if ( ! newRule ) {
				return undefined;
			}
			return { ...r, id: newRule.id };
		} )
		.filter( isDefined ),
} );
