import React from 'react'
import PropTypes from 'prop-types'
import { StyleSheet, View, Image } from 'react-native'
import { useViewport } from '../ViewportProvider/useViewport'
import { useThemeTokens } from '../ThemeProvider/useThemeTokens'
import { dictionary as defaultDictionary } from './dictionary'
import { selectSystemProps } from '../utils/props/selectSystemProps'
import { getTokensPropType } from '../utils/props/tokens'
import { htmlAttrs } from '../utils/htmlAttrs'
import { viewProps } from '../utils/props/viewProps'
import { useInputValue } from '../utils/input'
import { useCopy } from '../utils/useCopy'
import { a11yProps } from '../utils/props/a11yProps'

import { Badge } from '../Badge/Badge'
import { PriceLockup } from '../PriceLockup/PriceLockup'
import { Typography } from '../Typography/Typography'
import { Button } from '../Button/Button'
import { StackView } from '../StackView/StackView'
import { Box } from '../Box/Box'
import { Icon } from '../Icon/Icon'

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

const selectProductCardTokens = ({
  borderStyle,
  borderColor,
  borderWidth,
  borderRadius,
  paddingHorizontal,
  paddingVertical
}) => ({
  borderStyle,
  borderColor,
  borderWidth,
  borderRadius,
  paddingHorizontal,
  paddingVertical
})

export const ProductCard = React.forwardRef(
  (
    {
      copy = 'en',
      dictionary = defaultDictionary,
      image = {
        src: '',
        alt: ''
      },
      cardId,
      isSelected,
      onSelect,
      tokens,
      ...rest
    },
    ref
  ) => {
    const viewport = useViewport()
    const themeTokens = useThemeTokens('ProductCard', tokens, { viewport })

    const getCopy = useCopy({ copy, dictionary })

    const { currentValue, setValue } = useInputValue()
    const hasClicked = isSelected || currentValue

    const handlePress = (event) => {
      if (cardId) {
        onSelect(cardId)
      } else {
        setValue(!currentValue, event)
      }
    }

    const renderButton = hasClicked ? (
      <Box vertical={1}>
        <StackView space={2} direction="row">
          <Icon icon={themeTokens.selectedButtonIcon} variant={{ color: 'success' }} />
          <Typography variant={{ size: 'h4' }} tokens={{ fontWeight: 400 }}>
            {getCopy('selectedButtonLabel')}
          </Typography>
        </StackView>
      </Box>
    ) : (
      <Button onPress={handlePress} variant={{ purpose: 'primary', size: 'small', width: 'full' }}>
        {getCopy('buttonLabel')}
      </Button>
    )

    return (
      <View
        {...selectProps(rest)}
        style={[selectProductCardTokens(themeTokens), staticStyles.container]}
        ref={ref}
      >
        {image?.src ? (
          <View style={staticStyles.imageContainer}>
            <Image
              source={image.src}
              style={staticStyles.image}
              alt={image.alt}
              accessibilityLabel={image.alt}
              resizeMethod="resize"
              accessibilityIgnoresInvertColors
            />
          </View>
        ) : null}

        <View style={staticStyles.textContainer}>
          <Box left={3}>
            <StackView space={1}>
              {getCopy('badgeText') ? (
                <Badge variant={{ outline: true, purpose: 'editorial' }}>
                  {getCopy('badgeText')}
                </Badge>
              ) : null}
              <Typography variant={{ size: 'h6' }}>{getCopy('brandName')}</Typography>
              <Typography variant={{ size: 'h4', color: 'brand' }} tokens={{ fontWeight: 400 }}>
                {getCopy('productName')}
              </Typography>
              <StackView space={3} divider direction="row">
                <PriceLockup {...getCopy('primaryPrice')} size="small" ratePosition="bottom" />
                {getCopy('secondaryPrice')?.price ? (
                  <PriceLockup {...getCopy('secondaryPrice')} size="small" ratePosition="bottom" />
                ) : null}
              </StackView>
              <Box top={2}>
                <StackView space={2}>
                  <Typography variant={{ size: 'h6' }} tokens={{ fontWeight: 500 }}>
                    {getCopy('term')}
                  </Typography>
                  {getCopy('buttonLabel') ? <Box top={1}>{renderButton}</Box> : null}
                </StackView>
              </Box>
            </StackView>
          </Box>
        </View>
      </View>
    )
  }
)

ProductCard.displayName = 'ProductCard'

// If a language dictionary entry is provided, it must contain every key
const dictionaryContentShape = PropTypes.shape({
  badgeText: PropTypes.string,
  brandName: PropTypes.string.isRequired,
  productName: PropTypes.string.isRequired,
  primaryPrice: PropTypes.object.isRequired,
  secondaryPrice: PropTypes.object,
  term: PropTypes.string.isRequired,
  buttonLabel: PropTypes.string.isRequired,
  selectedButtonLabel: PropTypes.string.isRequired
})

ProductCard.propTypes = {
  ...selectedSystemPropTypes,
  /**
   * Image rendered for the product.
   */
  image: PropTypes.shape({
    src: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
    alt: PropTypes.string
  }),
  /**
   * Select English or French copy for the place holder labels.
   * You may also pass in a custom dictionary object.
   */
  copy: PropTypes.oneOfType([PropTypes.oneOf(['en', 'fr'])]),
  /**
   * Override the default dictionary, by passing the complete dictionary object for `en` and `fr`
   */
  dictionary: PropTypes.shape({
    en: dictionaryContentShape,
    fr: dictionaryContentShape
  }),
  tokens: getTokensPropType('ProductCard')
}

const staticStyles = StyleSheet.create({
  container: {
    flexDirection: 'row',
    flex: 1
  },
  imageContainer: {
    width: '30%',
    minWidth: 96,
    maxWidth: 96
  },
  image: {
    resizeMode: 'contain',
    width: '100%',
    height: undefined, // This is to maintain the aspect ratio
    aspectRatio: 0.8
  },
  textContainer: {
    width: '70%'
  }
})
