import * as React from 'react'
import {__, _x, sprintf} from '@wordpress/i18n'

import {
	useContext,
} from '@wordpress/element'

import {
	Button,
	ButtonGroupButtonProps,
	ButtonGroupComponent,
	useButtonGroupButton,
} from '@ska/components'

import EditableButton from './EditableButton'

import {
	parseVariantValue,
} from '../../../tailwind/classNames'

import {
	VARIANT_DEFAULT_STATE,
} from '../../attributes'

import {
	parseArbitraryValueType,
	unwrapArbitraryValue,
	wrapArbitraryValue,
} from '../../parser/util'

import {
	RadioContext,
	type RadioProps,
} from '.'

import './style.scss'

const noop = () => {}
const EMPTY_VALUES: string[] = []

const truncateTooltip = (str: string | undefined, len = 64) => str && str.length > len ? str.slice(0, len) + '…' : str

const RadioButton: React.FC<ButtonGroupButtonProps> = props => {

	const {
		showValues,
		deselectable,
	} = useContext(RadioContext)

	const {
		groupProps,
		option,
	} = props

	const {
		onChange = noop,
	} = groupProps

	const {
		type,
		isSmall = false,
		value: currentValues = EMPTY_VALUES,
		arbitraryValues = EMPTY_VALUES,
		isActive: getIsActive,
		onDoubleClick,
		onUpdate,
		onRemove,
	} = groupProps as RadioProps

	const currentValue = currentValues.length > 0 ? currentValues[0] : ''

	const {
		value: buttonValue = '',
	} = option

	const {
		Button: ButtonComponent,
		buttonProps,
	} = useButtonGroupButton(props)

	const {
		cleanValue,
		withPrefixSuffix,
	} = parseVariantValue(currentValue)

	const isVariantDefaultState = buttonValue === VARIANT_DEFAULT_STATE // Special case for making default state editable to another variant
	const isActive = (cleanValue === buttonValue) || (getIsActive && getIsActive(buttonValue)) || false
	const isArbitrary = arbitraryValues.includes(buttonValue)
	const canRemove = isArbitrary && !!onRemove && (type === 'variants' ? (isActive && !isVariantDefaultState) : true) // Variants are removable only when active

	const {
		children,
		label,
	} = buttonProps

	const buttonText = showValues && label ? label : children
	const buttonTooltip = showValues && label ? children : truncateTooltip(label)

	const shouldRenderEditableButton = isActive && (canRemove || isVariantDefaultState) && onUpdate

	/** When editing variants, the values should be treated as bare values, even though they can contain brackets like `[...]`, don't unwrap them. */
	const alwaysBare = type === 'variants'

	const button = shouldRenderEditableButton
		? (
			<EditableButton
				type={alwaysBare ? 'bare' : parseArbitraryValueType(buttonValue)}
				isActive={isActive}
				isSmall={buttonProps.isSmall}
				label={children}
				value={alwaysBare ? (isVariantDefaultState ? _x('Default', 'Label for "default state" variant', 'ska-blocks') : buttonValue) : unwrapArbitraryValue(buttonValue)}
				colorValue={buttonProps.colorValue ? buttonProps.colorValue.replaceAll('_', ' ') : undefined}
				onChange={nextValue => {
					if(onUpdate) {
						if(alwaysBare) {
							onUpdate(nextValue, buttonValue)
						} else {
							onUpdate(wrapArbitraryValue(nextValue, parseArbitraryValueType(buttonValue)), buttonValue)
						}
					}
				}}
				ButtonComponent={ButtonComponent}
			/>
		) : (
			// @ts-ignore
			<ButtonComponent
				{...buttonProps}
				children={buttonText}
				label={buttonTooltip}
				variant={isActive ? 'primary' : 'secondary'}
				onClick={() => {
					const nextValue = withPrefixSuffix(buttonValue)
					onChange(currentValues.includes(nextValue) ? [] : [nextValue])
				}}
				{...(onDoubleClick && {
					onDoubleClick: () => onDoubleClick(buttonValue),
				})}
			/>
		)

	return canRemove ? (
		<ButtonGroupComponent>
			{button}
			{(isActive && deselectable) ? (
				<Button
					{...(isSmall && {size: 'small'})}
					label={sprintf(__('Deselect "%s"', 'ska-blocks'), buttonValue)}
					showTooltip
					children={<span style={{transform: 'translate(1px, -1px)'}} dangerouslySetInnerHTML={{__html: `-&nbsp;`}} />}
					onClick={() => {
						onChange([])
					}}
				/>
			) : (
				<Button
					{...(isSmall && {size: 'small'})}
					label={sprintf(__('Remove "%s"', 'ska-blocks'), buttonValue)}
					showTooltip
					isDestructive
					children={<span dangerouslySetInnerHTML={{__html: `&times;`}} />}
					onClick={() => {
						if(isActive) {
							onChange([])
						}
						onRemove(buttonValue)
					}}
				/>
			)}
		</ButtonGroupComponent>
	) : button
}

export default RadioButton
