import React from 'react'
import PropTypes from 'prop-types'
import { Pressable, Text } from 'react-native'
import { selectSystemProps } from '../utils/props/selectSystemProps'
import { resolvePressableTokens } from '../utils/pressability'
import { htmlAttrs } from '../utils/htmlAttrs'
import { useListboxContext } from './ListboxContext'

const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs])

const getItemStyles = ({
  groupFontName,
  groupFontWeight,
  itemFontSize,
  itemPaddingTop,
  itemPaddingBottom,
  itemPaddingLeft,
  itemBorderLeftWidth,
  itemPaddingRight,
  itemBackgroundColor,
  itemColor,
  itemOutline,
  itemTextDecoration,
  itemBorderLeftColor,
  itemBorderRightWidth,
  itemBorderRightColor,
  itemBorderTopWidth,
  itemBorderTopColor,
  itemBorderBottomWidth,
  itemBorderBottomColor,
  itemBorderRadius
}) => ({
  fontFamily: `${groupFontName}${groupFontWeight}normal`,
  fontSize: itemFontSize,
  paddingTop: itemPaddingTop - itemBorderTopWidth,
  paddingBottom: itemPaddingBottom - itemBorderBottomWidth,
  paddingLeft: itemPaddingLeft - itemBorderLeftWidth,
  paddingRight: itemPaddingRight - itemBorderRightWidth,
  width: '100%',
  backgroundColor: itemBackgroundColor,
  color: itemColor,
  outline: itemOutline,
  textDecoration: itemTextDecoration,
  borderLeftWidth: itemBorderLeftWidth,
  borderLeftColor: itemBorderLeftColor,
  borderRightWidth: itemBorderRightWidth,
  borderRightColor: itemBorderRightColor,
  borderTopWidth: itemBorderTopWidth,
  borderTopColor: itemBorderTopColor,
  borderBottomWidth: itemBorderBottomWidth,
  borderBottomColor: itemBorderBottomColor,
  borderRadius: itemBorderRadius,
  justifyContent: 'center'
})

export const PressableItem = React.forwardRef(
  (
    {
      children,
      href,
      isChild = false,
      onBlur,
      onPress,
      tabIndex = 0,
      nextItemRef,
      prevItemRef,
      tokens,
      id,
      ...rest
    },
    ref
  ) => {
    const { selectedId, setSelectedId } = useListboxContext()

    const selectTextStyles = ({
      groupFontName,
      groupFontWeight,
      itemFontSize,
      itemColor,
      lineHeight
    }) => ({
      fontFamily: `${groupFontName}${groupFontWeight}normal`,
      fontSize: itemFontSize,
      color: itemColor,
      lineHeight: lineHeight * itemFontSize
    })

    const resolveButtonTokens = (pressableState) => {
      const themeTokens = resolvePressableTokens(tokens, pressableState, {
        isChild,
        current: id === selectedId && id !== undefined
      })
      return themeTokens
    }

    const handleKeyPress = (event) => {
      if (['Enter', ' '].includes(event?.key)) {
        onPress?.(event)
      } else if (event?.key === 'ArrowDown') {
        nextItemRef.current.focus()
      } else if (event?.key === 'ArrowUp' && prevItemRef?.current) {
        prevItemRef.current.focus()
      }
    }

    return (
      <Pressable
        isChild={isChild}
        style={(pressableState) => getItemStyles(resolveButtonTokens(pressableState))}
        onBlur={onBlur}
        onClick={onPress}
        onKeyPress={handleKeyPress}
        ref={ref}
        tabIndex={tabIndex}
        {...(href && { href })}
        {...(onPress && { onClick: onPress })}
        {...selectProps(rest)}
        onPress={(event) => {
          setSelectedId(id)
          onPress(event)
        }}
      >
        {(pressableState) => {
          return (
            <Text style={selectTextStyles(resolveButtonTokens(pressableState))}>{children}</Text>
          )
        }}
      </Pressable>
    )
  }
)
PressableItem.displayName = 'PressableItem'
PressableItem.propTypes = {
  ...selectedSystemPropTypes,
  href: PropTypes.string,
  isChild: PropTypes.bool,
  children: PropTypes.node.isRequired,
  onBlur: PropTypes.func,
  onPress: PropTypes.func,
  nextItemRef: PropTypes.object,
  prevItemRef: PropTypes.object
}
