import React from 'react'
import PropTypes from 'prop-types'
import { Pressable, View, StyleSheet } from 'react-native'
import { getTokensPropType } from '../utils/props/tokens'
import { resolvePressableTokens } from '../utils/pressability'
import { variantProp } from '../utils/props/variantProp'
import { useThemeTokensCallback } from '../ThemeProvider/useThemeTokens'
import { Typography } from '../Typography/Typography'
import { Spacer } from '../Spacer/Spacer'

const selectTypographyStyles = (
  { fontWeight, color, lineHeight, fontName, activeColor },
  isSelected
) => ({
  fontWeight,
  color: isSelected ? activeColor : color,
  lineHeight,
  fontName
})

const selectIconContainerStyles = ({ paddingTop, paddingBottom }) => ({
  paddingTop,
  paddingBottom,
  alignItems: 'center'
})

const selectIconStyles = ({ iconSize, iconColor, activeColor }, isSelected) => ({
  size: iconSize,
  color: isSelected ? activeColor : iconColor
})

const selectContainerStyles = ({ borderRadius, backgroundColor }) => ({
  borderRadius,
  backgroundColor,
  alignSelf: 'center',
  alignItems: 'center'
})

export const TabBarItem = React.forwardRef(
  (
    {
      href,
      variant,
      tokens,
      label,
      isSelected,
      id,
      onPress,
      icon: IconComponent,
      iconActive: IconActiveComponent,
      accessibilityRole = 'tab'
    },
    ref
  ) => {
    const getTokens = useThemeTokensCallback('TabBarItem', tokens, variant)

    const getPressableStyle = ({ pressed, focused, hovered }) => {
      const resolvedTokens = resolvePressableTokens(
        getTokens,
        { pressed, focused, hovered },
        { isSelected }
      )
      return {
        ...resolvedTokens,
        outline: 'none' // removes the default browser :focus outline
      }
    }

    return (
      <Pressable
        ref={ref}
        href={href}
        nativeID={id}
        onPress={onPress}
        style={({ pressed, focused, hovered }) => [
          styles.flexContainer,
          getPressableStyle({ pressed, focused, hovered })
        ]}
        accessibilityRole={accessibilityRole}
        testID={id}
      >
        {(pressableState) => {
          const resolvedTokens = getPressableStyle(pressableState)

          return (
            <View style={selectContainerStyles(resolvedTokens)}>
              <View style={[selectIconContainerStyles(resolvedTokens), styles.iconContainer]}>
                {isSelected
                  ? IconActiveComponent && (
                      <IconActiveComponent {...selectIconStyles(resolvedTokens, isSelected)} />
                    )
                  : IconComponent && <IconComponent {...selectIconStyles(resolvedTokens)} />}
              </View>
              <Spacer space={1} />
              <Typography
                variant={{ size: 'micro' }}
                tokens={selectTypographyStyles(resolvedTokens, isSelected)}
                align="center"
              >
                {label}
              </Typography>
              <Spacer space={1} />
            </View>
          )
        }}
      </Pressable>
    )
  }
)

TabBarItem.displayName = 'TabBarItem'

TabBarItem.propTypes = {
  /** The icon to be displayed when the item is not selected. */
  icon: PropTypes.elementType,
  /** The icon to be displayed when the item is selected. */
  iconActive: PropTypes.elementType,
  /** Tokens for theming and styling the TabBarItem. */
  tokens: getTokensPropType('TabBarItem'),
  /** Variant of the TabBarItem for styling purposes. */
  variant: variantProp.propType,
  /** Callback function to handle press events. */
  onPress: PropTypes.func,
  /** URL to navigate to when the item is pressed. */
  href: PropTypes.string,
  /** Indicates whether the item is selected. */
  isSelected: PropTypes.bool,
  /** Unique identifier for the item. */
  id: PropTypes.string,
  /** Label text for the item. */
  label: PropTypes.string.isRequired,
  /** Accessibility role for the item. */
  accessibilityRole: PropTypes.string
}

const styles = StyleSheet.create({
  flexContainer: {
    flex: 1,
    alignItems: 'center'
  },
  iconContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    minWidth: 44,
    minHeight: 40,
    aspectRatio: 1.1
  }
})
