/**
 * SEOvault HowTo block editor.
 *
 * Authors edit visible step-by-step content like a normal block. Schema
 * emission is deferred; this UI only reports setup readiness.
 */

import { __ } from '@wordpress/i18n';
import {
	useBlockProps,
	InspectorControls,
	RichText,
	BlockControls,
	MediaUpload,
	MediaUploadCheck,
} from '@wordpress/block-editor';
import {
	PanelBody,
	TextControl,
	TextareaControl,
	SelectControl,
	Button,
	ToolbarGroup,
	ToolbarButton,
	Notice,
} from '@wordpress/components';
import { useEffect, useRef } from '@wordpress/element';
import {
	createEmptyStep,
	ensureStableIds,
	insertStep,
	updateStepAt,
	removeStepAt,
	reorderSteps,
} from './utils/steps';
import {
	appendStringItem,
	removeStringAt,
	updateStringAt,
} from './utils/string-list';
import { getHowToSetupStatus } from './utils/setup-status';

const STYLE_OPTIONS = [
	{ label: __('Clean', 'seovault-ai'), value: 'clean' },
	{ label: __('Bordered', 'seovault-ai'), value: 'bordered' },
	{ label: __('Soft cards', 'seovault-ai'), value: 'soft-cards' },
	{ label: __('Editorial', 'seovault-ai'), value: 'editorial' },
	{ label: __('Minimal', 'seovault-ai'), value: 'minimal' },
	{ label: __('Dark', 'seovault-ai'), value: 'dark' },
];

const COLOR_OPTIONS = [
	{ label: __('Blue', 'seovault-ai'), value: 'blue' },
	{ label: __('Green', 'seovault-ai'), value: 'green' },
	{ label: __('Purple', 'seovault-ai'), value: 'purple' },
	{ label: __('Orange', 'seovault-ai'), value: 'orange' },
	{ label: __('Dark', 'seovault-ai'), value: 'dark' },
	{ label: __('Neutral', 'seovault-ai'), value: 'neutral' },
];

const DENSITY_OPTIONS = [
	{ label: __('Compact', 'seovault-ai'), value: 'compact' },
	{ label: __('Comfortable', 'seovault-ai'), value: 'comfortable' },
	{ label: __('Spacious', 'seovault-ai'), value: 'spacious' },
];

const DISPLAY_OPTIONS = [
	{ label: __('Numbered list', 'seovault-ai'), value: 'numbered' },
	{ label: __('Cards', 'seovault-ai'), value: 'cards' },
	{ label: __('Compact', 'seovault-ai'), value: 'compact' },
];

/**
 * @param {Object}   props
 * @param {Object}   props.attributes
 * @param {Function} props.setAttributes
 * @return {JSX.Element} Editor.
 */
export default function Edit({ attributes, setAttributes }) {
	const {
		name = '',
		description = '',
		steps = [],
		supplies = [],
		tools = [],
		totalTime = '',
		estimatedCost = { currency: '', value: '' },
		displayMode = 'numbered',
		stylePreset = 'clean',
		colorPreset = 'blue',
		density = 'comfortable',
		schemaVersion = 1,
	} = attributes;

	const normalizedSteps = ensureStableIds(steps);
	const supplyRows = Array.isArray(supplies) ? supplies.map((item) => String(item ?? '')) : [];
	const toolRows = Array.isArray(tools) ? tools.map((item) => String(item ?? '')) : [];
	const cost =
		estimatedCost && typeof estimatedCost === 'object'
			? estimatedCost
			: { currency: '', value: '' };
	const setup = getHowToSetupStatus({
		name,
		description,
		steps: normalizedSteps,
		supplies: supplyRows,
		tools: toolRows,
		totalTime,
		estimatedCost: cost,
	});
	const seededRef = useRef(false);
	const listRef = useRef(null);

	useEffect(() => {
		if (seededRef.current) {
			return;
		}
		seededRef.current = true;
		const needsSeed =
			!Array.isArray(steps) ||
			steps.length === 0 ||
			steps.some((step) => !step || !step.id) ||
			schemaVersion !== 1;
		if (needsSeed) {
			const nextSteps =
				!Array.isArray(steps) || steps.length === 0
					? [createEmptyStep(), createEmptyStep()]
					: ensureStableIds(steps);
			setAttributes({
				steps: nextSteps,
				schemaVersion: 1,
			});
		}
	}, [steps, schemaVersion, setAttributes]);

	const blockProps = useBlockProps({
		className: [
			'seovault-howto-block-editor',
			`seovault-howto-block-editor--${displayMode}`,
			`is-setup-${setup.status}`,
		].join(' '),
		'data-howto-setup': setup.status,
	});

	const setSteps = (next) => {
		setAttributes({ steps: ensureStableIds(next) });
	};

	const focusStepName = (index) => {
		window.requestAnimationFrame(() => {
			const root = listRef.current;
			if (!root) {
				return;
			}
			const field = root.querySelector(
				`[data-howto-editor-index="${index}"] .seovault-howto-block-editor__step-name input, [data-howto-editor-index="${index}"] .seovault-howto-block-editor__step-name textarea`
			);
			if (field && typeof field.focus === 'function') {
				field.focus();
			}
		});
	};

	const onAddStep = () => {
		const next = insertStep(normalizedSteps);
		setSteps(next);
		focusStepName(next.length - 1);
	};

	const onRemoveStep = (index) => {
		setSteps(removeStepAt(normalizedSteps, index));
	};

	const onMoveStep = (index, direction) => {
		const to = index + direction;
		setSteps(reorderSteps(normalizedSteps, index, to));
	};

	const noticeStatus =
		setup.status === 'ready_for_schema'
			? 'success'
			: setup.status === 'incomplete'
				? 'warning'
				: 'info';

	const setupLabel =
		setup.status === 'ready_for_schema'
			? __('How-to content ready (schema pending save)', 'seovault-ai')
			: setup.status === 'incomplete'
				? __('How-to setup incomplete', 'seovault-ai')
				: __('How-to setup', 'seovault-ai');

	const setupMessage =
		setup.status === 'ready_for_schema'
			? __(
					'Visible How-to content is ready. Schema publishing is handled separately by SEOvault when this post is saved — this block does not inject JSON-LD by itself.',
					'seovault-ai'
				)
			: setup.status === 'incomplete'
				? __(
						'Finish a how-to name and at least one complete step. Incomplete steps stay in the editor but are excluded from schema.',
						'seovault-ai'
					)
				: __(
						'Add a how-to name and ordered steps readers will see. Schema is not published until the minimum content exists.',
						'seovault-ai'
					);

	return (
		<>
			<BlockControls>
				<ToolbarGroup>
					<ToolbarButton
						icon="plus"
						label={__('Add step', 'seovault-ai')}
						onClick={onAddStep}
					/>
				</ToolbarGroup>
			</BlockControls>
			<InspectorControls>
				<PanelBody title={__('How-to display', 'seovault-ai')} initialOpen={true}>
					<SelectControl
						label={__('Display mode', 'seovault-ai')}
						value={displayMode}
						options={DISPLAY_OPTIONS}
						onChange={(value) => setAttributes({ displayMode: value })}
					/>
					<SelectControl
						label={__('Style preset', 'seovault-ai')}
						value={stylePreset}
						options={STYLE_OPTIONS}
						onChange={(value) => setAttributes({ stylePreset: value })}
					/>
					<SelectControl
						label={__('Color', 'seovault-ai')}
						value={colorPreset}
						options={COLOR_OPTIONS}
						onChange={(value) => setAttributes({ colorPreset: value })}
					/>
					<SelectControl
						label={__('Density', 'seovault-ai')}
						value={density}
						options={DENSITY_OPTIONS}
						onChange={(value) => setAttributes({ density: value })}
					/>
				</PanelBody>
				<PanelBody title={__('Time and cost', 'seovault-ai')} initialOpen={false}>
					<TextControl
						label={__('Total time (ISO-8601)', 'seovault-ai')}
						help={__(
							'Optional. Examples: PT30M, PT1H30M, P1DT2H. Invalid values are cleared on save.',
							'seovault-ai'
						)}
						value={totalTime}
						onChange={(value) => setAttributes({ totalTime: value })}
						placeholder="PT30M"
					/>
					<TextControl
						label={__('Cost currency (ISO 4217)', 'seovault-ai')}
						help={__('Optional three-letter code, e.g. USD.', 'seovault-ai')}
						value={cost.currency || ''}
						onChange={(value) =>
							setAttributes({
								estimatedCost: {
									currency: value,
									value: cost.value || '',
								},
							})
						}
						placeholder="USD"
					/>
					<TextControl
						label={__('Estimated cost', 'seovault-ai')}
						help={__(
							'Optional numeric amount. Currency and value must both be set.',
							'seovault-ai'
						)}
						value={cost.value === undefined || cost.value === null ? '' : String(cost.value)}
						onChange={(value) =>
							setAttributes({
								estimatedCost: {
									currency: cost.currency || '',
									value,
								},
							})
						}
						placeholder="0"
					/>
				</PanelBody>
			</InspectorControls>
			<div {...blockProps}>
				<Notice
					status={noticeStatus}
					isDismissible={false}
					className="seovault-howto-block-editor__status"
					spokenMessage={`${setupLabel}. ${setupMessage}`}
				>
					<strong>{setupLabel}</strong>
					<span className="seovault-howto-block-editor__status-text">
						{' '}
						{setupMessage}
					</span>
					{setup.completeCount > 0 && (
						<span
							className="seovault-howto-block-editor__status-count"
							aria-live="polite"
						>
							{' '}
							{sprintfComplete(setup.completeCount)}
						</span>
					)}
				</Notice>
				<div className="seovault-howto-block-editor__header">
					<TextControl
						label={__('How-to name', 'seovault-ai')}
						value={name}
						onChange={(value) => setAttributes({ name: value })}
						placeholder={__('How to…', 'seovault-ai')}
					/>
					<TextareaControl
						label={__('Summary', 'seovault-ai')}
						value={description}
						onChange={(value) => setAttributes({ description: value })}
						rows={2}
						placeholder={__(
							'Optional short summary for readers.',
							'seovault-ai'
						)}
					/>
				</div>

				<StringListEditor
					title={__('Supplies', 'seovault-ai')}
					addLabel={__('Add supply', 'seovault-ai')}
					itemLabel={__('Supply', 'seovault-ai')}
					rows={supplyRows}
					onChange={(next) => setAttributes({ supplies: next })}
				/>

				<StringListEditor
					title={__('Tools', 'seovault-ai')}
					addLabel={__('Add tool', 'seovault-ai')}
					itemLabel={__('Tool', 'seovault-ai')}
					rows={toolRows}
					onChange={(next) => setAttributes({ tools: next })}
				/>

				<div
					className="seovault-howto-block-editor__list"
					ref={listRef}
					role="list"
					aria-label={__('How-to steps', 'seovault-ai')}
				>
					{normalizedSteps.map((step, index) => (
						<div
							className="seovault-howto-block-editor__item"
							key={step.id}
							role="listitem"
							data-howto-editor-index={index}
							data-howto-step-id={step.id}
						>
							<div className="seovault-howto-block-editor__item-toolbar">
								<span className="seovault-howto-block-editor__item-label">
									{`${index + 1}. `}
									{__('Step', 'seovault-ai')}
								</span>
								<div className="seovault-howto-block-editor__item-actions">
									<Button
										variant="tertiary"
										size="small"
										disabled={index === 0}
										onClick={() => onMoveStep(index, -1)}
										aria-label={__('Move step up', 'seovault-ai')}
									>
										{__('Up', 'seovault-ai')}
									</Button>
									<Button
										variant="tertiary"
										size="small"
										disabled={index === normalizedSteps.length - 1}
										onClick={() => onMoveStep(index, 1)}
										aria-label={__('Move step down', 'seovault-ai')}
									>
										{__('Down', 'seovault-ai')}
									</Button>
									<Button
										isDestructive
										variant="tertiary"
										size="small"
										onClick={() => onRemoveStep(index)}
										aria-label={__('Remove step', 'seovault-ai')}
									>
										{__('Remove', 'seovault-ai')}
									</Button>
								</div>
							</div>
							<div className="seovault-howto-block-editor__step-name">
								<TextControl
									hideLabelFromVision
									label={__('Step name', 'seovault-ai')}
									value={step.name || ''}
									onChange={(value) =>
										setSteps(
											updateStepAt(normalizedSteps, index, { name: value })
										)
									}
									placeholder={__('Step title…', 'seovault-ai')}
								/>
							</div>
							<div className="seovault-howto-block-editor__step-text">
								<span className="components-base-control__label">
									{__('Step instructions', 'seovault-ai')}
								</span>
								<RichText
									tagName="div"
									className="seovault-howto-block-editor__step-rich"
									value={step.text || ''}
									onChange={(value) =>
										setSteps(
											updateStepAt(normalizedSteps, index, { text: value })
										)
									}
									placeholder={__('Describe this step…', 'seovault-ai')}
									allowedFormats={[
										'core/bold',
										'core/italic',
										'core/link',
									]}
								/>
							</div>
							<div className="seovault-howto-block-editor__step-media">
								<MediaUploadCheck>
									<MediaUpload
										onSelect={(media) =>
											setSteps(
												updateStepAt(normalizedSteps, index, {
													imageId: media && media.id ? media.id : 0,
												})
											)
										}
										allowedTypes={['image']}
										value={step.imageId || 0}
										render={({ open }) => (
											<div className="seovault-howto-block-editor__media-row">
												{step.imageId ? (
													<span className="seovault-howto-block-editor__media-id">
														{__('Image selected', 'seovault-ai')}
														{` (#${step.imageId})`}
													</span>
												) : (
													<span className="seovault-howto-block-editor__media-id">
														{__('No step image', 'seovault-ai')}
													</span>
												)}
												<Button
													variant="secondary"
													size="small"
													onClick={open}
													aria-label={__(
														'Select or change step image',
														'seovault-ai'
													)}
												>
													{step.imageId
														? __('Change image', 'seovault-ai')
														: __('Add image', 'seovault-ai')}
												</Button>
												{!!step.imageId && (
													<Button
														variant="tertiary"
														size="small"
														isDestructive
														onClick={() =>
															setSteps(
																updateStepAt(normalizedSteps, index, {
																	imageId: 0,
																})
															)
														}
														aria-label={__(
															'Remove step image',
															'seovault-ai'
														)}
													>
														{__('Remove image', 'seovault-ai')}
													</Button>
												)}
											</div>
										)}
									/>
								</MediaUploadCheck>
							</div>
						</div>
					))}
				</div>
				<div className="seovault-howto-block-editor__footer">
					<Button variant="secondary" onClick={onAddStep}>
						{__('Add step', 'seovault-ai')}
					</Button>
				</div>
			</div>
		</>
	);
}

/**
 * Repeatable plain-string list editor (supplies / tools).
 *
 * @param {Object}   props
 * @param {string}   props.title
 * @param {string}   props.addLabel
 * @param {string}   props.itemLabel
 * @param {string[]} props.rows
 * @param {Function} props.onChange
 * @return {JSX.Element} List editor.
 */
function StringListEditor({ title, addLabel, itemLabel, rows, onChange }) {
	return (
		<div className="seovault-howto-block-editor__string-list">
			<div className="seovault-howto-block-editor__string-list-header">
				<span className="seovault-howto-block-editor__item-label">{title}</span>
				<Button
					variant="tertiary"
					size="small"
					onClick={() => onChange(appendStringItem(rows))}
				>
					{addLabel}
				</Button>
			</div>
			{rows.length === 0 ? (
				<p className="seovault-howto-block-editor__string-list-empty">
					{__('Optional. Add items readers need for this how-to.', 'seovault-ai')}
				</p>
			) : (
				<ul className="seovault-howto-block-editor__string-list-items" role="list">
					{rows.map((row, index) => (
						<li key={`${itemLabel}-${index}`} role="listitem">
							<TextControl
								label={`${itemLabel} ${index + 1}`}
								hideLabelFromVision
								value={row}
								onChange={(value) =>
									onChange(updateStringAt(rows, index, value))
								}
								placeholder={itemLabel}
							/>
							<Button
								variant="tertiary"
								size="small"
								isDestructive
								onClick={() => onChange(removeStringAt(rows, index))}
								aria-label={`${__('Remove', 'seovault-ai')} ${itemLabel} ${index + 1}`}
							>
								{__('Remove', 'seovault-ai')}
							</Button>
						</li>
					))}
				</ul>
			)}
		</div>
	);
}

/**
 * @param {number} count Complete step count.
 * @return {string} Localized count phrase.
 */
function sprintfComplete(count) {
	return count === 1
		? __('1 complete step.', 'seovault-ai')
		: `${count} ${__('complete steps.', 'seovault-ai')}`;
}
