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

import { useThemeTokens } from '../ThemeProvider/useThemeTokens'
import { applyTextStyles } from '../ThemeProvider/utils/styles'
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 { wrapStringsInText } from '../utils/children'
import { transformGradient } from '../utils/transformGradient'
import { Icon } from '../Icon/Icon'

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

const selectContainerStyles = ({
  backgroundColor,
  backgroundGradient,
  borderColor,
  borderRadius,
  borderWidth,
  paddingBottom,
  paddingLeft,
  paddingRight,
  paddingTop
}) => {
  const styles = {
    borderColor,
    borderRadius,
    borderWidth,
    paddingBottom,
    paddingLeft,
    paddingRight,
    paddingTop
  }

  if (backgroundGradient) {
    if (Platform.OS === 'web') {
      styles.background = transformGradient(backgroundGradient)
    } else {
      const {
        stops: [stopOne, stopTwo]
      } = backgroundGradient
      styles.gradient = {}
      styles.gradient.start = { x: 0, y: 0 }
      styles.gradient.end = { x: 1, y: 1 }
      styles.gradient.colors = [stopOne.color, stopTwo.color]
    }
  } else {
    styles.backgroundColor = backgroundColor
  }

  return styles
}

const selectIconProps = ({ icon, iconColor, iconSize, iconPaddingTop }) => ({
  icon,
  tokens: { color: iconColor, paddingTop: iconPaddingTop, size: iconSize },
  variant: { size: 'small' }
})

const selectTextStyles = ({
  textColor,
  textLineHeight,
  fontName,
  fontSize,
  fontWeight,
  marginLeft
}) =>
  applyTextStyles({
    fontColor: textColor,
    fontName,
    fontSize,
    fontWeight,
    lineHeight: Platform.OS === 'web' ? textLineHeight : textLineHeight * 1.2,
    marginLeft
  })

/**
 * Status component displays a status indicator with optional custom gradient.
 *
 * @component
 * @param {object} tokens - The tokens for customizing the status component.
 * @param {string} variant - The variant of the status component.
 * @param {ReactNode} children - The content to be displayed inside the status component.
 * @param {function} customGradient - The custom gradient function for the status component.
 * @param {elementType} customGradient - Defines an icon to be rendered.
 * @param {object} rest - The rest of the props to be applied to the status component.
 * @param {React.Ref} ref - The ref to be applied to the status component.
 * @returns {ReactNode} The rendered status component.
 */
export const Status = React.forwardRef(
  ({ tokens, variant, children, customGradient, ...rest }, ref) => {
    const themeTokens = useThemeTokens('Status', tokens, variant)
    const { icon } = themeTokens
    const containerStyles = { ...selectContainerStyles(themeTokens), ...staticStyles.container }

    let content = (
      <>
        {icon ? <Icon {...selectIconProps(themeTokens)} /> : null}
        {wrapStringsInText(children, {
          style: selectTextStyles(themeTokens)
        })}
      </>
    )
    if (typeof customGradient === 'function') {
      content = customGradient(containerStyles.gradient, containerStyles, content)
    }

    return (
      <View ref={ref} style={containerStyles} {...selectProps(rest)}>
        {content}
      </View>
    )
  }
)

Status.displayName = 'Status'

Status.propTypes = {
  ...selectedSystemPropTypes,
  tokens: getTokensPropType('Status'),
  variant: variantProp.propType,
  /**
   * The content to be displayed inside the status component.
   */
  children: PropTypes.node.isRequired,
  /**
   * The custom gradient function for the status component.
   */
  customGradient: PropTypes.func
}

const staticStyles = StyleSheet.create({
  container: {
    flexDirection: 'row',
    alignItems: 'center',
    ...Platform.select({
      web: {
        display: 'inline-flex',
        width: 'fit-content'
      },
      default: {
        display: 'flex',
        width: 'auto'
      }
    })
  }
})
