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

import { applyShadowToken } from '../ThemeProvider/utils/styles'
import { useThemeTokens } 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 { ProgressContext } from './ProgressContext'

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

const BORDER_SIDES = 2
const CENTER_DIVISOR = 2

const selectProgressStyles = ({
  backgroundColor,
  borderWidth,
  borderColor,
  borderRadius,
  height,
  shadow
}) => ({
  backgroundColor,
  borderWidth,
  borderColor,
  borderRadius,
  height,
  ...applyShadowToken(shadow)
})

const selectBarWrapperStyles = ({ barHeight, borderRadius, borderWidth, height }) => ({
  height: barHeight,
  width: '100%',
  position: 'absolute',
  top: (height - borderWidth * BORDER_SIDES - barHeight) / CENTER_DIVISOR,
  borderRadius
})

/**
 * The `Progress` is a container for displaying one or several `ProgressBar`s.
 *
 * ## Props
 *
 * - Use `children` prop to pass one or multiple `ProgressBar`s. Note that in case of stacked progress bars
 *   each next will be displayed on top of the previous one.
 *
 * ## Tokens
 *
 * - Use the following tokens to customize the appearance:
 *   - `backgroundColor` for the background color of the progress container,
 *   - `barHeight` to control the height of the progress bars displayed within the container,
 *   - `borderColor` to control the color of the border,
 *   - `borderRadius` for the rounded corners,
 *   - `borderWidth` to change the border width.
 *   - `height` to control the height of the progress bar container.
 *   - `shadow` to apply a box shadow to the progress bar container.
 *
 * ## Variants
 *
 * - Use the `size` variant to control the height of your progress bars:  passing `'mini'` will make your
 *   progress bar container narrower.
 * - Use the `layers` variant to control how multiple progress bars are positioned:
 *   - `false` (default): bars are positioned vertically one below the other.
 *   - `true`: bars overlay on top of each other (layered/stacked on z-axis).
 *   Note: The `layers` prop is deprecated. After August 2026, `layers: true` will become the permanent
 *   default behavior and the `layers` prop will be removed. To maintain vertical layout after removal,
 *   use separate individual Progress components.
 *
 * ## Usability and A11y guidelines
 *
 * `Progress` component accepts the standard accessibility properties, however it's more important to make sure
 * its children (instances of `ProgressBar`) receive the accessibility properties specific to the `progressbar`
 * role.
 *
 */
export const Progress = React.forwardRef(({ children, tokens, variant, ...rest }, ref) => {
  const themeTokens = useThemeTokens('Progress', tokens, variant)
  const layers = variant?.layers ?? false
  const { barHeight, height } = themeTokens

  const content =
    barHeight && barHeight !== height ? (
      <View style={selectBarWrapperStyles(themeTokens)}>{children}</View>
    ) : (
      children
    )

  return (
    <ProgressContext.Provider value={{ layers }}>
      <View
        ref={ref}
        style={[staticStyles.progressContainer, selectProgressStyles(themeTokens)]}
        {...selectProps(rest)}
      >
        {content}
      </View>
    </ProgressContext.Provider>
  )
})
Progress.displayName = 'Progress'

Progress.propTypes = {
  ...selectedSystemPropTypes,
  /**
   * Use the `children` prop to supply one or several `ProgressBar`s.
   */
  children: PropTypes.node.isRequired,
  /**
   * Progress tokens.
   */
  tokens: getTokensPropType('Progress'),
  /**
   * Progress variant.
   */
  variant: variantProp.propType
}

const staticStyles = StyleSheet.create({
  progressContainer: {
    position: 'relative'
  }
})
