/**
 * Shared ColorPalette with Theme / Default tabs.
 * Used by inspector color dropdowns and the format toolbar.
 * Opacity lives under the swatches (above Clear) — not inside the custom picker.
 */
import {
	Button,
	ColorPalette,
	RangeControl,
	TabPanel,
} from '@wordpress/components';
import { useEffect, useMemo, useRef, useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { useThemeTokens } from '../hooks/useThemeTokens';
import { DEFAULT_COLORS } from '../styleFieldDefaults';
import { applyAlphaToColor, getColorAlpha, isAbsentColor } from '../cssVars';
import './ThemeColorPalette.css';

const OPACITY_HIGHLIGHT_MS = 1600;

/**
 * Rememberable base color (has a resolvable hue). Fully transparent keyword is not.
 *
 * @param {string} color
 * @return {boolean}
 */
function isRememberableColor( color ) {
	const raw = String( color || '' ).trim();
	if ( ! raw || raw.toLowerCase() === 'transparent' ) {
		return false;
	}
	if ( raw.toLowerCase().includes( 'gradient' ) ) {
		return false;
	}
	return true;
}

/**
 * Normalize palette rows from useThemeTokens / callers into tab descriptors.
 *
 * @param {Array<{ name?: string, title?: string, colors?: Array }>|null|undefined} palettes
 * @param {Array} themeColors
 * @return {Array<{ name: string, title: string, colors: Array }>}
 */
function buildTabs( palettes, themeColors ) {
	let theme = Array.isArray( themeColors ) ? themeColors : [];
	let defaults = DEFAULT_COLORS;

	if ( Array.isArray( palettes ) && palettes.length ) {
		const looksLikeColors = palettes.every(
			( row ) =>
				row &&
				typeof row === 'object' &&
				row.color &&
				! Array.isArray( row.colors )
		);
		if ( looksLikeColors ) {
			defaults = palettes;
		} else {
			palettes.forEach( ( row ) => {
				const key = String( row?.name || '' )
					.toLowerCase()
					.replace( /\s+/g, '-' );
				const titleKey = String( row?.title || '' )
					.toLowerCase()
					.replace( /\s+/g, '-' );
				const list = Array.isArray( row?.colors ) ? row.colors : [];
				if ( key === 'theme' || titleKey === 'theme' ) {
					theme = list;
				} else if ( key === 'default' || titleKey === 'default' ) {
					defaults = list.length ? list : DEFAULT_COLORS;
				}
			} );
		}
	}

	return [
		{
			name: 'default',
			title: __( 'Default', 'joc-blockora-morph' ),
			colors: defaults,
		},
		{
			name: 'theme',
			title: __( 'Theme', 'joc-blockora-morph' ),
			colors: theme,
		},
	];
}

/**
 * @param {object}   props
 * @param {string}   [props.value]
 * @param {Function} props.onChange
 * @param {boolean}  [props.clearable]
 * @param {boolean}  [props.enableAlpha]
 * @param {boolean}  [props.disableCustomColors]
 * @param {string}   [props.className]
 * @param {Array}    [props.palettes] Theme token palettes or flat color list
 * @param {boolean}  [props.asSidebar] Pass through to ColorPalette sidebar layout
 */
export default function ThemeColorPalette( {
	value = '',
	onChange,
	clearable = true,
	enableAlpha = true,
	disableCustomColors = false,
	className = '',
	palettes = null,
	asSidebar = true,
} ) {
	const { colorPalettes } = useThemeTokens();
	const tabs = useMemo(
		() => buildTabs( palettes != null ? palettes : colorPalettes, [] ),
		[ palettes, colorPalettes ]
	);

	const valueStr = String( value || '' ).trim();
	const alpha = getColorAlpha( valueStr );
	const [ opacityHighlight, setOpacityHighlight ] = useState( false );
	const highlightTimerRef = useRef( 0 );

	useEffect(
		() => () => {
			window.clearTimeout( highlightTimerRef.current );
		},
		[]
	);

	const flashOpacityNotice = () => {
		if ( ! enableAlpha ) {
			return;
		}
		setOpacityHighlight( true );
		window.clearTimeout( highlightTimerRef.current );
		highlightTimerRef.current = window.setTimeout( () => {
			setOpacityHighlight( false );
		}, OPACITY_HIGHLIGHT_MS );
	};

	// Remember last resolvable color so opacity still works after alpha hits 0.
	const lastColorRef = useRef(
		isRememberableColor( valueStr ) ? valueStr : '#000000'
	);
	if ( isRememberableColor( valueStr ) ) {
		lastColorRef.current = valueStr;
	}

	const commitColor = ( next ) => {
		if ( isAbsentColor( next ) ) {
			onChange?.( '' );
			return;
		}
		const raw = String( next ).trim();
		if ( ! enableAlpha ) {
			onChange?.( raw );
			return;
		}
		// Transparent / zero-alpha current value — don't lock new swatches invisible.
		const keepAlpha =
			valueStr &&
			valueStr.toLowerCase() !== 'transparent' &&
			alpha > 0
				? alpha
				: 1;
		onChange?.( applyAlphaToColor( raw, keepAlpha ) );
		flashOpacityNotice();
	};

	const commitAlpha = ( nextPct ) => {
		// RangeControl may pass undefined while the number field is empty —
		// ignore that so dragging/typing 0 is not treated as "reset to 100%".
		if ( nextPct == null || nextPct === '' ) {
			return;
		}
		const pct = Number( nextPct );
		if ( Number.isNaN( pct ) ) {
			return;
		}
		const nextA = Math.min( 100, Math.max( 0, pct ) ) / 100;
		const base = isRememberableColor( valueStr )
			? valueStr
			: lastColorRef.current || '#000000';
		onChange?.( applyAlphaToColor( base, nextA ) );
	};

	return (
		<div
			className={ `bm-theme-color-palette ${ className }`.trim() }
		>
			<TabPanel
				className="bm-theme-color-palette__tabs"
				activeClass="is-active"
				initialTabName="default"
				tabs={ tabs.map( ( tab ) => ( {
					name: tab.name,
					title: tab.title,
				} ) ) }
			>
				{ ( tab ) => {
					const colors =
						tabs.find( ( t ) => t.name === tab.name )?.colors ||
						[];
					return (
						<div className="bm-theme-color-palette__tab">
							{ colors.length ? (
								<ColorPalette
									colors={ colors }
									value={ valueStr || undefined }
									onChange={ commitColor }
									clearable={ false }
									enableAlpha={ false }
									disableCustomColors={ disableCustomColors }
									__experimentalIsRenderedInSidebar={
										asSidebar
									}
								/>
							) : (
								<p className="bm-theme-color-palette__empty">
									{ tab.name === 'theme'
										? __(
												'No theme colors available.',
												'joc-blockora-morph'
										  )
										: __(
												'No colors configured.',
												'joc-blockora-morph'
										  ) }
								</p>
							) }
						</div>
					);
				} }
			</TabPanel>

			{ enableAlpha ? (
				<div
					className={
						'bm-theme-color-palette__opacity' +
						( opacityHighlight ? ' is-highlighted' : '' )
					}
				>
					<RangeControl
						label={ __( 'Opacity', 'joc-blockora-morph' ) }
						value={ Math.round( alpha * 100 ) }
						onChange={ commitAlpha }
						min={ 0 }
						max={ 100 }
						__next40pxDefaultSize
						__nextHasNoMarginBottom
					/>
				</div>
			) : null }

			{ clearable ? (
				<div className="bm-theme-color-palette__clear">
					<Button
						variant="tertiary"
						onClick={ () => onChange?.( '' ) }
						disabled={ ! valueStr }
					>
						{ __( 'Clear', 'joc-blockora-morph' ) }
					</Button>
				</div>
			) : null }
		</div>
	);
}
