/**
 * Modal to name a duplicated Gutenberg block before cloning.
 */
import { createPortal, useEffect, useRef, useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { api } from '../api';
import Notice from './ui/Notice';

/**
 * @param {object}   props
 * @param {object}   props.block     Source user block.
 * @param {boolean}  props.busy      Clone request in flight.
 * @param {Function} props.onClose
 * @param {Function} props.onConfirm ( name: string ) => void
 */
export default function CloneBlockModal( { block, busy = false, onClose, onConfirm } ) {
	const [ name, setName ] = useState( '' );
	const [ error, setError ] = useState( '' );
	const [ validating, setValidating ] = useState( false );
	const nameInputRef = useRef( null );

	useEffect( () => {
		if ( ! block ) {
			return;
		}
		const base = String( block.name || '' ).trim() || __( 'Block', 'joc-blockora-morph' );
		setName( `${ base }_1` );
		setError( '' );
		setValidating( false );
		window.requestAnimationFrame( () => {
			nameInputRef.current?.focus?.();
			nameInputRef.current?.select?.();
		} );
	}, [ block ] );

	useEffect( () => {
		if ( ! block ) {
			return undefined;
		}
		const onKey = ( e ) => {
			if ( e.key === 'Escape' && ! busy && ! validating ) {
				onClose();
			}
		};
		const prevOverflow = document.body.style.overflow;
		document.body.style.overflow = 'hidden';
		window.addEventListener( 'keydown', onKey );
		return () => {
			document.body.style.overflow = prevOverflow;
			window.removeEventListener( 'keydown', onKey );
		};
	}, [ block, busy, validating, onClose ] );

	if ( ! block ) {
		return null;
	}

	const showNameError = ( message ) => {
		setError( message );
		window.requestAnimationFrame( () => {
			nameInputRef.current?.focus?.();
			nameInputRef.current?.select?.();
		} );
	};

	const submit = async ( e ) => {
		e?.preventDefault?.();
		if ( busy || validating ) {
			return;
		}

		const trimmed = name.trim();
		if ( ! trimmed ) {
			showNameError( __( 'Block name is required.', 'joc-blockora-morph' ) );
			return;
		}

		setValidating( true );
		setError( '' );
		try {
			const result = await api.get(
				`/user-blocks/check-name?name=${ encodeURIComponent( trimmed ) }`
			);
			if ( ! result?.valid ) {
				showNameError(
					result?.message ||
						__( 'That block name is already in use and is already in your library. Choose a unique name.', 'joc-blockora-morph' )
				);
				return;
			}
			onConfirm( trimmed );
		} catch ( err ) {
			showNameError(
				err?.message ||
					__( 'Could not validate block name. Try again.', 'joc-blockora-morph' )
			);
		} finally {
			setValidating( false );
		}
	};

	const portalTarget =
		document.getElementById( 'joc-blockora-morph-app' ) || document.body;
	const locked = busy || validating;

	return createPortal(
		<div
			className="bm-modal-root bm-fade fixed inset-0 z-[100100] flex items-center justify-center p-4 font-sans sm:p-6"
			role="dialog"
			aria-modal="true"
			aria-labelledby="bm-clone-block-title"
		>
			<div
				className="bm-modal-backdrop"
				onClick={ locked ? undefined : onClose }
			/>
			<form
				className="bm-rise relative z-10 w-full max-w-md overflow-hidden rounded-xl border border-outline-variant/30 bg-surface-lowest shadow-card"
				onSubmit={ submit }
			>
				<header className="border-b border-outline-variant/20 px-5 py-4">
					<p className="mb-1 text-caps-micro font-bold uppercase tracking-widest text-outline">
						{ __( 'Duplicate block', 'joc-blockora-morph' ) }
					</p>
					<h2
						id="bm-clone-block-title"
						className="m-0 text-headline-lg text-on-surface"
					>
						{ __( 'Name the copy', 'joc-blockora-morph' ) }
					</h2>
					<p className="mt-1 mb-0 text-body-md text-on-surface-variant">
						{ __(
							'Choose a unique name for the cloned block. It will appear in My Blocks and the Gutenberg inserter.',
							'joc-blockora-morph'
						) }
					</p>
				</header>

				<div className="space-y-3 px-5 py-4">
					<label>
						<span className="bm-field-label">
							{ __( 'Block name', 'joc-blockora-morph' ) }{ ' ' }
							<em className="not-italic text-red-600">*</em>
						</span>
						<input
							ref={ nameInputRef }
							type="text"
							className={
								error ? 'bm-field-input is-invalid' : 'bm-field-input'
							}
							value={ name }
							required
							onChange={ ( ev ) => {
								setName( ev.target.value );
								if ( error ) {
									setError( '' );
								}
							} }
							disabled={ locked }
							autoComplete="off"
							aria-invalid={ error ? 'true' : 'false' }
							placeholder={ __( 'e.g. Center Hero_1', 'joc-blockora-morph' ) }
						/>
					</label>
					{ error ? <Notice variant="danger">{ error }</Notice> : null }
					<p className="m-0 text-[12px] text-outline">
						{ __( 'Cloning from', 'joc-blockora-morph' ) }{ ' ' }
						<strong className="text-on-surface">{ block.name }</strong>
					</p>
				</div>

				<footer className="flex flex-wrap items-center justify-end gap-2 border-t border-outline-variant/20 bg-surface-low/60 px-5 py-3">
					<button
						type="button"
						className="bm-btn bm-btn--ghost bm-btn--sm"
						onClick={ onClose }
						disabled={ locked }
					>
						{ __( 'Cancel', 'joc-blockora-morph' ) }
					</button>
					<button
						type="submit"
						className="bm-btn bm-btn--primary bm-btn--sm"
						disabled={ locked || ! name.trim() }
					>
						{ validating
							? __( 'Checking…', 'joc-blockora-morph' )
							: busy
							? __( 'Duplicating…', 'joc-blockora-morph' )
							: __( 'Duplicate', 'joc-blockora-morph' ) }
					</button>
				</footer>
			</form>
		</div>,
		portalTarget
	);
}
