import { __ } from '@wordpress/i18n';
import { useBlockProps, useInnerBlocksProps, InspectorControls, RichText, BlockControls, store as blockEditorStore } from '@wordpress/block-editor';
import { useSelect } from '@wordpress/data';
import { useState } from '@wordpress/element';
import { TabPanel, PanelBody, ToolbarGroup, ToolbarButton } from '@wordpress/components';
import { cog, styles, formatIndent, formatIndentRTL, formatBold, formatItalic } from '@wordpress/icons';
import './editor.scss';

import { useUniqueBlockClass } from '../../components/hooks/useUniqueBlockClass';
import { useDeviceSettings, generateBlockStyles } from '../../components/controls/blockStyles';
import { generateBlockStylesHover } from '../../components/controls/blockStylesHover';
import { sanitizeSvg } from '../../components/settings/iconUtils';
import LabeledAppender from '../../components/controls/LabeledAppender';
import { StylePanel } from './components/StylePanel';
import { useListItemActions } from './hooks/useListItemActions';

const NESTED_ALLOWED_BLOCKS = [ 'axcelersblocks/list', 'axcelersblocks/heading', 'axcelersblocks/bodycopy' ];
const TEXT_TAG_NAMES = [ 'span', 'strong', 'em', 'a' ];

// A new list item seeds a bodycopy with a short summary of the List / List Item
// blocks, so a freshly inserted list reads as a real example. The line is chosen
// by the item's position, giving the default 3 items distinct copy. Items that
// already hold inline text (the `content` attribute) are left untouched — see
// the guarded template below.
const BODYCOPY_NAME = 'axcelersblocks/bodycopy';
const DEFAULT_BODYCOPY_CONTENT = [
	'The List block stacks items into a clean, fully styled list — ordered or unordered.',
	'Each row is its own List Item block, so items can be styled and managed independently.',
	'Drop a heading, paragraph, or nested list into any item to build rich, structured content.',
];

const escapeAttribute = ( value ) => String( value || '' )
	.replace( /&/g, '&amp;' )
	.replace( /"/g, '&quot;' )
	.replace( /</g, '&lt;' )
	.replace( />/g, '&gt;' );

const getWholeLinkFormat = ( value ) => {
	if ( ! value || typeof value !== 'string' || ! value.includes( '<a' ) || typeof window === 'undefined' ) {
		return null;
	}

	const doc = new window.DOMParser().parseFromString( `<div>${ value }</div>`, 'text/html' );
	const wrapper = doc.body.firstElementChild;
	const linkElement = wrapper?.firstElementChild;

	if (
		! wrapper ||
		wrapper.childNodes.length !== 1 ||
		! linkElement ||
		linkElement.tagName.toLowerCase() !== 'a'
	) {
		return null;
	}

	return {
		content: linkElement.innerHTML,
		href: linkElement.getAttribute( 'href' ) || '',
		target: linkElement.getAttribute( 'target' ) || '',
		rel: linkElement.getAttribute( 'rel' ) || '',
	};
};

const getRichTextValue = ( value, tagName, href, target, rel ) => {
	if ( tagName !== 'a' || ! href ) {
		return value;
	}

	const attrs = [
		`href="${ escapeAttribute( href ) }"`,
		target ? `target="${ escapeAttribute( target ) }"` : '',
		rel ? `rel="${ escapeAttribute( rel ) }"` : '',
	].filter( Boolean ).join( ' ' );

	return `<a ${ attrs }>${ value || '' }</a>`;
};

export default function Edit( { attributes, setAttributes, clientId, context = {}, isSelected } ) {
	const {
		content,
		anchor,
		uniqueClass,
		iconSvg,
		iconColor,
		textTagName = 'span',
		textLinkUrl = '',
		textLinkTarget = '',
		textLinkRel = '',
	} = attributes;

	const listTag     = context['axcelersblocks/listTag'] || 'ul';
	const listIconSvg = context['axcelersblocks/listIconSvg'] || '';

	// Per-item icon: use own iconSvg if set, otherwise fall back to the list-level context icon.
	const activeIconSvg    = ( typeof iconSvg === 'string' && iconSvg.includes( '<svg' ) ) ? iconSvg : listIconSvg;
	const sanitizedIconSvg = sanitizeSvg( activeIconSvg );
	// Custom marker works for both ul and ol — the icon replaces the default bullet/counter.
	const showCustomMarker = typeof sanitizedIconSvg === 'string' && sanitizedIconSvg.includes( '<svg' );
	const showMarker       = showCustomMarker || listTag === 'ol';

	useUniqueBlockClass({ clientId, uniqueClass, setAttributes, blockName: 'axcelersblocks-list-item' });

	const { insertListItemAfter, insertNestedList, nestedBlockCount } = useListItemActions( clientId );

	// Page-builder pattern: the "add inner block" affordance is contextual — it
	// only appears (on its own line, below the item content) while this item or
	// something inside it is active. This keeps the canvas clean instead of
	// rendering a permanent "+" beside every item's text.
	const hasSelectedInnerBlock = useSelect(
		( select ) => select( blockEditorStore ).hasSelectedInnerBlock( clientId, true ),
		[ clientId ]
	);
	const showNestedAppender = isSelected || hasSelectedInnerBlock;

	// Pick the starter bodycopy line by this item's position in the list so the
	// default 3 items read as distinct copy (cycles for any extra items).
	const itemIndex = useSelect(
		( select ) => select( blockEditorStore ).getBlockIndex( clientId ),
		[ clientId ]
	);
	const seedContent = DEFAULT_BODYCOPY_CONTENT[ ( ( itemIndex % DEFAULT_BODYCOPY_CONTENT.length ) + DEFAULT_BODYCOPY_CONTENT.length ) % DEFAULT_BODYCOPY_CONTENT.length ];

	const devices = useDeviceSettings();
	const [ activeStyleTab, setActiveStyleTab ] = useState( 'main' );

	const blockProps = useBlockProps({
		id: anchor || undefined,
		className: [ 'axcelersblocks-list-item', uniqueClass ].filter( Boolean ).join( ' ' ),
	});

	const hasRichBlocks = nestedBlockCount > 0;
	const normalizedTextTagName = TEXT_TAG_NAMES.includes( textTagName ) ? textTagName : 'span';
	const richTextTagName = normalizedTextTagName === 'a' ? 'span' : normalizedTextTagName;
	const richTextValue = getRichTextValue( content, normalizedTextTagName, textLinkUrl, textLinkTarget, textLinkRel );
	const setTextTagName = ( tagName ) => {
		setAttributes( {
			textTagName: normalizedTextTagName === tagName ? 'span' : tagName,
		} );
	};
	const updateTextContent = ( value ) => {
		const wholeLinkFormat = getWholeLinkFormat( value );

		if ( wholeLinkFormat ) {
			setAttributes( {
				content: wholeLinkFormat.content,
				textTagName: 'a',
				textLinkUrl: wholeLinkFormat.href,
				textLinkTarget: wholeLinkFormat.target,
				textLinkRel: wholeLinkFormat.rel,
			} );
			return;
		}

		if ( normalizedTextTagName === 'a' ) {
			setAttributes( {
				content: value,
				textTagName: 'span',
				textLinkUrl: '',
				textLinkTarget: '',
				textLinkRel: '',
			} );
			return;
		}

		setAttributes( { content: value } );
	};

	const { children, ...nestedBlocksProps } = useInnerBlocksProps(
		{
			className: [ 'axcelersblocks-list-item__nested', hasRichBlocks ? 'has-rich-blocks' : '' ].filter( Boolean ).join( ' ' ),
		},
		{
			allowedBlocks: NESTED_ALLOWED_BLOCKS,
			// Seed a starter bodycopy on brand-new items only. Items created in the
			// legacy inline-text mode carry a `content` attribute — for those we
			// pass no template so their text is never replaced on load.
			template: content ? undefined : [ [ BODYCOPY_NAME, { content: seedContent, tagName: 'p' } ] ],
			templateLock: false,
			orientation: 'vertical',
			defaultBlock: { name: 'axcelersblocks/list' },
			directInsert: false,
			renderAppender: showNestedAppender
				? () => (
					<LabeledAppender
						rootClientId={ clientId }
						label={ __( 'Add block', 'axcelersblocks' ) }
						iconOnly
						className="axcelersblocks-list-item__add"
					/>
				)
				: false,
		}
	);

	return (
		<>
			<BlockControls>
				<ToolbarGroup>
					<ToolbarButton
						icon={ formatIndentRTL }
						label={ __( 'Add item below', 'axcelersblocks' ) }
						onClick={ insertListItemAfter }
					/>
					<ToolbarButton
						icon={ formatIndent }
						label={ nestedBlockCount > 0 ? __( 'Select sub list', 'axcelersblocks' ) : __( 'Add sub list', 'axcelersblocks' ) }
						onClick={ insertNestedList }
					/>
				</ToolbarGroup>
				{ ! hasRichBlocks && (
					<ToolbarGroup>
						<ToolbarButton
							icon={ formatBold }
							label={ __( 'Use strong text tag', 'axcelersblocks' ) }
							isPressed={ normalizedTextTagName === 'strong' }
							onClick={ () => setTextTagName( 'strong' ) }
						/>
						<ToolbarButton
							icon={ formatItalic }
							label={ __( 'Use emphasis text tag', 'axcelersblocks' ) }
							isPressed={ normalizedTextTagName === 'em' }
							onClick={ () => setTextTagName( 'em' ) }
						/>
					</ToolbarGroup>
				) }
			</BlockControls>

			<InspectorControls>
				<TabPanel
					className="axcelersblocks-tabs"
					activeClass="is-active"
					tabs={ [
						{ name: 'settings', title: <>{ cog }</>,    className: 'settings-tab' },
						{ name: 'style',    title: <>{ styles }</>, className: 'style-tab' },
					] }
				>
					{ ( tab ) => (
						<>
							{ tab.name === 'settings' && <PanelBody title={ __( 'List Item', 'axcelersblocks' ) } initialOpen /> }
							{ tab.name === 'style' && (
								<StylePanel
									attributes={ attributes }
									setAttributes={ setAttributes }
									uniqueClass={ uniqueClass }
									activeTab={ activeStyleTab }
									setActiveTab={ setActiveStyleTab }
								/>
							) }
						</>
					) }
				</TabPanel>
			</InspectorControls>

			{ uniqueClass ? (
				<style>
					{ generateBlockStyles( uniqueClass, devices, attributes ) }
					{ generateBlockStylesHover( uniqueClass, devices, attributes ) }
					{ /* Per-item marker colour override */ }
					{ iconColor ? `.${ uniqueClass } .icon { color: ${ iconColor }; } .${ uniqueClass } .icon svg { fill: currentColor; }` : '' }
				</style>
			) : null }

			<li { ...blockProps }>
				<span className="axcelersblocks-list-item__badge" aria-hidden="true">{ __( 'List Item', 'axcelersblocks' ) }</span>
				{ showMarker && (
					<span
						className="axcelersblocks-list-item__marker icon"
						aria-hidden="true"
						{ ...( showCustomMarker ? { dangerouslySetInnerHTML: { __html: sanitizedIconSvg } } : {} ) }
					/>
				) }

				<div className="axcelersblocks-list-item__content">
					{ ! hasRichBlocks && (
						<RichText
							tagName={ richTextTagName }
							value={ richTextValue }
							onChange={ updateTextContent }
							placeholder={ __( 'List item…', 'axcelersblocks' ) }
							className="axcelersblocks-list-item__text"
							allowedFormats={ [ 'core/link' ] }
							identifier="content"
						/>
					) }

					<div { ...nestedBlocksProps }>{ children }</div>
				</div>
			</li>
		</>
	);
}
