import { registerBlockType } from '@wordpress/blocks';
import { useEffect, useRef } from '@wordpress/element';
import {
	InnerBlocks,
	InspectorControls,
	useBlockProps,
	MediaUpload,
	MediaUploadCheck,
} from '@wordpress/block-editor';
import {
	PanelBody,
	SelectControl,
	RangeControl,
	ToggleControl,
	TextControl,
	Button,
} from '@wordpress/components';
import metadata from '../block.json';
import './editor.css';

/* ---------- accordion template (root locked; interiors free) ------ */
/* ‼  No lock/templateLock attributes on the inner groups.
      They remain ordinary Group blocks so you can add / move / delete
      anything INSIDE them. */
const TEMPLATE = [
	[
		'core/group',
		{
			className: 'crispycohd-accordion-header',
		},
		[
			[
				'core/paragraph',
				{
					placeholder: 'Replace this with your accordion title',
				},
			],
		],
	],
	[
		'core/separator',
		{
			className: 'crispycohd-accordion-divider',
		},
	],
	[
		'core/group',
		{
			className: 'crispycohd-accordion-content',
			layout:    { type: 'constrained' },
		},
		[
			[
				'core/paragraph',
				{
					placeholder: 'Replace this with your accordion content',
				},
			],
		],
	],
];


registerBlockType(metadata.name, {
	edit({ attributes, setAttributes, clientId }) {
		const { uniqueId, animation, duration, iconType, iconSvg, iconImgUrl, showDivider, caretSide, exclusive, defaultOpen } = attributes;

		// Persist a stable id for ARIA relationships on the front end.
		useEffect(() => {
			if (!uniqueId) {
				setAttributes({ uniqueId: clientId.slice(0, 8) });
			}
		}, [uniqueId, clientId]);

		const svgToDataUrl = (svg) => {
			if (!svg) return '';
			const encoded = encodeURIComponent(svg)
				.replace(/%0A/g, '')
				.replace(/%09/g, '')
				.replace(/%20/g, ' ');
			return `url("data:image/svg+xml;utf8,${encoded}")`;
		};

		const caretIconOverride = (() => {
			if (iconType === 'svg' && iconSvg) return svgToDataUrl(iconSvg);
			if (iconType === 'image' && iconImgUrl) return `url("${iconImgUrl}")`;
			return '';
		})();

		const rootRef = useRef(null);

		// Ensure the caret button exists in the editor preview (locked element).
		useEffect(() => {
			const root = rootRef.current;
			if (!root) return;
			const header = root.querySelector('.crispycohd-accordion-header');
			if (!header) return;
			if (header.querySelector('.crispycohd-accordion-caret-button')) return;
			const btn = document.createElement('button');
			btn.type = 'button';
			btn.className = 'crispycohd-accordion-caret-button';
			btn.setAttribute('aria-label', 'Toggle accordion');
			// Do not hijack editor selection. Clicking the button should still allow
			// selecting the block in the editor, so we only prevent the default toggle
			// behaviour in the editor.
			btn.addEventListener('click', (e) => e.preventDefault());
			header.appendChild(btn);
		}, [animation, iconType, iconSvg, iconImgUrl, caretSide]);

		const blockProps = useBlockProps({
			className: `crispycohd-accordion crispycohd-accordion--${animation}`,
			'data-cc-id': uniqueId || clientId.slice(0, 8),
			'data-duration': duration,
			'data-icon-type': iconType,
			...( iconType === 'svg' ? { 'data-icon-svg': iconSvg } : {} ),
			...( iconType === 'image' ? { 'data-icon-img': iconImgUrl } : {} ),
			'data-show-divider': showDivider,
			'data-caret-side': caretSide,
			'data-exclusive': exclusive,
			'data-default-open': defaultOpen,
			style: {
				'--crispycohd-duration': `${duration}ms`,
				...( caretIconOverride ? { '--cc-caret-icon': caretIconOverride } : {} ),
			},
		});

		return (
			<>
				<InspectorControls>
					{/* Animation */}
					<PanelBody title="Animation">
						<SelectControl
							label="Effect"
							value={animation}
							options={[
								{ label: 'Slide', value: 'slide' },
								{ label: 'Fade',  value: 'fade'  },
							]}
							onChange={(v) => setAttributes({ animation: v })}
						/>
						<RangeControl
							label="Duration (ms)"
							value={duration}
							min={100}
							max={2000}
							onChange={(v) => setAttributes({ duration: v })}
						/>
					</PanelBody>

					{/* Caret Icon */}
					<PanelBody title="Caret Icon" initialOpen={false}>
						<SelectControl
							label="Icon Source"
							value={iconType}
							options={[
								{ label: 'Built-in Caret', value: 'default' },
								{ label: 'Custom SVG',     value: 'svg'     },
								{ label: 'Custom Image',   value: 'image'   },
							]}
							onChange={(v) => setAttributes({ iconType: v })}
						/>
						{iconType === 'svg' && (
							<TextControl
								label="SVG Mark-up"
								value={iconSvg}
								onChange={(v) => setAttributes({ iconSvg: v })}
							/>
						)}
						{iconType === 'image' && (
							<MediaUploadCheck>
								<MediaUpload
									onSelect={(m) => setAttributes({ iconImgUrl: m.url })}
									allowedTypes={['image']}
									render={({ open }) => (
										<Button variant="secondary" onClick={open}>
											{iconImgUrl ? 'Replace Image' : 'Choose Image'}
										</Button>
									)}
								/>
							</MediaUploadCheck>
						)}
					</PanelBody>

					{/* Divider */}
					<PanelBody title="Divider" initialOpen={false}>
						<ToggleControl
							label="Show divider"
							checked={showDivider}
							onChange={(v) => setAttributes({ showDivider: v })}
						/>
					</PanelBody>

					{/* Interaction */}
					<PanelBody title="Interaction" initialOpen={false}>
						<ToggleControl
							label="Open by default"
							checked={defaultOpen}
							onChange={(v) => setAttributes({ defaultOpen: v })}
						/>
						<ToggleControl
							label="Exclusive open (close other accordions)"
							checked={exclusive}
							onChange={(v) => setAttributes({ exclusive: v })}
						/>
					</PanelBody>

					{/* Caret Position */}
					<PanelBody title="Caret Position" initialOpen={false}>
						<SelectControl
							label="Side"
							value={caretSide}
							options={[
								{ label: 'Right', value: 'right' },
								{ label: 'Left', value: 'left' },
							]}
							onChange={(v) => setAttributes({ caretSide: v })}
						/>
					</PanelBody>
				</InspectorControls>

				<div {...blockProps} ref={rootRef}>
					{/* Root lock stops extra root blocks; renderAppender=false hides "+" */}
					<InnerBlocks
						template={TEMPLATE}
						renderAppender={false}
					/>
				</div>
			</>
		);
	},

	save({ attributes }) {
		const { uniqueId, animation, duration, iconType, iconSvg, iconImgUrl, showDivider, caretSide, exclusive, defaultOpen } = attributes;

		const svgToDataUrl = (svg) => {
			if (!svg) return '';
			const encoded = encodeURIComponent(svg)
				.replace(/%0A/g, '')
				.replace(/%09/g, '')
				.replace(/%20/g, ' ');
			return `url("data:image/svg+xml;utf8,${encoded}")`;
		};

		const caretIconOverride = (() => {
			if (iconType === 'svg' && iconSvg) return svgToDataUrl(iconSvg);
			if (iconType === 'image' && iconImgUrl) return `url("${iconImgUrl}")`;
			return '';
		})();

		const dataAttrs = {
			className: `crispycohd-accordion crispycohd-accordion--${animation}${defaultOpen ? ' is-open' : ''}`,
			'data-cc-id': uniqueId || '',
			'data-duration': duration,
			'data-icon-type': iconType,
			'data-show-divider': showDivider,
			'data-caret-side': caretSide,
			'data-exclusive': exclusive,
			'data-default-open': defaultOpen,
			style: {
				'--crispycohd-duration': `${duration}ms`,
				...( caretIconOverride ? { '--cc-caret-icon': caretIconOverride } : {} ),
			},
		};
		if (iconType === 'svg')   dataAttrs['data-icon-svg']  = iconSvg;
		if (iconType === 'image') dataAttrs['data-icon-img']  = iconImgUrl;

		return (
			<div {...useBlockProps.save(dataAttrs)}>
				<InnerBlocks.Content />
			</div>
		);
	},
});
