/**
 * Purrlink Sidebar Component
 *
 * Main sidebar panel for the Gutenberg editor.
 *
 * @package Purrlink
 */

import { useState, useEffect, useCallback } from '@wordpress/element';
import { useSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import { Spinner } from '@wordpress/components';
import apiFetch from '@wordpress/api-fetch';

import RelatedPosts from './RelatedPosts';
import BridgeGenerator, { sanitizeHTML } from './BridgeGenerator';

/**
 * Hook to get actual text selection from the editor.
 *
 * @return {string} Selected text content.
 */
const useSelectedText = () => {
	const [selectedText, setSelectedText] = useState('');

	const handleSelectionChange = useCallback(() => {
		// Get the editor iframe or main document
		const editorCanvas = document.querySelector('iframe[name="editor-canvas"]');
		const doc = editorCanvas?.contentDocument || document;

		const selection = doc.getSelection();
		if (selection && selection.toString().trim()) {
			setSelectedText(selection.toString().trim());
		}
	}, []);

	useEffect(() => {
		// Listen on main document
		document.addEventListener('selectionchange', handleSelectionChange);

		// Also listen on editor iframe if exists
		const editorCanvas = document.querySelector('iframe[name="editor-canvas"]');
		if (editorCanvas?.contentDocument) {
			editorCanvas.contentDocument.addEventListener('selectionchange', handleSelectionChange);
		}

		// Check for iframe load (for site editor)
		const checkIframe = () => {
			const iframe = document.querySelector('iframe[name="editor-canvas"]');
			if (iframe?.contentDocument) {
				iframe.contentDocument.addEventListener('selectionchange', handleSelectionChange);
			}
		};

		// Retry after a short delay for late-loading iframes
		const timeoutId = setTimeout(checkIframe, 1000);

		return () => {
			document.removeEventListener('selectionchange', handleSelectionChange);

			const editorCanvas = document.querySelector('iframe[name="editor-canvas"]');
			if (editorCanvas?.contentDocument) {
				editorCanvas.contentDocument.removeEventListener('selectionchange', handleSelectionChange);
			}

			clearTimeout(timeoutId);
		};
	}, [handleSelectionChange]);

	return selectedText;
};

/**
 * Sidebar component.
 *
 * @return {JSX.Element} Sidebar component.
 */
const PurrlinkSidebar = () => {
	const [relatedPosts, setRelatedPosts] = useState([]);
	const [selectedPost, setSelectedPost] = useState(null);
	const [bridge, setBridge] = useState('');
	const [isLoadingPosts, setIsLoadingPosts] = useState(false);
	const [isGenerating, setIsGenerating] = useState(false);
	const [error, setError] = useState('');
	const [notRelatedWarning, setNotRelatedWarning] = useState('');

	const selectedText = useSelectedText();

	// Get current post ID
	const postId = useSelect((select) => {
		return select('core/editor').getCurrentPostId();
	}, []);

	// Fetch related posts when component mounts or post changes
	useEffect(() => {
		if (!postId) {
			return;
		}

		const fetchRelatedPosts = async () => {
			setIsLoadingPosts(true);
			setError('');

			try {
				const posts = await apiFetch({
					path: `/purrlink/v1/related-posts?post_id=${postId}`,
				});
				setRelatedPosts(posts);
			} catch (err) {
				setError(err.message || __('Failed to load related posts', 'purrlink'));
			} finally {
				setIsLoadingPosts(false);
			}
		};

		fetchRelatedPosts();
	}, [postId]);

	/**
	 * Handle post selection.
	 *
	 * @param {Object} post Selected post object.
	 */
	const handleSelectPost = (post) => {
		setSelectedPost(post);
		setBridge('');
		setError('');
		setNotRelatedWarning('');
	};

	/**
	 * Generate bridge sentence.
	 *
	 * @param {boolean} force Force generation even if content not related.
	 */
	const handleGenerate = async (force = false) => {
		if (!selectedText || !selectedPost) {
			setError(__('Please select text and a target article', 'purrlink'));
			return;
		}

		setIsGenerating(true);
		setError('');
		setNotRelatedWarning('');

		try {
			const response = await apiFetch({
				path: '/purrlink/v1/generate',
				method: 'POST',
				data: {
					context: selectedText,
					target_id: selectedPost.id,
					target_title: selectedPost.title,
					target_url: selectedPost.url,
					target_excerpt: selectedPost.excerpt || '',
					force_generate: force,
				},
			});

			if (response.success) {
				setBridge(response.bridge);
			} else if (response.not_related) {
				// AI detected content is not related.
				setNotRelatedWarning(response.reason);
				setBridge('');
			} else {
				setError(response.message || __('Failed to generate bridge', 'purrlink'));
			}
		} catch (err) {
			setError(err.message || __('An error occurred', 'purrlink'));
		} finally {
			setIsGenerating(false);
		}
	};

	/**
	 * Handle regenerate (normal).
	 */
	const handleRegenerate = () => {
		handleGenerate(false);
	};

	/**
	 * Handle force generate (bypass relevance check).
	 */
	const handleForceGenerate = () => {
		handleGenerate(true);
	};

	/**
	 * Handle bridge text change (for editing).
	 *
	 * @param {string} newBridge Updated bridge text.
	 */
	const handleBridgeChange = (newBridge) => {
		setBridge(newBridge);
	};

	/**
	 * Insert bridge sentence into editor.
	 * SECURITY: Sanitizes HTML before insertion for defense-in-depth.
	 *
	 * @param {string} mode Insert mode: 'after' or 'inline'.
	 */
	const handleInsert = (mode = 'after') => {
		if (!bridge) {
			return;
		}

		// Sanitize bridge HTML before insertion (defense-in-depth).
		const sanitizedBridge = sanitizeHTML(bridge);

		const { createBlock } = wp.blocks;
		const {
			insertBlocks,
			selectBlock,
			updateBlockAttributes,
		} = wp.data.dispatch('core/block-editor');
		const {
			getSelectedBlockClientId,
			getBlockIndex,
			getBlockRootClientId,
			getBlock,
		} = wp.data.select('core/block-editor');

		const selectedBlockId = getSelectedBlockClientId();

		if (mode === 'inline' && selectedBlockId) {
			// Append to current paragraph.
			const currentBlock = getBlock(selectedBlockId);

			if (currentBlock && currentBlock.name === 'core/paragraph') {
				const currentContent = currentBlock.attributes.content || '';
				const newContent = currentContent + ' ' + sanitizedBridge;

				updateBlockAttributes(selectedBlockId, {
					content: newContent,
				});

				// Clear state after insert.
				setBridge('');
				setSelectedPost(null);
				return;
			}
		}

		// Default: Insert as new paragraph after selected block.
		const newBlock = createBlock('core/paragraph', {
			content: sanitizedBridge,
		});

		if (selectedBlockId) {
			const rootClientId = getBlockRootClientId(selectedBlockId);
			const currentIndex = getBlockIndex(selectedBlockId, rootClientId);

			insertBlocks(newBlock, currentIndex + 1, rootClientId);
			selectBlock(newBlock.clientId);
		} else {
			insertBlocks(newBlock);
		}

		// Clear state after insert.
		setBridge('');
		setSelectedPost(null);
	};

	return (
		<div className="purrlink-sidebar">
			{/* Selected Text Section */}
			<div className="purrlink-sidebar__section">
				<h3 className="purrlink-sidebar__section-title">
					{__('Selected Text', 'purrlink')}
				</h3>
				{selectedText ? (
					<div className="purrlink-selected-text">{selectedText}</div>
				) : (
					<div className="purrlink-selected-text purrlink-selected-text--empty">
						{__('Select a paragraph to get started', 'purrlink')}
					</div>
				)}
			</div>

			{/* Related Posts Section */}
			<div className="purrlink-sidebar__section">
				<h3 className="purrlink-sidebar__section-title">
					{__('Related Articles', 'purrlink')}
				</h3>
				{isLoadingPosts ? (
					<div className="purrlink-bridge__loading">
						<Spinner />
						{__('Loading posts...', 'purrlink')}
					</div>
				) : (
					<RelatedPosts
						posts={relatedPosts}
						selectedPost={selectedPost}
						currentPostId={postId}
						onSelect={handleSelectPost}
					/>
				)}
			</div>

			{/* Bridge Generator Section */}
			{selectedPost && (
				<div className="purrlink-sidebar__section">
					<h3 className="purrlink-sidebar__section-title">
						{__('Bridge Sentence', 'purrlink')}
					</h3>
					<BridgeGenerator
						bridge={bridge}
						isLoading={isGenerating}
						error={error}
						notRelatedWarning={notRelatedWarning}
						selectedPost={selectedPost}
						selectedText={selectedText}
						onGenerate={handleGenerate}
						onRegenerate={handleRegenerate}
						onForceGenerate={handleForceGenerate}
						onInsert={handleInsert}
						onBridgeChange={handleBridgeChange}
					/>
				</div>
			)}

			{/* Error Display */}
			{error && !selectedPost && (
				<div className="purrlink-notice purrlink-notice--error">{error}</div>
			)}
		</div>
	);
};

export default PurrlinkSidebar;
