import { useState, useRef, useEffect } from 'react';
import Editor, {
	BtnBold,
	BtnBulletList,
	BtnClearFormatting,
	BtnItalic,
	BtnLink,
	BtnNumberedList,
	BtnRedo,
	BtnStrikeThrough,
	BtnUnderline,
	BtnUndo,
	createButton,
	Separator,
	Toolbar,
} from 'react-simple-wysiwyg';
import { __ } from '@wordpress/i18n';
import {
	openMediaUploader,
	generateMediaContent,
	sanitizeContent,
	insertTableHandel,
} from './helper';
import { align, imageIcon, pdfIcon, tableIcon, videoIcon } from './icons';
import MediaControls from './MediaControls';
import ColorControls from './ColorPicker';
import MonacoCodeEditor from '../MonacoCodeEditor';

const BtnAlignLeft = createButton( 'Align left', '⇤', 'justifyLeft' );
const BtnAlignCenter = createButton( 'Align center', '≡', 'justifyCenter' );
const BtnAlignRight = createButton( 'Align right', '⇥', 'justifyRight' );
const BtnAlignJustify = createButton( 'Justify', '≣', 'justifyFull' );

const ReactSimpleWysiwyg = ( {
	name,
	defaultValue = '',
	saveValueHandler,
} ) => {
	const [ value, setValue ] = useState( defaultValue );
	const [ selectedElement, setSelectedElement ] = useState( null );
	const [ showMediaTooltip, setShowMediaTooltip ] = useState( false );
	const [ isHtmlMode, setIsHtmlMode ] = useState( false );
	const editorRef = useRef( null );
	const [ dropdown, setDropdown ] = useState( false );

	function onChange( e ) {
		const newValue = sanitizeContent( e.target.value );
		setValue( newValue );
		saveValueHandler( name, newValue );
	}

	const handleBlur = () => {
		if ( editorRef.current ) {
			const sanitizedValue = sanitizeContent(
				editorRef.current.innerHTML
			);
			if ( sanitizedValue !== value ) {
				setValue( sanitizedValue );
				saveValueHandler( name, sanitizedValue );
			}
		}
	};

	const handlePaste = ( e ) => {
		e.preventDefault();

		const clipboardData = e.clipboardData || window.clipboardData;
		const html = clipboardData.getData( 'text/html' );
		const text = clipboardData.getData( 'text/plain' );

		let contentToInsert = '';

		if ( html ) {
			contentToInsert = sanitizeContent( html );
		} else {
			contentToInsert = sanitizeContent( text.replace( /\n/g, '<br/>' ) );
		}

		insertContentAtCursor( contentToInsert );
	};

	const addSelectionBorder = ( element ) => {
		removeAllSelectionBorders();
		element.style.border = '2px solid var(--quizpress-primary)';
		element.style.outline = 'none';
		element.dataset.selected = 'true';
	};

	const removeAllSelectionBorders = () => {
		if ( editorRef.current ) {
			const mediaElements =
				editorRef.current.querySelectorAll( 'img, video' );
			mediaElements.forEach( ( el ) => {
				if ( el.dataset.selected ) {
					el.style.removeProperty( 'border' );
					el.style.removeProperty( 'box-shadow' );
					delete el.dataset.selected;
				}
			} );
		}
	};

	useEffect( () => {
		const handleMediaClick = ( e ) => {
			if (
				( e.target.tagName === 'IMG' ||
					e.target.tagName === 'VIDEO' ) &&
				editorRef.current &&
				editorRef.current.contains( e.target )
			) {
				e.preventDefault();
				e.stopPropagation();

				setSelectedElement( e.target );
				addSelectionBorder( e.target );
				setShowMediaTooltip( true );
			}
		};

		const handleClickOutside = ( e ) => {
			if (
				e.target.closest( '.quizpress-media-controls-overlay' ) ||
				e.target.closest( '.quizpress-media-tooltip' ) ||
				e.target.closest( '.quizpress-resize-handle' ) ||
				e.target.closest( '[class*="select"]' ) ||
				e.target.closest( '[class*="Select"]' ) ||
				e.target.closest( '[id*="react-select"]' )
			) {
				return;
			}

			if ( e.target.tagName !== 'IMG' && e.target.tagName !== 'VIDEO' ) {
				setSelectedElement( null );
				setShowMediaTooltip( false );
				removeAllSelectionBorders();
			}
		};

		const handleKeyDown = ( e ) => {
			if ( e.key === 'Escape' ) {
				setSelectedElement( null );
				setShowMediaTooltip( false );
				removeAllSelectionBorders();
			}
		};

		if ( editorRef.current ) {
			editorRef.current.addEventListener( 'click', handleMediaClick );
			document.addEventListener( 'click', handleClickOutside, true );
			document.addEventListener( 'keydown', handleKeyDown );
		}

		return () => {
			if ( editorRef.current ) {
				editorRef.current.removeEventListener(
					'click',
					handleMediaClick
				);
			}
			document.removeEventListener( 'click', handleClickOutside, true );
			document.removeEventListener( 'keydown', handleKeyDown );
		};
	}, [] );

	const insertContentAtCursor = ( content ) => {
		if ( editorRef.current ) {
			const editor = editorRef.current;
			const selection = window.getSelection();

			if ( selection.rangeCount > 0 ) {
				const range = selection.getRangeAt( 0 );
				const container = range.commonAncestorContainer;

				if ( editor.contains( container ) || editor === container ) {
					range.deleteContents();
					const tempDiv = document.createElement( 'div' );
					tempDiv.innerHTML = content;

					while ( tempDiv.firstChild ) {
						range.insertNode( tempDiv.firstChild );
					}

					const newValue = sanitizeContent( editor.innerHTML );
					setValue( newValue );
					saveValueHandler( name, newValue );
					return;
				}
			}

			const newValue = sanitizeContent( value + content );
			setValue( newValue );
			saveValueHandler( name, newValue );
		}
	};

	const handleMediaInsert = ( type ) => {
		openMediaUploader( type, ( attachment ) => {
			const content = generateMediaContent( attachment, type );
			insertContentAtCursor( content );
		} );
	};

	const insertImage = () => handleMediaInsert( 'image' );
	const insertVideo = () => handleMediaInsert( 'video' );
	const insertPdf = () => handleMediaInsert( 'pdf' );

	const insertTable = () => {
		insertTableHandel( insertContentAtCursor, __ );
	};

	const handleMediaUpdate = () => {
		if ( editorRef.current ) {
			const newValue = sanitizeContent( editorRef.current.innerHTML );
			setValue( newValue );
			saveValueHandler( name, newValue );
		}
	};

	const handleMediaControlsClose = () => {
		setShowMediaTooltip( false );
		setSelectedElement( null );
		removeAllSelectionBorders();
	};

	useEffect( () => {
		function handleDocumentClick() {
			setDropdown( false );
		}

		if ( dropdown ) {
			document.addEventListener( 'click', handleDocumentClick );
		}
		return () => {
			document.removeEventListener( 'click', handleDocumentClick );
		};
	}, [ dropdown ] );

	function dropdownHandler( e ) {
		e.stopPropagation();
	}

	const savedSelectionRef = useRef( null );
	const saveSelection = () => {
		const sel = window.getSelection();
		if (
			sel.rangeCount > 0 &&
			! sel.isCollapsed &&
			editorRef.current?.contains( sel.anchorNode )
		) {
			savedSelectionRef.current = sel.getRangeAt( 0 ).cloneRange();
		}
	};

	const restoreSelection = () => {
		if ( savedSelectionRef.current && editorRef.current ) {
			const sel = window.getSelection();
			sel.removeAllRanges();
			try {
				// Make sure the editor is focused first
				editorRef.current.focus();
				sel.addRange( savedSelectionRef.current );
			} catch ( e ) {
				console.error( 'Error restoring selection:', e );
				savedSelectionRef.current = null;
			}
		}
	};

	useEffect( () => {
		const editor = editorRef.current;
		if ( ! editor ) {
			return;
		}

		let selectionTimeout;

		const handleSelectionChange = () => {
			// Debounce selection changes to avoid excessive saves
			clearTimeout( selectionTimeout );
			selectionTimeout = setTimeout( () => {
				const sel = window.getSelection();
				if (
					sel.rangeCount > 0 &&
					! sel.isCollapsed &&
					editor.contains( sel.anchorNode )
				) {
					savedSelectionRef.current = sel
						.getRangeAt( 0 )
						.cloneRange();
				}
			}, 50 );
		};

		const handleMouseUp = ( e ) => {
			// Save selection immediately on mouseup if there's a selection
			setTimeout( () => {
				const sel = window.getSelection();
				if (
					sel.rangeCount > 0 &&
					! sel.isCollapsed &&
					editor.contains( sel.anchorNode )
				) {
					savedSelectionRef.current = sel
						.getRangeAt( 0 )
						.cloneRange();
				}
			}, 10 );
		};

		const handleKeyUp = ( e ) => {
			// Save selection on key events that might change selection
			if (
				e.shiftKey ||
				[ 'ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown' ].includes(
					e.key
				)
			) {
				setTimeout( () => {
					const sel = window.getSelection();
					if (
						sel.rangeCount > 0 &&
						! sel.isCollapsed &&
						editor.contains( sel.anchorNode )
					) {
						savedSelectionRef.current = sel
							.getRangeAt( 0 )
							.cloneRange();
					}
				}, 10 );
			}
		};

		// Use capture phase to catch events before they bubble
		document.addEventListener( 'selectionchange', handleSelectionChange );
		editor.addEventListener( 'mouseup', handleMouseUp, true );
		editor.addEventListener( 'keyup', handleKeyUp, true );

		return () => {
			clearTimeout( selectionTimeout );
			document.removeEventListener(
				'selectionchange',
				handleSelectionChange
			);
			editor.removeEventListener( 'mouseup', handleMouseUp, true );
			editor.removeEventListener( 'keyup', handleKeyUp, true );
		};
	}, [] );

	const toggleHtmlMode = () => {
		if ( ! isHtmlMode ) {
			setIsHtmlMode( true );
		} else {
			setIsHtmlMode( false );
		}
	};

	return (
		<div style={ { position: 'relative' } }>
			{ isHtmlMode ? (
				<>
					<button
						className="quizpress-editor-btn quizpress-editor-btn--html"
						onClick={ () => setIsHtmlMode( ! isHtmlMode ) }
					>
						<span className="quizpress-icon quizpress-icon--arrow-left"></span>
						{ __( 'Back to Editor', 'easy-content-manager' ) }
					</button>
					<MonacoCodeEditor
						value={ defaultValue }
						saveHandler={ ( value ) => {
							saveValueHandler( name, value ), setValue( value );
						} }
					/>
				</>
			) : (
				<>
					<Editor
						value={ value }
						onChange={ onChange }
						onBlur={ handleBlur }
						onPaste={ handlePaste }
						ref={ editorRef }
					>
						<Toolbar>
							<BtnUndo />
							<BtnRedo />
							<Separator />
							<BtnBold />
							<BtnItalic />
							<BtnUnderline />
							<BtnStrikeThrough />
							<Separator />
							<button
								type="button"
								className="quizpress-editor-btn-alignment"
								onMouseDown={ ( e ) => {
									e.preventDefault();
									e.stopPropagation();

									const sel = window.getSelection();
									if (
										sel.rangeCount > 0 &&
										! sel.isCollapsed &&
										editorRef.current?.contains(
											sel.anchorNode
										)
									) {
										savedSelectionRef.current = sel
											.getRangeAt( 0 )
											.cloneRange();
									}

									setDropdown( ( prev ) => ! prev );
								} }
								onClick={ ( e ) => {
									e.preventDefault();
									e.stopPropagation();

									setTimeout( () => {
										restoreSelection();
									}, 0 );
								} }
							>
								{ align() }
							</button>
							{ dropdown && (
								<div
									onClick={ dropdownHandler }
									className="quizpress-editor-alignment-dropdown"
								>
									<BtnAlignLeft />
									<BtnAlignCenter />
									<BtnAlignRight />
									<BtnAlignJustify />
								</div>
							) }

							<Separator />

							<ColorControls
								onMouseDownHandler={ ( e, handler ) => {
									e.preventDefault();
									e.stopPropagation();

									// Save selection before any state changes
									const sel = window.getSelection();
									if (
										sel.rangeCount > 0 &&
										! sel.isCollapsed &&
										editorRef.current?.contains(
											sel.anchorNode
										)
									) {
										savedSelectionRef.current = sel
											.getRangeAt( 0 )
											.cloneRange();
									}

									handler();
								} }
								onClickHandler={ ( e ) => {
									e.preventDefault();
									e.stopPropagation();

									// Restore selection after state change
									setTimeout( () => {
										restoreSelection();
									}, 0 );
								} }
							/>

							<BtnNumberedList />
							<BtnBulletList />
							<Separator />
							<BtnLink />
							<BtnClearFormatting />
							<button
								onClick={ () => setIsHtmlMode( ! isHtmlMode ) }
								className="quizpress-editor-btn"
								title={ __( '</>', 'easy-content-manager' ) }
							>
								{ '</>' }
							</button>

							<Separator />

							<button
								type="button"
								onClick={ insertImage }
								className="quizpress-editor-btn"
								title={ __(
									'Insert Image',
									'easy-content-manager'
								) }
							>
								{ imageIcon() }
							</button>

							<button
								type="button"
								onClick={ insertVideo }
								className="quizpress-editor-btn"
								title={ __(
									'Insert Video',
									'easy-content-manager'
								) }
							>
								{ videoIcon() }
							</button>

							<button
								type="button"
								onClick={ insertTable }
								className="quizpress-editor-btn"
								title={ __(
									'Insert Table',
									'easy-content-manager'
								) }
							>
								{ tableIcon() }
							</button>

							<button
								type="button"
								onClick={ insertPdf }
								className="quizpress-editor-btn"
								title={ __(
									'Insert PDF',
									'easy-content-manager'
								) }
							>
								{ pdfIcon() }
							</button>
						</Toolbar>
					</Editor>

					{ /* <MediaControls
						selectedElement={selectedElement}
						onUpdate={handleMediaUpdate}
						onClose={handleMediaControlsClose}
						isOpen={showMediaTooltip}
					/> */ }
				</>
			) }
		</div>
	);
};

export default ReactSimpleWysiwyg;
