import { useState, useCallback, useEffect, useRef } from '@wordpress/element';
import { Button } from '@wordpress/components';
import { __ } from '@wordpress/i18n';

function htmlToPlainText( html ) {
	if ( ! html || typeof html !== 'string' ) {
		return '';
	}
	const div = document.createElement( 'div' );
	div.innerHTML = html;
	return ( div.innerText || div.textContent || '' ).replace( /\u00a0/g, ' ' );
}

function escapeHtml( text ) {
	const div = document.createElement( 'div' );
	div.textContent = text;
	return div.innerHTML;
}

function plainTextToCommentHtml( text ) {
	const trimmed = text.trim();
	if ( ! trimmed ) {
		return '';
	}
	const blocks = trimmed.split( /\n{2,}/ );
	return blocks
		.map( ( block ) => {
			const withBreaks = escapeHtml( block ).replace( /\n/g, '<br />' );
			return `<p>${ withBreaks }</p>`;
		} )
		.join( '' );
}

export default function BasicCommentEditor( {
	onSubmit,
	disabled,
	initialHtml = null,
	onCancel = null,
	clearDraftOnCancel = false,
	submitLabel = null,
	autoFocus = false,
} ) {
	const isEditMode = initialHtml !== null;
	const textareaRef = useRef( null );
	const [ text, setText ] = useState( () =>
		htmlToPlainText( initialHtml || '' )
	);
	const [ submitting, setSubmitting ] = useState( false );
	const [ submitError, setSubmitError ] = useState( null );

	useEffect( () => {
		if ( initialHtml !== null ) {
			setText( htmlToPlainText( initialHtml ) );
		}
	}, [ initialHtml ] );

	useEffect( () => {
		if ( ! autoFocus ) {
			return;
		}
		requestAnimationFrame( () => {
			requestAnimationFrame( () => {
				const el = textareaRef.current;
				if ( ! el ) {
					return;
				}
				el.focus();
				const len = el.value.length;
				el.setSelectionRange( len, len );
			} );
		} );
	}, [ autoFocus ] );

	const isEmpty = ! text.trim();
	const submitDisabled = isEmpty || submitting || disabled;
	const showCancel =
		onCancel != null || ( clearDraftOnCancel && ! submitDisabled );

	const handleCancelClick = useCallback( () => {
		if ( onCancel ) {
			onCancel();
			return;
		}
		setText( '' );
		setSubmitError( null );
	}, [ onCancel ] );

	const handleSubmit = useCallback( async () => {
		if ( submitDisabled ) {
			return;
		}
		setSubmitting( true );
		setSubmitError( null );
		try {
			await onSubmit( plainTextToCommentHtml( text ) );
			if ( ! isEditMode ) {
				setText( '' );
			}
		} catch ( err ) {
			setSubmitError(
				err.message ||
					__( 'Failed to post comment.', 'jumplinks-editorial-workflow' )
			);
		} finally {
			setSubmitting( false );
		}
	}, [ submitDisabled, onSubmit, text, isEditMode ] );

	return (
		<div className="flow-comment-editor flow-comment-editor--basic">
			<div className="flow-comment-editor__content">
				<textarea
					ref={ textareaRef }
					className="flow-comment-editor__textarea"
					value={ text }
					onChange={ ( e ) => setText( e.target.value ) }
					placeholder={ __(
						'Write a comment…',
						'jumplinks-editorial-workflow'
					) }
					disabled={ submitting || disabled }
					rows={ 3 }
				/>
			</div>
			{ submitError && (
				<p className="flow-comment-editor__error">{ submitError }</p>
			) }
			<div className="flow-comment-editor__submit-row">
				<Button
					variant="secondary"
					className="flow-comment-editor__submit-btn"
					onClick={ handleSubmit }
					disabled={ submitDisabled }
					__next40pxDefaultSize
				>
					{ submitting
						? __( 'Saving\u2026', 'jumplinks-editorial-workflow' )
						: submitLabel ||
						  __( 'Add Comment', 'jumplinks-editorial-workflow' ) }
				</Button>
				{ showCancel && (
					<Button
						className="flow-btn--text flow-btn--cancel"
						onClick={ handleCancelClick }
						disabled={ submitting }
						__next40pxDefaultSize
					>
						{ __( 'Cancel', 'jumplinks-editorial-workflow' ) }
					</Button>
				) }
			</div>
		</div>
	);
}
