import React from 'react'
import { View } from 'react-native'
import PropTypes from 'prop-types'

import { useThemeTokensCallback } from '../ThemeProvider/useThemeTokens'
import { a11yProps } from '../utils/props/a11yProps'
import { getTokensPropType } from '../utils/props/tokens'
import { selectSystemProps } from '../utils/props/selectSystemProps'
import { variantProp } from '../utils/props/variantProp'
import { viewProps } from '../utils/props/viewProps'
import { useCopy } from '../utils/useCopy'
import { StackWrap } from '../StackView/StackWrap'
import { Typography } from '../Typography/Typography'
import { ColorBubble } from './ColorBubble'
import { UNAVAILABLE_VARIANT, DICTIONARY_CONTENT_SHAPE } from './constants'
import { DEFAULT_COLOR_TOGGLE_DICTIONARY } from './dictionary'

const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])

export const ColorToggle = React.forwardRef(
  (
    {
      tokens,
      variant,
      defaultColourId,
      defaultColorId = defaultColourId,
      items,
      onChange,
      showTooltips,
      copy = 'en',
      dictionary = DEFAULT_COLOR_TOGGLE_DICTIONARY,
      ...rest
    },
    ref
  ) => {
    const [currentColorId, setCurrentColorId] = React.useState(defaultColorId)
    const getTokens = useThemeTokensCallback('ColorToggle', tokens, variant)
    const getCopy = useCopy({ dictionary, copy })
    const { space } = getTokens()
    const currentItem = items.find(({ id }) => id === currentColorId)

    return (
      <View ref={ref} {...selectProps(rest)}>
        <Typography>
          {currentItem?.unavailable
            ? `${currentItem?.colorName ?? currentItem?.colourName} ${getCopy('unavailable')}`
            : currentItem?.colorName ?? currentItem?.colourName ?? ''}
        </Typography>
        <StackWrap space={space} accessibilityRole="radiogroup">
          {items.map(
            (
              { id, colorHexCode, colourHexCode, colorName, colourName, unavailable, disabled },
              index
            ) => {
              const colorBubbleId = id || `ColorBubble[${index}]`

              const handleChangeColor = (event) => {
                setCurrentColorId(id)
                onChange?.(event, {
                  id,
                  colorHexCode: colorHexCode ?? colourHexCode,
                  colorName: colorName ?? colourName,
                  colourHexCode: colorHexCode ?? colourHexCode,
                  colourName: colorName ?? colourName,
                  unavailable
                })
              }

              return (
                <ColorBubble
                  key={colorBubbleId}
                  id={colorBubbleId}
                  tokens={getTokens}
                  isSelected={id === currentColorId}
                  colorHexCode={colorHexCode ?? colourHexCode}
                  colorName={colorName ?? colourName}
                  onPress={handleChangeColor}
                  showTooltip={showTooltips}
                  unavailable={unavailable}
                  isDisabled={!!disabled}
                />
              )
            }
          )}
        </StackWrap>
      </View>
    )
  }
)

ColorToggle.displayName = 'ColorToggle'

ColorToggle.propTypes = {
  ...selectedSystemPropTypes,
  /**
   * Optional theme token overrides for the outer ColorToggle component
   */
  tokens: getTokensPropType('ColorToggle'),
  /**
   * Color toggle variant.
   */
  variant: variantProp.propType,
  /**
   * Id of the selected color when component mounts (deprecated, use defaultColorId)
   * @deprecated Use defaultColorId
   */
  defaultColourId: PropTypes.string,
  /**
   * Id of the selected color when component mounts
   */
  defaultColorId: PropTypes.string,
  /**
   * Array of objects containing specifics for each ColorBubble to be rendered in the group.
   */
  items: PropTypes.arrayOf(
    PropTypes.exact({
      colorHexCode: PropTypes.string,
      colourHexCode: PropTypes.string,
      colorName: PropTypes.string,
      colourName: PropTypes.string,
      id: PropTypes.string,
      unavailable: PropTypes.oneOf(Object.values(UNAVAILABLE_VARIANT)),
      disabled: PropTypes.bool
    })
  ),
  /**
   * If provided, this function is called when the current selection of the color is changed of all currently `items`. Receives two parameters: item object selected and the event
   */
  onChange: PropTypes.func,
  /**
   * When true, displays each color's name as a tooltip on hover (web only).
   */
  showTooltips: PropTypes.bool,
  /**
   * Select English or French copy.
   */
  copy: PropTypes.oneOf(['en', 'fr']),
  /**
   * Override default labels.
   */
  dictionary: PropTypes.shape({
    en: DICTIONARY_CONTENT_SHAPE,
    fr: DICTIONARY_CONTENT_SHAPE
  })
}

// Backwards compatibility alias
// eslint-disable-next-line react/no-multi-comp
export const ColourToggle = React.forwardRef((props, ref) => <ColorToggle {...props} ref={ref} />)
ColourToggle.displayName = 'ColourToggle'
ColourToggle.propTypes = ColorToggle.propTypes
