import React from 'react'
import { StyleSheet, View } from 'react-native'
import PropTypes from 'prop-types'
import { Divider } from '../Divider/Divider'
import { useViewport } from '../ViewportProvider/useViewport'
import { useThemeTokens } from '../ThemeProvider/useThemeTokens'
import { selectSystemProps } from '../utils/props/selectSystemProps'
import { getTokensPropType } from '../utils/props/tokens'
import { htmlAttrs } from '../utils/htmlAttrs'
import { viewProps } from '../utils/props/viewProps'
import { renderFootnoteContent } from './utils/renderFootnoteContent'
import { renderPrice } from './utils/renderPrice'
import { renderTypography } from './utils/renderTypography'

const PRICE_BASELINE_VARIANT = 'baseline'

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

const selectTopTextTypographyTokens = ({ topTextFontSize, topTextLineHeight }) => ({
  fontSize: topTextFontSize,
  lineHeight: topTextLineHeight
})

const selectCurrencySymbolTypographyTokens = ({
  currencySymbolFontSize,
  currencySymbolLineHeight,
  currencySymbolFontWeight
}) => ({
  fontSize: currencySymbolFontSize,
  lineHeight: currencySymbolLineHeight,
  fontWeight: currencySymbolFontWeight
})

const selectAmountTypographyTokens = ({
  amountFontSize,
  amountLineHeight,
  amountLetterSpacing,
  amountFontWeight,
  fontColor
}) => {
  // This is used to apply the proper line height to the amount
  const lineHeightMultiplier = 1.18
  return {
    color: fontColor,
    fontSize: amountFontSize,
    lineHeight: amountLineHeight * lineHeightMultiplier,
    letterSpacing: amountLetterSpacing,
    fontWeight: amountFontWeight
  }
}

const selectCentsTypographyTokens = ({ centsFontSize, centsLineHeight, centsFontWeight }) => ({
  fontSize: centsFontSize,
  lineHeight: centsLineHeight,
  fontWeight: centsFontWeight
})

const selectRateTypographyTokens = ({ rateFontSize, rateLineHeight, rateFontWeight }) => ({
  fontSize: rateFontSize,
  lineHeight: rateLineHeight,
  fontWeight: rateFontWeight
})

const selectBottomTextTypographyTokens = ({ bottomTextFontSize, bottomTextLineHeight }) => ({
  fontSize: bottomTextFontSize,
  lineHeight: bottomTextLineHeight
})

const selectContainertokens = ({ alignItemsText }) => ({
  alignItems: alignItemsText
})

export const PriceLockup = React.forwardRef(
  (
    {
      size = 'medium',
      signDirection = 'left',
      footnoteLinks,
      topText,
      price,
      currencySymbol = '$',
      rateText,
      ratePosition = 'right',
      bottomText,
      onClickFootnote,
      strikeThrough,
      a11yText,
      tokens: priceLockupTokens,
      variant = {},
      ...rest
    },
    ref
  ) => {
    const viewport = useViewport()
    const {
      footnoteMarginTop,
      footnoteGap,
      bottomTextMarginTop,
      priceMarginBottom,
      bottomLinksMarginLeft,
      fontColor,
      dividerColor,
      ...themeTokens
    } = useThemeTokens(
      'PriceLockup',
      priceLockupTokens,
      { ...variant, size },
      { viewport, strikeThrough }
    )
    const currencySymbolTypographyTokens = selectCurrencySymbolTypographyTokens(themeTokens)
    const amountTypographyTokens = selectAmountTypographyTokens(themeTokens)
    const centsTypographyTokens = selectCentsTypographyTokens(themeTokens)
    const rateTypographyTokens = selectRateTypographyTokens(themeTokens)
    const topTextTypographyTokens = selectTopTextTypographyTokens(themeTokens)
    const bottomTextTypographyTokens = selectBottomTextTypographyTokens(themeTokens)

    const isPriceBaseline = variant?.price === PRICE_BASELINE_VARIANT

    return (
      <View
        style={[staticStyles.priceLockupContainer, selectContainertokens(themeTokens)]}
        ref={ref}
        {...selectProps(rest)}
      >
        {topText ? (
          <View style={staticStyles.topText}>
            {renderTypography(topText, topTextTypographyTokens, undefined, fontColor)}
          </View>
        ) : null}
        {renderPrice(
          price,
          rateText,
          ratePosition,
          signDirection,
          currencySymbol,
          currencySymbolTypographyTokens,
          amountTypographyTokens,
          centsTypographyTokens,
          rateTypographyTokens,
          fontColor,
          strikeThrough,
          a11yText,
          bottomText,
          bottomLinksMarginLeft,
          footnoteLinks,
          onClickFootnote,
          themeTokens,
          isPriceBaseline
        )}
        {bottomText ? (
          <>
            <Divider
              testID="price-lockup-divider"
              role="separator"
              tokens={{ color: dividerColor }}
            />
            {renderFootnoteContent(
              footnoteMarginTop,
              bottomTextMarginTop,
              bottomText,
              bottomTextTypographyTokens,
              fontColor,
              footnoteLinks,
              bottomLinksMarginLeft,
              onClickFootnote,
              themeTokens
            )}
          </>
        ) : null}
      </View>
    )
  }
)

PriceLockup.displayName = 'PriceLockup'
PriceLockup.propTypes = {
  ...selectedSystemPropTypes,
  /**
   * Size of the component
   *
   * Small for pricing in product catalogue pages, medium for pricing in product comparison cards.
   */
  size: PropTypes.oneOf(['small', 'medium']),
  /**
   * If currency symbol other than `$` to be used
   */
  currencySymbol: PropTypes.string,
  /**
   * Shows additional info above the price
   */
  topText: PropTypes.string,
  /**
   * Monetary value (including decimals separated by ".")
   */
  price: PropTypes.string.isRequired,
  /**
   * Shows month/year unit
   */
  rateText: PropTypes.string,
  /**
   * Shows additional info below the price with a `Divider`
   */
  bottomText: PropTypes.string,
  /**
   * Displays which side the currency should appear (left, right)
   */
  signDirection: PropTypes.oneOf(['right', 'left']),
  /**
   * Displays where the rate should appear (bottom, right)
   */
  ratePosition: PropTypes.oneOf(['right', 'bottom']),
  /**
   * Shows additional link for context
   */
  footnoteLinks: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.string])),
  /**
   * Function to be called when a footnote link is clicked
   */
  onClickFootnote: PropTypes.func,
  /**
   * To show price savings comparison
   */
  strikeThrough: PropTypes.bool,
  /**
   * To provide a11y text for `PriceLockup` component
   *
   * **Note:** a11yText will override strikethrough price, so it must include price (ie. "was 50 dollars per month")
   */
  a11yText: PropTypes.string,
  /**
   * `PriceLockup` tokens
   */
  tokens: getTokensPropType('PriceLockup')
}

const staticStyles = StyleSheet.create({
  priceLockupContainer: {
    alignSelf: 'flex-start'
  },
  topText: {
    marginBottom: 4
  }
})
