/**
 * WordPress dependencies
 */
import { Button, Dashicon } from '@safe-wordpress/components';
import { useDispatch, useSelect } from '@safe-wordpress/data';
import { createInterpolateElement } from '@safe-wordpress/element';
import { _x, sprintf } from '@safe-wordpress/i18n';

/**
 * External dependencies
 */
import { ReusableEntitiesDialog } from '@nab/components';
import { store as NAB_DATA } from '@nab/data';
import { store as NAB_EDITOR } from '@nab/editor';
import { createSegmentationRule as createSegmentationRuleWithDefaults } from '@nab/segmentation-rules';
import { EMPTY_ARRAY, isDefined } from '@nab/utils';
import type {
	Dict,
	ReusableSegment,
	SegmentationRuleId,
	SegmentationRuleTypeName,
} from '@nab/types';

/**
 * Internal dependencies
 */
import './style.scss';
import { SegmentationRule } from '../../../editor/components/segment/segmentation-rule';
import { SegmentationRuleTypeCategoryList } from '../../../editor/components/segment/segmentation-rule-type-category-list';

export const ParticipationSection = (): JSX.Element => (
	<div className="nab-edit-experiment__participation-section">
		<Title />
		<ParticipationConditions />
		<ReusableParticipationDialog />
	</div>
);

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

const Title = () => (
	<h2>
		{ createInterpolateElement(
			sprintf(
				/* translators: %s: Dashicon. */
				_x( '%s Participation', 'text', 'nelio-ab-testing' ),
				'<icon></icon>'
			),
			{
				icon: (
					<Dashicon
						className="nab-participation-section__title-icon"
						icon="groups"
					/>
				),
			}
		) }
	</h2>
);

const ParticipationConditions = () => {
	const { conditions, createCondition, updateCondition, removeCondition } =
		useParticipationConditions();
	const { openReusableDialog } = useDispatch( NAB_EDITOR );
	const isImportEnabled = useIsImportEnabled();

	return (
		<div className="nab-edit-experiment-participation-section__content">
			<p>
				{ ! conditions.length
					? _x(
							'All visitors will contribute to this heatmap. If you want to limit participation to a subset of visitors, use the actions below:',
							'text',
							'nelio-ab-testing'
					  )
					: _x(
							'Only visitors who meet all the following criteria will contribute to this heatmap:',
							'text',
							'nelio-ab-testing'
					  ) }
			</p>
			<div className="nab-edit-experiment-participation-section__conditions">
				{ conditions.map( ( condition ) => (
					<SegmentationRule
						key={ condition.id }
						rule={ condition }
						setAttributes={ ( attrs ) =>
							updateCondition( condition.id, attrs )
						}
						remove={ () => removeCondition( condition.id ) }
					/>
				) ) }
			</div>
			<div className="nab-edit-experiment-participation-section__actions">
				<SegmentationRuleTypeCategoryList
					segmentationRules={ conditions }
					createSegmentationRule={ createCondition }
				/>
				{ isImportEnabled && ! conditions.length && (
					<Button
						variant="secondary"
						onClick={ () =>
							openReusableDialog( 'manage-segments' )
						}
					>
						{ _x(
							'Import Segment',
							'command',
							'nelio-ab-testing'
						) }
					</Button>
				) }
			</div>
		</div>
	);
};

function ReusableParticipationDialog(): JSX.Element | null {
	const dialog = useReusableDialog();
	const { closeReusableDialog: onClose } = useDispatch( NAB_EDITOR );
	const { setHeatmapData } = useDispatch( NAB_EDITOR );

	const { isSaving, reusableSegments } = useSelect(
		( select ) => ( {
			isSaving: select( NAB_DATA ).isSavingReusableEntities(),
			reusableSegments: select( NAB_DATA ).getReusableSegments(),
		} ),
		[]
	);

	if ( 'manage-segments' !== dialog ) {
		return null;
	}

	return (
		<ReusableEntitiesDialog< ReusableSegment >
			mode="manage"
			isSingular
			labels={ {
				title: _x( 'Reusable Segments', 'text', 'nelio-ab-testing' ),
				replace: _x( 'Import Segment', 'text', 'nelio-ab-testing' ),
				selectSingle: _x(
					'Select a segment to import:',
					'user',
					'nelio-ab-testing'
				),
			} }
			items={ reusableSegments }
			saving={ isSaving }
			onReplace={ ( selection ) => {
				if ( ! selection[ 0 ] ) {
					return;
				}
				void setHeatmapData( {
					participationConditions: selection[ 0 ].segmentationRules
						.map( ( sr ) => {
							const newRule = createSegmentationRuleWithDefaults(
								sr.type
							);
							if ( ! newRule ) {
								return undefined;
							}
							return { ...sr, id: newRule.id };
						} )
						.filter( isDefined ),
				} );
				void onClose();
			} }
			onClose={ onClose }
		/>
	);
}

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

const useParticipationConditions = () => {
	const conditions = useSelect(
		( select ) =>
			select( NAB_EDITOR ).getHeatmapAttribute(
				'participationConditions'
			) ?? EMPTY_ARRAY,
		[]
	);

	const { setHeatmapData } = useDispatch( NAB_EDITOR );

	return {
		conditions,

		createCondition: ( type: SegmentationRuleTypeName ) => {
			const rule = createSegmentationRuleWithDefaults( type );
			if ( rule ) {
				void setHeatmapData( {
					participationConditions: [ ...conditions, rule ],
				} );
			}
		},

		updateCondition: ( id: SegmentationRuleId, attrs: Dict ) =>
			void setHeatmapData( {
				participationConditions: conditions.map( ( c ) =>
					c.id === id
						? { ...c, attributes: { ...c.attributes, ...attrs } }
						: c
				),
			} ),

		removeCondition: ( id: SegmentationRuleId ) =>
			void setHeatmapData( {
				participationConditions: conditions.filter(
					( c ) => c.id !== id
				),
			} ),
	};
};

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

const useIsImportEnabled = (): boolean =>
	useSelect(
		( select ) => !! select( NAB_DATA ).getReusableGoals().length,
		[]
	);
