/**
 * WordPress dependencies
 */
import { Button, Dashicon, Dropdown } from '@safe-wordpress/components';
import apiFetch from '@safe-wordpress/api-fetch';
import { useInstanceId } from '@safe-wordpress/compose';
import { useSelect } from '@safe-wordpress/data';
import { useState } from '@safe-wordpress/element';
import { _x } from '@safe-wordpress/i18n';

/**
 * External dependencies
 */
import { trim } from 'lodash';
import { store as NAB_DATA, usePageAttribute } from '@nab/data';
import type { SiteId, SubscriptionPlan, Url } from '@nab/types';

/**
 * Internal dependencies
 */
import './style.scss';

import { useWalkthroughEffect } from './walkthrough';
import { QuestionList } from './question-list';
import { ContactForm, ContactFormProps } from './contact-form';
import { ChatBot } from './chat-bot';

import type { Question, State, TutorialStep } from './types';

export type ContextualHelpProps = FloatingProps | ButtonProps | ContentProps;

type BaseProps = {
	readonly screen: string;
	readonly questions: ReadonlyArray< Question >;
	readonly walkthrough: ReadonlyArray< TutorialStep >;
};

export type FloatingProps = BaseProps & {
	readonly mode: 'floating';
};

export type ButtonProps = BaseProps & {
	readonly mode: 'button';
	readonly placement:
		| 'top'
		| 'top-start'
		| 'top-end'
		| 'right'
		| 'right-start'
		| 'right-end'
		| 'bottom'
		| 'bottom-start'
		| 'bottom-end'
		| 'left'
		| 'left-start'
		| 'left-end'
		| 'overlay';
};

export type ContentProps = BaseProps & {
	readonly mode: 'content';
	readonly onCloseForm: () => void;
	readonly onRunWalkthrough: () => void;
};

export const ContextualHelp = ( props: ContextualHelpProps ): JSX.Element => {
	const instanceId = useInstanceId( ContextualHelp );
	const runWalkthrough = useWalkthroughEffect(
		props.screen,
		props.walkthrough
	);

	if ( 'content' === props.mode ) {
		const { onRunWalkthrough, ...rest } = props;
		return (
			<>
				<ChatBot />
				<Content
					runWalkthrough={
						!! runWalkthrough
							? () => {
									runWalkthrough();
									onRunWalkthrough();
							  }
							: undefined
					}
					{ ...rest }
				/>
			</>
		);
	}

	return (
		<div
			className={ `nab-contextual-help__wrapper nab-contextual-help__wrapper--is-${ props.mode }` }
		>
			<ChatBot />
			<Dropdown
				placement={
					'button' === props.mode ? props.placement : 'top-start'
				}
				contentClassName="nab-contextual-help__dropdown"
				renderToggle={ ( { onToggle, isOpen } ) =>
					'button' === props.mode ? (
						<Button
							id={ `nab-contextual-help__toggle-${ instanceId }` }
							onClick={ onToggle }
							aria-expanded={ isOpen }
							aria-live="polite"
							icon="editor-help"
							title={ _x( 'Help', 'text', 'nelio-ab-testing' ) }
							aria-label={ _x(
								'Help',
								'text',
								'nelio-ab-testing'
							) }
						/>
					) : (
						<Button
							id={ `nab-contextual-help__toggle-${ instanceId }` }
							className="nab-contextual-help__toggle"
							onClick={ onToggle }
							aria-expanded={ isOpen }
							aria-live="polite"
						>
							<Dashicon icon="editor-help" />
						</Button>
					)
				}
				renderContent={ ( { onToggle } ) => (
					<Content
						onCloseForm={ onToggle }
						runWalkthrough={
							!! runWalkthrough
								? () => {
										runWalkthrough();
										onToggle();
								  }
								: undefined
						}
						{ ...props }
					/>
				) }
			/>
		</div>
	);
};

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

const Content = ( {
	screen,
	questions,
	onCloseForm,
	runWalkthrough,
}: Omit< ContentProps, 'mode' | 'onRunWalkthrough' > & {
	readonly runWalkthrough?: () => void;
} ) => {
	const [ _, openChatBot ] = usePageAttribute( 'chatbot/status', false );
	const [ state, doSetState ] = useState< State >( {
		mode: 'questions',
		email: '',
		description: '',
		isTicketSubmitting: false,
		submissionStatus: 'none',
	} );

	const setState = ( a: Partial< State > ) =>
		doSetState( { ...state, ...a } );
	const { mode } = state;

	const { siteId, homeUrl, subscription, apiUrl } = useSelect(
		( select ) => ( {
			siteId: select( NAB_DATA ).getPluginSetting( 'siteId' ),
			homeUrl: select( NAB_DATA ).getPluginSetting( 'homeUrl' ),
			subscription: select( NAB_DATA ).getPluginSetting( 'subscription' ),
			apiUrl: select( NAB_DATA ).getPluginSetting( 'apiUrl' ),
		} ),
		[]
	);

	const submitTicket: ContactFormProps[ 'onSubmit' ] = ( {
		email,
		description,
		success,
		error,
	} ) => {
		success();
		apiFetch( {
			url: `${ apiUrl }/ticket`,
			credentials: 'omit',
			method: 'POST',
			mode: 'cors',
			data: {
				email,
				description: getDescription(
					description,
					siteId,
					homeUrl,
					subscription
				),
				subject: `I need help in ${ screen }`,
			},
		} ).then( success, error );
	};

	if ( 'contact-form' === mode ) {
		return (
			<ContactForm
				attributes={ state }
				setAttributes={ setState }
				onSubmit={ submitTicket }
				closeForm={ onCloseForm }
			/>
		);
	}

	return (
		<QuestionList
			runWalkthrough={ runWalkthrough }
			questions={ questions }
			onChatBot={ () => {
				onCloseForm();
				openChatBot( true );
			} }
			onContactUs={ () =>
				setState( {
					mode: 'contact-form',
					email: '',
					description: '',
				} )
			}
		/>
	);
};

// =======
// HELPERS
// =======

function getDescription(
	description: string,
	siteId: SiteId,
	homeUrl: Url,
	subscription: SubscriptionPlan | false
): string {
	const div = document.createElement( 'div' );
	const br = () => document.createElement( 'br' );

	const extra = document.createElement( 'strong' );
	extra.textContent = 'Additional Information';

	const ul = document.createElement( 'ul' );
	const li1 = document.createElement( 'li' );
	li1.textContent = `Site ID: ${ siteId }`;
	const li2 = document.createElement( 'li' );
	li2.textContent = `Site URL: ${ homeUrl }`;
	const li3 = document.createElement( 'li' );
	li3.textContent = `Subscribed: ${
		false === subscription ? 'no' : subscription
	}`;
	ul.appendChild( li1 );
	ul.appendChild( li2 );
	ul.appendChild( li3 );

	trim( description )
		.split( /\n+/ )
		.forEach( ( t ) => {
			const p = document.createTextNode( t );
			div.appendChild( p );
			div.appendChild( br() );
			div.appendChild( br() );
		} );

	div.appendChild( extra );
	div.appendChild( br() );
	div.appendChild( ul );

	return div.innerHTML;
}
