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

/**
 * External dependencies
 */
import clsx from 'clsx';
import { last } from 'lodash';
import { store as NAB_DATA } from '@nab/data';
import type { ExperimentSuggestion, Maybe, Opportunity } from '@nab/types';

/**
 * Internal dependencies
 */
import './style.scss';
import { AiIcon } from '../ai-icon';
import { CreateExperimentFromOpportunityButton } from '../create-experiment-from-opportunity-button';
import { LoadingAnimation } from '../loading-animation';
import { ExperimentSuggestionView } from '../experiment-suggestion-view';

export type ExperimentSuggestionsModalType = {
	readonly isFollowUp?: boolean;
};

export function ExperimentSuggestionsModal(
	props: ExperimentSuggestionsModalType
): JSX.Element | null {
	const { opportunityBeingInstantiated, state } = useSelect(
		( select ) => ( {
			opportunityBeingInstantiated:
				select( NAB_DATA ).getOpportunityBeingInstantiated(),
			state: select( NAB_DATA ).getSuggestionGenerationState(),
		} ),
		[]
	);
	const { setSuggestionGenerationState } = useDispatch( NAB_DATA );

	if ( 'idle' === state.status ) {
		return null;
	}

	const isLoading = 'opportunity-scan-ready' !== state.status;
	const isDismissible = ! isLoading && ! opportunityBeingInstantiated;

	return (
		<Modal
			className="nab-suggestions-modal"
			title={
				(
					<>
						<AiIcon />{ ' ' }
						{ _x( 'Test Suggestions', 'text', 'nelio-ab-testing' ) }{ ' ' }
						<div className="nab-suggestions-modal__subtitle">
							{ _x(
								'AI-powered ideas to improve your site',
								'text',
								'nelio-ab-testing'
							) }
						</div>
					</>
				 ) as unknown as string
			}
			isDismissible={ isDismissible }
			shouldCloseOnEsc={ isDismissible }
			shouldCloseOnClickOutside={ isDismissible }
			onRequestClose={ () =>
				isDismissible
					? setSuggestionGenerationState( { status: 'idle' } )
					: void null
			}
		>
			{ state.status === 'opportunity-scan-ready' ? (
				<SuggestionsBody
					opportunity={ state.opportunity }
					suggestions={ state.suggestions }
					instantiatingSuggestion={ state.instantiatingSuggestion }
					{ ...props }
				/>
			) : (
				<ScanningBody { ...props } />
			) }
		</Modal>
	);
}

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

const MESSAGE_DURATION_IN_MS = 2500;
const SCANNING_MESSAGES = [
	_x( 'Analyzing this opportunity…', 'text', 'nelio-ab-testing' ),
	_x( 'Exploring possibilities…', 'text', 'nelio-ab-testing' ),
	_x( 'Crafting test ideas…', 'text', 'nelio-ab-testing' ),
	_x( 'Almost there…', 'text', 'nelio-ab-testing' ),
] as const;

const FOLLOWUP_SCANNING_MESSAGES = [
	_x( 'Analyzing this test…', 'text', 'nelio-ab-testing' ),
	_x( 'Exploring possibilities…', 'text', 'nelio-ab-testing' ),
	_x( 'Crafting follow-up tests…', 'text', 'nelio-ab-testing' ),
	_x( 'Almost there…', 'text', 'nelio-ab-testing' ),
];

function ScanningBody( {
	isFollowUp,
}: ExperimentSuggestionsModalType ): JSX.Element {
	const [ messageIndex, setMessageIndex ] = useState( 0 );

	useEffect( () => {
		setTimeout( () => {
			setMessageIndex( messageIndex + 1 );
		}, MESSAGE_DURATION_IN_MS );
	}, [ messageIndex ] );

	const messages = isFollowUp
		? FOLLOWUP_SCANNING_MESSAGES
		: SCANNING_MESSAGES;

	return (
		<div className="nab-suggestions-modal__loading-body">
			<LoadingAnimation />
			<div className="nab-suggestions-modal__loading-text">
				{ messages[ messageIndex ] ?? last( messages ) }
			</div>
		</div>
	);
}

function SuggestionsBody( {
	opportunity,
	suggestions,
	instantiatingSuggestion,
	isFollowUp,
}: {
	readonly opportunity: Opportunity;
	readonly suggestions: ReadonlyArray< ExperimentSuggestion >;
	readonly instantiatingSuggestion: Maybe< ExperimentSuggestion >;
} & ExperimentSuggestionsModalType ) {
	const { setSuggestionGenerationState } = useDispatch( NAB_DATA );
	const opportunityBeingInstantiated = useSelect(
		( select ) => select( NAB_DATA ).getOpportunityBeingInstantiated(),
		[]
	);
	const { instantiateSuggestionAsExperiment } = useDispatch( NAB_DATA );
	return (
		<div className="nab-suggestions-modal__suggestions-body">
			{ suggestions.length ? (
				<div>
					<AiIcon />{ ' ' }
					{ isFollowUp
						? sprintf(
								/* translators: %d: Number of suggestions. */
								_x(
									'%d ideas found as follow-up',
									'text',
									'nelio-ab-testing'
								),
								suggestions.length
						  )
						: sprintf(
								/* translators: %d: Number of suggestions. */
								_x(
									'%d ideas found for this opportunity',
									'text',
									'nelio-ab-testing'
								),
								suggestions.length
						  ) }
				</div>
			) : (
				<div>
					{ isFollowUp
						? sprintf(
								/* translators: %s: Nelio AI. */
								_x(
									'%s couldn’t come up with a suitable suggestion for this page.',
									'text',
									'nelio-ab-testing'
								),
								'Nelio AI'
						  ) +
						  ' ' +
						  _x(
								'Start with a blank test and choose what you’d like to optimize.',
								'user',
								'nelio-ab-testing'
						  )
						: sprintf(
								/* translators: %s: Nelio AI. */
								_x(
									'%s couldn’t find a suitable follow-up for this test.',
									'text',
									'nelio-ab-testing'
								),
								'Nelio AI'
						  ) +
						  ' ' +
						  _x(
								'Explore more opportunities in the Overview screen or create a new test from scratch.',
								'user',
								'nelio-ab-testing'
						  ) }
				</div>
			) }

			{ suggestions.map( ( suggestion, index ) => (
				<ExperimentSuggestionView
					key={ index }
					value={ suggestion }
					isBusy={ suggestion === instantiatingSuggestion }
					isDisabled={
						( !! instantiatingSuggestion &&
							instantiatingSuggestion !== suggestion ) ||
						!! opportunityBeingInstantiated
					}
					onCreateExperiment={ () =>
						instantiateSuggestionAsExperiment( suggestion )
					}
				/>
			) ) }

			{ isFollowUp && ! suggestions.length && (
				<div className="nab-suggestions-modal__fallback-experiment-action">
					<Button
						variant="primary"
						onClick={ () =>
							setSuggestionGenerationState( { status: 'idle' } )
						}
					>
						{ _x( 'Close', 'command', 'nelio-ab-testing' ) }
					</Button>
				</div>
			) }

			{ ! isFollowUp && (
				<div
					className={ clsx( {
						'nab-suggestions-modal__fallback-experiment': true,
						'nab-suggestions-modal__fallback-experiment--has-suggestions':
							!! suggestions.length,
					} ) }
				>
					{ !! suggestions.length && (
						<>
							<div className="nab-suggestions-modal__fallback-experiment-icon-wrapper">
								<div className="nab-suggestions-modal__fallback-experiment-icon">
									<AiIcon />
								</div>
							</div>
							<div className="nab-suggestions-modal__fallback-experiment-content">
								<div className="nab-suggestions-modal__fallback-experiment-title">
									{ _x(
										'These are AI-generated suggestions',
										'text',
										'nelio-ab-testing'
									) }
								</div>
								<div className="nab-suggestions-modal__fallback-experiment-subtitle">
									{ _x(
										'Review each idea and create the test that make the most sense for you.',
										'user',
										'nelio-ab-testing'
									) }
								</div>
							</div>
						</>
					) }
					<div className="nab-suggestions-modal__fallback-experiment-button">
						<CreateExperimentFromOpportunityButton
							opportunity={ opportunity }
							isBusy={
								opportunity === opportunityBeingInstantiated
							}
							isDisabled={ !! instantiatingSuggestion }
							labels={ {
								action: _x(
									'Create Blank Test',
									'command',
									'nelio-ab-testing'
								),
								busy: _x(
									'Creating Blank Test…',
									'text',
									'nelio-ab-testing'
								),
							} }
							variant={
								suggestions.length ? 'secondary' : 'primary'
							}
						/>
					</div>
				</div>
			) }
		</div>
	);
}
