import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import StatusIcon from '../components/StatusIcon';
import Portal from '../components/Portal';

const TEXT_DOMAIN = 'stock-sync-with-google-sheet-for-woocommerce';
const TOAST_TIMEOUT = 2000;

const NoticesContext = createContext( null );

let nextId = 1;

/**
 * Replaces the legacy Sizzle Toast/Vn notifications.
 *
 * - toast(): top-right, auto-dismissing (paused while hovered or focused).
 * - alert(): centred dialog that stays until dismissed (legacy `position: 'center', timeout: false`).
 */
export const NoticesProvider = ( { children } ) => {
	const [ toasts, setToasts ] = useState( [] );
	const [ dialog, setDialog ] = useState( null );

	const dismissToast = useCallback( ( id ) => {
		setToasts( ( current ) => current.filter( ( item ) => item.id !== id ) );
	}, [] );

	const toast = useCallback( ( type, title, content = '' ) => {
		const id = nextId++;
		setToasts( ( current ) => [ ...current, { id, type, title, content } ] );
		return id;
	}, [] );

	const alert = useCallback( ( type, title, content = '' ) => {
		setDialog( { type, title, content } );
	}, [] );

	const value = useMemo(
		() => ( {
			success: ( title, content ) => toast( 'success', title, content ),
			warning: ( title, content ) => toast( 'warning', title, content ),
			error: ( title, content ) => toast( 'error', title, content ),
			alert,
		} ),
		[ toast, alert ]
	);

	return (
		<NoticesContext.Provider value={ value }>
			{ children }
			<Portal>
				<div className="ssgsw-toasts" aria-live="polite">
					{ toasts.map( ( item ) => (
						<Toast key={ item.id } { ...item } onDismiss={ dismissToast } />
					) ) }
				</div>
				{ dialog && <AlertDialog { ...dialog } onClose={ () => setDialog( null ) } /> }
			</Portal>
		</NoticesContext.Provider>
	);
};

const Toast = ( { id, type, title, content, onDismiss } ) => {
	const [ paused, setPaused ] = useState( false );

	useEffect( () => {
		if ( paused ) {
			return undefined;
		}
		const timer = setTimeout( () => onDismiss( id ), TOAST_TIMEOUT );
		return () => clearTimeout( timer );
	}, [ id, paused, onDismiss ] );

	return (
		<div
			className={ `ssgsw-toast ssgsw-toast--${ type }` }
			role={ type === 'error' ? 'alert' : 'status' }
			onMouseEnter={ () => setPaused( true ) }
			onMouseLeave={ () => setPaused( false ) }
			onFocus={ () => setPaused( true ) }
			onBlur={ () => setPaused( false ) }
		>
			<StatusIcon type={ type } className="ssgsw-toast__icon" />
			<div className="ssgsw-toast__body">
				<strong>{ title }</strong>
				{ content && <p>{ content }</p> }
			</div>
			<button type="button" className="ssgsw-toast__close" onClick={ () => onDismiss( id ) } aria-label={ __( 'Dismiss', TEXT_DOMAIN ) }>
				&times;
			</button>
		</div>
	);
};

const AlertDialog = ( { type, title, content, onClose } ) => {
	const buttonRef = useRef( null );

	useEffect( () => {
		const previousFocus = document.activeElement;
		buttonRef.current?.focus();
		const onKeyDown = ( event ) => {
			if ( event.key === 'Escape' ) {
				onClose();
			}
		};
		document.addEventListener( 'keydown', onKeyDown );
		return () => {
			document.removeEventListener( 'keydown', onKeyDown );
			previousFocus?.focus?.();
		};
	}, [ onClose ] );

	return (
		<div className="ssgsw-dialog-backdrop" onClick={ onClose } role="presentation">
			<div
				className={ `ssgsw-dialog ssgsw-dialog--${ type }` }
				role="alertdialog"
				aria-modal="true"
				aria-labelledby="ssgsw-dialog-title"
				onClick={ ( event ) => event.stopPropagation() }
			>
				<StatusIcon type={ type } className="ssgsw-dialog__icon" />
				<h2 id="ssgsw-dialog-title">{ title }</h2>
				{ content && <p>{ content }</p> }
				<button ref={ buttonRef } type="button" className="ssgsw-button ssgsw-button--primary" onClick={ onClose }>
					{ __( 'OK', TEXT_DOMAIN ) }
				</button>
			</div>
		</div>
	);
};

export const useNotices = () => useContext( NoticesContext );
