/**
 * Per-button direct style properties (WordPress-like).
 * Optional library reference for centralized button styles.
 * Fields are gated by variant `styleSupports` from the buttons field schema.
 */
import {
	Button,
	ColorIndicator,
	Dropdown,
	TextControl,
	__experimentalDropdownContentWrapper as DropdownContentWrapper,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { useState } from '@wordpress/element';
import SearchableSelect from '../SearchableSelect';
import ShadowFields from '../ShadowFields';
import FlexibleUnitControl from '../FlexibleUnitControl';
import FontSizeField from '../FontSizeField';
import ThemeColorPalette from '../ThemeColorPalette';
import BoxBorderField from '../BoxBorderField';
import BoxRadiusField from '../BoxRadiusField';
import {
	colorDropdownPopoverProps,
	useColorDropdownOutsideClose,
} from '../colorDropdownFocus';
import { useThemeTokens } from '../../hooks/useThemeTokens';
import {
	DEFAULT_BUTTON_ICON_SIZE,
	resolveButtonIconSize,
} from '../../shared/buttonIcon';
import {
	BUTTON_ICON_POSITION_OPTIONS,
	BUTTON_ITEM_BORDER_VAR_ROOT,
	BUTTON_ITEM_RADIUS_ALL_VAR,
	BUTTON_ITEM_RADIUS_FIELD_KEY,
	BUTTON_SIZE_OPTIONS,
	BUTTON_SIZE_PRESETS,
	BUTTON_STYLE_SUPPORTS_ALL,
	buttonItemBorderFieldValues,
	buttonItemStylePatchFromBorderVars,
	buttonSupports,
	normalizeButtonStyleItem,
} from '../../shared/buttonStyleBaseline';
import ButtonIconPicker from './ButtonIconPicker';
const BUTTON_ICON_SIZE_UNITS = [
	{ value: 'px', label: 'px', default: 20 },
	{ value: 'rem', label: 'rem', default: 1.25 },
	{ value: 'em', label: 'em', default: 1 },
];

const PAD_UNITS = [
	{ value: 'rem', label: 'rem', default: 0.75 },
	{ value: 'px', label: 'px', default: 12 },
	{ value: 'em', label: 'em', default: 0.75 },
];

function ColorRow( { label, value, onChange, colors } ) {
	const [ open, setOpen ] = useState( false );
	const close = () => setOpen( false );
	const hostRef = useColorDropdownOutsideClose( open, close );

	return (
		<div className="bm-repeater__color">
			<span className="bm-repeater__color-label">{ label }</span>
			<div ref={ hostRef } className="bm-color-dropdown-host">
				<Dropdown
					open={ open }
					onToggle={ setOpen }
					onClose={ close }
					className="bm-color-dropdown"
					contentClassName="bm-color-dropdown__content"
					popoverProps={ colorDropdownPopoverProps( close ) }
					renderToggle={ ( { isOpen, onToggle } ) => (
						<Button
							className="bm-color-dropdown__toggle"
							variant="secondary"
							onClick={ onToggle }
							aria-expanded={ isOpen }
							aria-label={ label }
							__next40pxDefaultSize
						>
							<ColorIndicator
								className="bm-color-dropdown__indicator"
								colorValue={ value || undefined }
							/>
							<span className="bm-color-dropdown__label">
								{ value || __( 'Select', 'joc-blockora-morph' ) }
							</span>
						</Button>
					) }
					renderContent={ () => (
						<DropdownContentWrapper paddingSize="medium">
							<div className="bm-color-dropdown__panel">
								<ThemeColorPalette
									palettes={ colors }
									value={ value || '' }
									onChange={ ( next ) =>
										onChange(
											next == null ||
												String( next ).trim() === ''
												? ''
												: next
										)
									}
									clearable
									enableAlpha
								/>
							</div>
						</DropdownContentWrapper>
					) }
				/>
			</div>
		</div>
	);
}

function Panel( { title, children } ) {
	return (
		<div className="bm-btn-style-panel">
			<strong className="bm-btn-style-panel__title">{ title }</strong>
			<div className="bm-btn-style-panel__body">{ children }</div>
		</div>
	);
}

/**
 * @param {object}   props
 * @param {object}   props.item
 * @param {Function} props.onChange
 * @param {string[]} [props.styleSupports]
 * @param {Array}    [props.buttonLibrary]
 * @param {Array}    [props.fontFamilyOptions]
 * @param {Array}    [props.colorPalettes]
 * @param {string}   [props.title]
 * @param {number}   [props.buttonIndex]
 * @param {boolean}  [props.focus]
 * @param {Function} [props.onRemove]
 * @param {Function} [props.onDuplicate]
 * @param {boolean}  [props.showContent] Label / URL (Fields only; icon picker is always available).
 */
export default function ButtonItemStyleEditor( {
	item,
	onChange,
	styleSupports = BUTTON_STYLE_SUPPORTS_ALL,
	buttonLibrary = [],
	fontFamilyOptions = [],
	colorPalettes = [],
	title,
	buttonIndex,
	focus = false,
	onRemove,
	onDuplicate,
	showContent = false,
} ) {
	const { fontSizes: themeFontSizes } = useThemeTokens();
	const supports = Array.isArray( styleSupports )
		? styleSupports
		: BUTTON_STYLE_SUPPORTS_ALL;
	const hasLibrary = Array.isArray( buttonLibrary ) && buttonLibrary.length > 0;
	const rawLibId = Number( item?.libraryBlockId );
	const libraryId =
		Number.isFinite( rawLibId ) && rawLibId !== 0 ? rawLibId : null;
	// styleMode alone drives Source — id may be empty until a Button is chosen.
	const mode =
		String( item?.styleMode || '' ).toLowerCase() === 'library'
			? 'library'
			: 'custom';
	const libEntry =
		mode === 'library' && libraryId != null
			? buttonLibrary.find( ( b ) => Number( b.id ) === libraryId )
			: null;
	const isLibrarySource = mode === 'library' && libraryId != null;
	// Style reference: Design from My Block; label / URL / icon + position stay on this placement.
	const normalized = normalizeButtonStyleItem(
		isLibrarySource && libEntry?.styles
			? {
					...( libEntry.styles || {} ),
					icon:
						String( item?.icon || '' ).trim() !== ''
							? String( item.icon )
							: String( libEntry.styles?.icon || '' ),
					iconPosition:
						item?.iconPosition ||
						normalizeButtonStyleItem( item || {} ).iconPosition,
					styleMode: 'library',
					libraryBlockId: libraryId,
			  }
			: item || {}
	);
	const patchItem = ( partial ) => onChange( { ...item, ...partial } );
	const patch = ( partial ) => {
		if ( isLibrarySource ) {
			const keys = Object.keys( partial || {} ).filter(
				( key ) => key !== 'styleMode' && key !== 'libraryBlockId'
			);
			// Placement-only content — never write Design back to My Blocks.
			const placementOnly = keys.every( ( key ) =>
				[ 'link', 'icon', 'iconPosition' ].includes( key )
			);
			if ( ! placementOnly ) {
				return;
			}
		}
		patchItem( partial );
	};
	const iconSize = resolveButtonIconSize( normalized.iconSize );
	const sizeOptions = BUTTON_SIZE_OPTIONS.map( ( opt ) => ( {
		...opt,
		label:
			opt.value === 'small'
				? __( 'Small', 'joc-blockora-morph' )
				: opt.value === 'medium'
				? __( 'Medium', 'joc-blockora-morph' )
				: opt.value === 'large'
				? __( 'Large', 'joc-blockora-morph' )
				: __( 'Custom', 'joc-blockora-morph' ),
	} ) );
	const iconPosOptions = BUTTON_ICON_POSITION_OPTIONS.map( ( opt ) => ( {
		...opt,
		label:
			opt.value === 'right'
				? __( 'Right', 'joc-blockora-morph' )
				: __( 'Left', 'joc-blockora-morph' ),
	} ) );
	const libOptions = [
		{ label: __( '— Choose a button —', 'joc-blockora-morph' ), value: '' },
		...buttonLibrary.map( ( b ) => ( {
			label: b.title || b.name || `#${ b.id }`,
			value: String( b.id ),
		} ) ),
	];
	const styleOptions = [
		{ label: __( 'Custom', 'joc-blockora-morph' ), value: 'custom' },
	];
	if ( hasLibrary ) {
		styleOptions.push( {
			label: __( 'From button library', 'joc-blockora-morph' ),
			value: 'library',
		} );
	}

	const applySize = ( next ) => {
		const size = next || 'medium';
		if ( size === 'custom' ) {
			patch( { size: 'custom' } );
			return;
		}
		const pad = BUTTON_SIZE_PRESETS[ size ] || BUTTON_SIZE_PRESETS.medium;
		patch( {
			size,
			padY: pad.padY,
			padX: pad.padX,
		} );
	};

	const applyLibraryButton = ( nextId ) => {
		const parsed = nextId !== '' && nextId != null ? Number( nextId ) : NaN;
		const id = Number.isFinite( parsed ) && parsed !== 0 ? parsed : null;
		// Reference only — Design comes from the live Button catalog.
		patchItem( {
			styleMode: 'library',
			libraryBlockId: id,
		} );
	};

	return (
		<div
			className={
				'bm-repeater__button-styles bm-btn-style' +
				( focus ? ' is-focused' : '' ) +
				( mode === 'library' ? ' is-library-source' : '' )
			}
			data-bm-btn-style={
				typeof buttonIndex === 'number' ? String( buttonIndex ) : undefined
			}
			id={
				typeof buttonIndex === 'number'
					? `bm-btn-style-${ buttonIndex }`
					: undefined
			}
		>
			{ title ||
			typeof onRemove === 'function' ||
			typeof onDuplicate === 'function' ? (
				<div className="bm-btn-style__header">
					{ title ? (
						<strong className="bm-repeater__group-title">
							{ title }
						</strong>
					) : null }
					{ typeof onDuplicate === 'function' ||
					typeof onRemove === 'function' ? (
						<div className="bm-btn-style__header-actions">
							{ typeof onDuplicate === 'function' ? (
								<Button
									size="small"
									variant="tertiary"
									onClick={ onDuplicate }
								>
									{ __( 'Duplicate', 'joc-blockora-morph' ) }
								</Button>
							) : null }
							{ typeof onRemove === 'function' ? (
								<Button
									size="small"
									variant="tertiary"
									isDestructive
									onClick={ onRemove }
								>
									{ __( 'Remove', 'joc-blockora-morph' ) }
								</Button>
							) : null }
						</div>
					) : null }
				</div>
			) : null }

			{ hasLibrary ? (
				<div className="bm-btn-style__source">
					<Panel title={ __( 'Style reference', 'joc-blockora-morph' ) }>
						<SearchableSelect
							label={ __( 'Source', 'joc-blockora-morph' ) }
							value={ mode }
							options={ styleOptions }
							onChange={ ( next ) => {
								const nextMode =
									next === 'library' ? 'library' : 'custom';
								if ( nextMode === 'library' ) {
									// Keep / restore libraryBlockId — do not clear on Custom toggles.
									patchItem( {
										styleMode: 'library',
										libraryBlockId: libraryId,
									} );
									return;
								}
								// Snapshot current Design into the placement so Custom stays editable
								// without losing the linked Button id for switching back.
								patchItem( {
									...normalizeButtonStyleItem( normalized ),
									styleMode: 'custom',
									libraryBlockId: libraryId,
								} );
							} }
							help={
								isLibrarySource
									? __(
											'Colors and size come from the Button My Block. Label, URL, and icon stay on this placement only.',
											'joc-blockora-morph'
									  )
									: __(
											'Use a downloaded Button block as a shared style. Switch Source to Custom to keep placement-only Design.',
											'joc-blockora-morph'
									  )
							}
							searchableThreshold={ 99 }
						/>
						{ mode === 'library' ? (
							<SearchableSelect
								label={ __( 'Button', 'joc-blockora-morph' ) }
								value={
									libraryId != null
										? String( libraryId )
										: ''
								}
								options={ libOptions }
								onChange={ applyLibraryButton }
								searchableThreshold={ 6 }
							/>
						) : null }
					</Panel>
				</div>
			) : null }

			{ mode === 'library' && ! isLibrarySource ? (
				<p className="bm-btn-style__locked-note">
					{ __(
						'Choose a Button from the Style reference list, or switch Source to Custom for this placement only.',
						'joc-blockora-morph'
					) }
				</p>
			) : isLibrarySource ? (
				<div className="bm-btn-style__styles">
					<p className="bm-btn-style__locked-note">
						{ __(
							'Colors, size, and icon tint come from My Blocks. Icon glyph and position stay on this placement.',
							'joc-blockora-morph'
						) }
					</p>
					{ buttonSupports( supports, 'icon' ) ? (
						<Panel title={ __( 'Icon', 'joc-blockora-morph' ) }>
							<div className="bm-btn-style__icon-pick">
								<span className="bm-repeater__color-label">
									{ __( 'Icon', 'joc-blockora-morph' ) }
								</span>
								<ButtonIconPicker
									value={ normalized.icon || '' }
									onChange={ ( next ) =>
										patch( { icon: next || '' } )
									}
								/>
							</div>
							<div className="bm-repeater__icon-styles">
								<SearchableSelect
									label={ __(
										'Position',
										'joc-blockora-morph'
									) }
									value={ normalized.iconPosition }
									options={ iconPosOptions }
									onChange={ ( next ) =>
										patch( {
											iconPosition:
												next === 'right'
													? 'right'
													: 'left',
										} )
									}
									searchableThreshold={ 99 }
								/>
							</div>
						</Panel>
					) : null }
				</div>
			) : (
				<div className="bm-btn-style__styles">
					{ showContent ? (
						<Panel title={ __( 'Content', 'joc-blockora-morph' ) }>
							<TextControl
								label={ __( 'Label', 'joc-blockora-morph' ) }
								value={ String( item?.link?.title ?? '' ) }
								onChange={ ( next ) =>
									patch( {
										link: {
											...( item?.link &&
											typeof item.link === 'object'
												? item.link
												: {} ),
											title: next,
											url:
												item?.link?.url != null
													? item.link.url
													: '#',
										},
									} )
								}
							/>
							<TextControl
								label={ __( 'URL', 'joc-blockora-morph' ) }
								value={ String( item?.link?.url ?? '' ) }
								onChange={ ( next ) =>
									patch( {
										link: {
											...( item?.link &&
											typeof item.link === 'object'
												? item.link
												: {} ),
											title: item?.link?.title ?? '',
											url: next,
										},
									} )
								}
								type="url"
							/>
						</Panel>
					) : null }

					<div className="bm-repeater__custom">
						{ buttonSupports( supports, 'colors' ) ? (
							<Panel title={ __( 'Color', 'joc-blockora-morph' ) }>
								<div className="bm-repeater__color-grid">
									<ColorRow
										label={ __(
											'Background',
											'joc-blockora-morph'
										) }
										value={ normalized.bg }
										onChange={ ( next ) =>
											patch( { bg: next } )
										}
										colors={ colorPalettes }
									/>
									<ColorRow
										label={ __( 'Text', 'joc-blockora-morph' ) }
										value={ normalized.color }
										onChange={ ( next ) =>
											patch( { color: next } )
										}
										colors={ colorPalettes }
									/>
									<ColorRow
										label={ __(
											'Background (hover)',
											'joc-blockora-morph'
										) }
										value={ normalized.bgHover }
										onChange={ ( next ) =>
											patch( { bgHover: next } )
										}
										colors={ colorPalettes }
									/>
									<ColorRow
										label={ __(
											'Text (hover)',
											'joc-blockora-morph'
										) }
										value={ normalized.colorHover }
										onChange={ ( next ) =>
											patch( { colorHover: next } )
										}
										colors={ colorPalettes }
									/>
								</div>
							</Panel>
						) : null }

						{ buttonSupports( supports, 'fontFamily' ) ? (
							<Panel
								title={ __( 'Typography', 'joc-blockora-morph' ) }
							>
								<SearchableSelect
									label={ __(
										'Font family',
										'joc-blockora-morph'
									) }
									value={ normalized.fontFamily }
									options={ fontFamilyOptions }
									onChange={ ( next ) =>
										patch( { fontFamily: next || '' } )
									}
									searchableThreshold={ 1 }
									previewFontFamily
								/>
								<FontSizeField
									label={ __(
										'Size',
										'joc-blockora-morph'
									) }
									fontSizes={ themeFontSizes }
									value={ normalized.fontSize || '' }
									onChange={ ( next ) =>
										patch( { fontSize: next || '' } )
									}
								/>
							</Panel>
						) : null }

						{ buttonSupports( supports, 'size' ) ||
						buttonSupports( supports, 'padding' ) ? (
							<Panel
								title={ __( 'Dimensions', 'joc-blockora-morph' ) }
							>
								{ buttonSupports( supports, 'size' ) ? (
									<SearchableSelect
										label={ __(
											'Button size',
											'joc-blockora-morph'
										) }
										value={ normalized.size }
										options={ sizeOptions }
										onChange={ applySize }
										searchableThreshold={ 99 }
									/>
								) : null }
								{ buttonSupports( supports, 'padding' ) ? (
									<div className="bm-btn-style-panel__row">
										<FlexibleUnitControl
											label={ __(
												'Padding Y',
												'joc-blockora-morph'
											) }
											value={ normalized.padY }
											onChange={ ( next ) =>
												patch( {
													size: 'custom',
													padY:
														next || normalized.padY,
												} )
											}
											units={ PAD_UNITS }
										/>
										<FlexibleUnitControl
											label={ __(
												'Padding X',
												'joc-blockora-morph'
											) }
											value={ normalized.padX }
											onChange={ ( next ) =>
												patch( {
													size: 'custom',
													padX:
														next || normalized.padX,
												} )
											}
											units={ PAD_UNITS }
										/>
									</div>
								) : null }
							</Panel>
						) : null }

						{ buttonSupports( supports, 'borderRadius' ) ? (
							<Panel title={ __( 'Border', 'joc-blockora-morph' ) }>
								<BoxBorderField
									field={ {
										key: BUTTON_ITEM_BORDER_VAR_ROOT,
										label: __(
											'Border',
											'joc-blockora-morph'
										),
										defaultWidth: '0px',
										defaultStyle: 'none',
										defaultColor: 'transparent',
										defaultSides: {
											top: '0',
											right: '0',
											bottom: '0',
											left: '0',
										},
									} }
									values={ buttonItemBorderFieldValues(
										normalized
									) }
									onChange={ ( next ) =>
										patch(
											buttonItemStylePatchFromBorderVars(
												next
											)
										)
									}
								/>
								<BoxRadiusField
									field={ {
										key: BUTTON_ITEM_RADIUS_FIELD_KEY,
										allKey: BUTTON_ITEM_RADIUS_ALL_VAR,
										label: __(
											'Radius',
											'joc-blockora-morph'
										),
									} }
									values={ buttonItemBorderFieldValues(
										normalized
									) }
									onChange={ ( next ) =>
										patch(
											buttonItemStylePatchFromBorderVars(
												next
											)
										)
									}
								/>
							</Panel>
						) : null }

						{ buttonSupports( supports, 'boxShadow' ) ? (
							<Panel title={ __( 'Shadow', 'joc-blockora-morph' ) }>
								<ShadowFields
									label={ __(
										'Box shadow',
										'joc-blockora-morph'
									) }
									preset={ normalized.shadowPreset }
									color={ normalized.shadowColor }
									css={ normalized.shadow || 'none' }
									colorPalettes={ colorPalettes }
									onChange={ ( next ) =>
										patch( {
											shadowPreset: next.preset,
											shadowColor: next.color,
											shadow: next.css,
										} )
									}
								/>
							</Panel>
						) : null }

						{ buttonSupports( supports, 'icon' ) ? (
							<Panel title={ __( 'Icon', 'joc-blockora-morph' ) }>
								<div className="bm-btn-style__icon-pick">
									<span className="bm-repeater__color-label">
										{ __( 'Icon', 'joc-blockora-morph' ) }
									</span>
									<ButtonIconPicker
										value={ normalized.icon || '' }
										onChange={ ( next ) =>
											patch( { icon: next || '' } )
										}
									/>
								</div>
								<div className="bm-repeater__icon-styles">
									<SearchableSelect
										label={ __(
											'Position',
											'joc-blockora-morph'
										) }
										value={ normalized.iconPosition }
										options={ iconPosOptions }
										onChange={ ( next ) =>
											patch( {
												iconPosition:
													next === 'right'
														? 'right'
														: 'left',
											} )
										}
										searchableThreshold={ 99 }
									/>
									<FlexibleUnitControl
										label={ __( 'Size', 'joc-blockora-morph' ) }
										className="bm-repeater__icon-size-control"
										value={ iconSize }
										onChange={ ( next ) =>
											patch( {
												iconSize: resolveButtonIconSize(
													next ||
														DEFAULT_BUTTON_ICON_SIZE
												),
											} )
										}
										units={ BUTTON_ICON_SIZE_UNITS }
									/>
									<div className="bm-repeater__color-grid">
										<ColorRow
											label={ __(
												'Color',
												'joc-blockora-morph'
											) }
											value={ normalized.iconColor }
											onChange={ ( next ) =>
												patch( {
													iconColor: next || '',
												} )
											}
											colors={ colorPalettes }
										/>
									</div>
								</div>
							</Panel>
						) : null }
					</div>
				</div>
			) }
		</div>
	);
}
