import React from 'react'
import PropTypes from 'prop-types'
import {
  Card as CardBase,
  getTokensPropType,
  paddingProp,
  responsiveProps,
  selectSystemProps,
  StackView,
  useThemeTokens,
  useThemeTokensCallback,
  variantProp,
  a11yProps,
  viewProps,
  PressableCardBase,
  useResponsiveProp,
  hrefAttrsProp,
  useAllViewportTokens
} from '@telus-uds/components-base'
import styled from 'styled-components'
import CardContent from './CardContent'
import CardFooter from './CardFooter'
import FullBleedContent, {
  getFullBleedBorderRadius,
  useFullBleedContentProps
} from '../shared/FullBleedContent'
import ConditionalWrapper from '../shared/ConditionalWrapper'

// Passes React Native-oriented system props through UDS Card
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])

const GRID_COLUMNS = 12

const POSITION = {
  LEFT: 'left',
  RIGHT: 'right',
  TOP: 'top',
  BOTTOM: 'bottom',
  NONE: 'none'
}

/**
 * Helper function to get StackView tokens
 * @param {Object} columnFlex - Column flex properties
 * @param {string} contentStackAlign - Alignment value for content stack
 * @returns {Object} StackView tokens object
 */
const getStackViewTokens = (columnFlex, contentStackAlign) => ({
  ...columnFlex,
  alignItems: contentStackAlign
})

/**
 * Helper function to get CardContent tokens
 * @param {Object} baseTokens - Base tokens to spread
 * @param {Object} options - Options object
 * @param {boolean} options.backgroundImage - Whether background image is present
 * @param {string} options.fullBleedContentChildrenAlign - Alignment for full bleed content children
 * @param {boolean} options.useTransparentBackground - Whether to use transparent background when no backgroundImage
 * @returns {Object} CardContent tokens object
 */
const getCardContentTokens = (baseTokens, options = {}) => {
  const { backgroundImage, fullBleedContentChildrenAlign, useTransparentBackground } = options

  // Determine background color based on conditions
  let backgroundColorOverride = {}
  if (useTransparentBackground) {
    backgroundColorOverride = { backgroundColor: 'transparent' }
  } else if (backgroundImage) {
    backgroundColorOverride = { backgroundColor: 'transparent' }
  }

  return {
    ...baseTokens,
    ...backgroundColorOverride,
    ...(fullBleedContentChildrenAlign && {
      alignSelf: fullBleedContentChildrenAlign
    })
  }
}

/**
 * A basic card component, unstyled by default.
 *
 * ## Component API
 *
 * ### With Footer
 *
 * Pass any component or simply a string in the `footer` prop in order to render
 * a card with a footer (which uses the `alternative` background).
 *
 * ### With Full Bleed Content
 *
 * Use `fullBleedContent` prop to add a full bleed style image, video or other content to the
 * card. This prop accepts an object with the following properties:
 * - `alt`: alt tag for an image,
 * - `src`: default image source,
 * - `position`: `none`, `bottom`, `left`, `right` or `top`, depending on where you would like your full bleed image to be placed,
 * - `imgCol`: set the span of the image per viewport (based on 12 column value for width of card) when `position` of image is on `left` or `right`
 * - all the props from the `ResponsiveImage` component in case you want that full bleed image to be responsive,
 * - `content`: pass a custom JSX to be used for rendering of the full bleed content (defaults to `ResponsiveImage`
 *   receiving the other props).
 *
 * Note that `position` can be responsive, i.e. different for different viewports. A full bleed content with position
 * {xs: 'none', md: 'left'} for example, will have a full bleed content to the left of card content when viewed on desktops
 * viewports, and no content when viewed on mobile viewports.
 *
 * ## Accessibility
 * `Card` component accepts all the standard accessibility props.
 */
const DynamicWidthContainer = styled.div.withConfig({
  shouldForwardProp: (prop) =>
    !['marginTop', 'marginBottom', 'marginLeft', 'marginRight', 'height', 'alignSelf'].includes(
      prop
    )
})(
  ({
    width,
    display,
    borderRadius,
    overflow,
    marginTop,
    marginBottom,
    marginLeft,
    marginRight,
    alignSelf
  }) => ({
    width,
    display,
    borderRadius,
    overflow,
    marginTop,
    marginBottom,
    marginLeft,
    marginRight,
    alignSelf
  })
)

const InteractiveCardWrapper = styled.div(() => ({
  position: 'relative',
  flex: 1,
  display: 'flex',
  flexDirection: 'column'
}))

const InteractiveOverlay = styled.div(({ overlayOpacity, borderRadius }) => ({
  position: 'absolute',
  top: 0,
  left: 0,
  right: 0,
  bottom: 0,
  backgroundColor: `rgba(0, 0, 0, ${overlayOpacity || 0})`,
  borderRadius,
  pointerEvents: 'none',
  transition: 'background-color 0.2s ease',
  zIndex: 1
}))

const FocusBorder = styled.div(({ borderWidth, borderColor, borderRadius }) => ({
  position: 'absolute',
  top: 0,
  left: 0,
  right: 0,
  bottom: 0,
  borderWidth,
  borderColor,
  borderRadius,
  borderStyle: 'solid',
  pointerEvents: 'none',
  zIndex: 2
}))

const FullBleedPaddingWrapper = styled.div(
  ({ paddingTop, paddingBottom, paddingLeft, paddingRight }) => ({
    paddingTop,
    paddingBottom,
    paddingLeft,
    paddingRight,
    display: 'flex',
    flexDirection: 'column'
  })
)

/**
 * Calculates the padding values for full bleed content.
 * Inherits the card's theme padding (minus borderWidth to visually match card body padding)
 * and allows custom overrides via the fullBleedPadding prop.
 *
 * @param {object} themeTokens - The card's resolved theme tokens (contains padding values and borderWidth)
 * @param {object|boolean} fullBleedPadding - true to inherit card padding, or an object with overrides
 * @param {object} paddingSides - Boolean flags for which sides to apply padding
 * @returns {object} Padding values for each side in px
 */
const calculateFullBleedPadding = (themeTokens, fullBleedPadding, paddingSides) => {
  const customTokens = typeof fullBleedPadding === 'object' ? fullBleedPadding : undefined
  const borderWidth = themeTokens.borderWidth || 0

  const applyPadding = (side) => {
    const sideKey = `applyPadding${side}`
    if (!paddingSides[sideKey]) return 0
    const tokenKey = `padding${side}`
    return customTokens?.[tokenKey] ?? themeTokens[tokenKey] - borderWidth ?? 0
  }

  return {
    paddingTop: applyPadding('Top'),
    paddingBottom: applyPadding('Bottom'),
    paddingLeft: applyPadding('Left'),
    paddingRight: applyPadding('Right')
  }
}

const Card = React.forwardRef(
  (
    {
      children,
      footer,
      footerPadding,
      fullBleedImage,
      fullBleedContent = fullBleedImage,
      fullBleedPadding,
      tokens = {},
      variant,
      interactiveCard,
      onPress,
      dataSet,
      backgroundImage,
      ...rest
    } = {
      fullBleedContent: { position: null }
    },
    ref
  ) => {
    const { hrefAttrs: cardLevelHrefAttrs, rest: restWithoutHrefAttrs } = hrefAttrsProp.bundle(rest)
    const { href: cardLevelHref, ...restProps } = restWithoutHrefAttrs

    const {
      contentStackAlign,
      contentStackDirection,
      fullBleedContentPosition,
      fullBleedContentProps,
      fullBleedContentChildrenAlign,
      fullBleedPaddingSides
    } = useFullBleedContentProps(fullBleedContent)

    const {
      imgCol,
      interactive: fullBleedInteractive,
      onPress: fullBleedOnPress,
      href: fullBleedHref,
      hrefAttrs: fullBleedHrefAttrs,
      ...fullBleedContentPropsClean
    } = fullBleedContentProps

    const effectiveFullBleedOnPress = fullBleedOnPress || onPress
    const effectiveFullBleedHref = fullBleedHref || cardLevelHref
    const effectiveFullBleedHrefAttrs = fullBleedHrefAttrs || cardLevelHrefAttrs

    // If the card has rounded corners and a full bleed image, we need to apply
    // those corners on the image as well, but partially
    const variantForTokens = backgroundImage ? { ...variant, style: undefined } : variant
    const allThemeTokens = useThemeTokens('Card', tokens, variantForTokens)
    const { borderRadius } = allThemeTokens

    // Get viewport-aware tokens for responsive full bleed padding
    // useThemeTokens (above) doesn't pass viewport state, so it resolves to base/mobile tokens.
    // useAllViewportTokens resolves tokens for ALL viewports + the current one (reactive to resize).
    // This ensures fullBleedPadding matches CardContent's padding at every breakpoint.
    const allViewportTokens = useAllViewportTokens('Card', tokens, variant)

    // Interactive cards: merge variants for CardBase (outer container)
    // The outer variant takes priority over interactiveCard.variant for the style property
    // This ensures the gradient is only applied to CardBase, not PressableCardBase and avoid duplication
    const interactiveStyle = interactiveCard?.variant?.style
    const outerStyle = variant?.style
    const mergedVariant = {
      ...variant,
      style: outerStyle || interactiveStyle
    }

    // Interactive cards: build configuration for PressableCardBase
    // This determines which style to use for interactive states (hover, pressed, etc.)
    // without causing gradient duplication
    let interactiveCardConfig = {}
    if (interactiveCard?.body) {
      const styleToUse = interactiveCard?.variant?.style || variant?.style
      const { style, ...otherVariantProps } = interactiveCard?.variant || {}

      interactiveCardConfig = {
        interactive: true,
        ...(styleToUse && { style: styleToUse }),
        ...otherVariantProps
      }
    }

    const getThemeTokensBase = useThemeTokensCallback(
      'Card',
      interactiveCard?.tokens,
      interactiveCardConfig
    )

    // Wrap getThemeTokens to remove gradient from resolved tokens
    // PressableCardBase calls this function with pressableState (hover, pressed, etc.)
    // We intercept the resolved tokens and remove gradient properties to prevent duplication
    // since the gradient should only appear on CardBase (outer container)
    const getThemeTokens = React.useCallback(
      (pressableState) => {
        const resolvedTokens = getThemeTokensBase(pressableState)
        const { gradient, backgroundGradient, ...tokensWithoutGradient } = resolvedTokens
        return tokensWithoutGradient
      },
      [getThemeTokensBase]
    )

    const getFocusBorderTokens = useThemeTokensCallback(
      'Card',
      {},
      {
        ...variant,
        interactive: true
      }
    )

    // Keep backgroundColor for CardContent, it won't affect FullBleedContent image
    const tokensWithoutBg = tokens

    const fullBleedInteractiveVariant = backgroundImage
      ? {
          ...variant,
          interactive: true,
          style: undefined
        }
      : {
          ...variant,
          interactive: true
        }

    const getFullBleedInteractiveTokens = useThemeTokensCallback(
      'Card',
      tokensWithoutBg,
      fullBleedInteractiveVariant
    )

    const getFullBleedInteractiveCardTokens = (cardState) => {
      return {
        ...getFullBleedInteractiveTokens(cardState),
        paddingTop: 0,
        paddingBottom: 0,
        paddingLeft: 0,
        paddingRight: 0,
        borderWidth: 0,
        ...(interactiveCard?.body ? { gradient: undefined } : {})
      }
    }

    const hasFooter = Boolean(footer)
    const fullBleedBorderRadius = getFullBleedBorderRadius(
      borderRadius,
      fullBleedContentPosition,
      hasFooter
    )

    // Calculate full bleed content padding values
    // When fullBleedPadding is truthy, apply padding around full bleed content
    // Uses viewport-aware tokens (allViewportTokens.current) so padding matches
    // CardContent's responsive padding at every breakpoint
    const hasFullBleedPadding = Boolean(fullBleedPadding)
    const fullBleedPaddingValues = hasFullBleedPadding
      ? calculateFullBleedPadding(
          allViewportTokens.current,
          fullBleedPadding,
          fullBleedPaddingSides
        )
      : null

    // takes imgCol from fullBleedContent if present, to dynamically set width of image
    // card content will adapt to the size of image to add up to 100% width of card width
    // pass as props to ConditionalWrapper
    const imgColCurrentViewport = useResponsiveProp(imgCol)
    const maxCol = GRID_COLUMNS

    const hasValidImgCol =
      imgCol && imgColCurrentViewport !== undefined && !Number.isNaN(imgColCurrentViewport)
    const fullBleedImageWidth = hasValidImgCol
      ? `${(imgColCurrentViewport / maxCol) * 100}%`
      : undefined
    const adaptiveContentWidth = hasValidImgCol
      ? `${((maxCol - imgColCurrentViewport) / maxCol) * 100}%`
      : undefined

    const isImageWidthAdjustable =
      hasValidImgCol &&
      (fullBleedContentPosition === POSITION.LEFT || fullBleedContentPosition === POSITION.RIGHT)

    const contentWrapperStyleProps = {
      ...(hasValidImgCol && { width: adaptiveContentWidth }),
      ...(hasValidImgCol && imgColCurrentViewport >= maxCol && { display: 'none' }),
      ...(fullBleedContentChildrenAlign && {
        alignSelf: fullBleedContentChildrenAlign
      })
    }

    const columnFlex = {
      flexGrow: interactiveCard?.body ? 0 : 1,
      flexShrink: 1,
      justifyContent: 'space-between'
    }

    const cardBaseTokens = Object.fromEntries(
      Object.entries(tokens).filter(
        ([key]) =>
          ![
            'paddingTop',
            'paddingBottom',
            'paddingLeft',
            'paddingRight',
            ...(backgroundImage ? ['backgroundColor', 'gradient', 'backgroundGradient'] : [])
          ].includes(key)
      )
    )

    const cardBaseVariant = backgroundImage
      ? {
          ...(interactiveCard?.body ? mergedVariant : variant),
          padding: 'custom',
          style: undefined
        }
      : { ...(interactiveCard?.body ? mergedVariant : variant), padding: 'custom' }

    const isHorizontalFullBleed =
      fullBleedContentPosition === POSITION.LEFT || fullBleedContentPosition === POSITION.RIGHT
    const isVerticalFullBleed =
      fullBleedContentPosition === POSITION.TOP || fullBleedContentPosition === POSITION.BOTTOM

    const imageWrapperStyleProps = {
      ...(isImageWidthAdjustable && { width: fullBleedImageWidth }),
      ...(isImageWidthAdjustable &&
        imgColCurrentViewport >= maxCol && { borderRadius, overflow: 'hidden' }),
      ...(isImageWidthAdjustable && imgColCurrentViewport === 0 && { display: 'none' })
    }

    return (
      <CardBase
        ref={ref}
        variant={cardBaseVariant}
        tokens={cardBaseTokens}
        backgroundImage={backgroundImage}
        onPress={fullBleedInteractive ? undefined : onPress}
        {...(interactiveCard?.selectionType && { interactiveCard, id: rest.id })}
        {...selectProps(restProps)}
      >
        {interactiveCard?.selectionType && children ? (
          <CardContent
            tokens={getCardContentTokens(tokens, { backgroundImage })}
            variant={variant}
            withFooter={hasFooter}
            backgroundImage={backgroundImage}
          >
            {children}
          </CardContent>
        ) : null}
        {interactiveCard?.body && !interactiveCard.selectionType ? (
          <>
            <PressableCardBase
              ref={ref}
              tokens={getThemeTokens}
              dataSet={dataSet}
              onPress={onPress}
              href={interactiveCard?.href}
              hrefAttrs={interactiveCard?.hrefAttrs}
              {...selectProps(restProps)}
            >
              {(cardState) => (
                <>
                  {typeof interactiveCard?.body === 'function'
                    ? interactiveCard.body(cardState)
                    : interactiveCard.body}
                </>
              )}
            </PressableCardBase>
            {children && fullBleedContentPosition === POSITION.NONE && !fullBleedInteractive ? (
              <CardContent
                tokens={getCardContentTokens(tokens, { backgroundImage })}
                variant={variant}
                withFooter={hasFooter}
                backgroundImage={backgroundImage}
              >
                {children}
              </CardContent>
            ) : null}
          </>
        ) : null}
        {fullBleedInteractive ? (
          <PressableCardBase
            ref={ref}
            tokens={getFullBleedInteractiveCardTokens}
            dataSet={dataSet}
            onPress={effectiveFullBleedOnPress}
            href={effectiveFullBleedHref}
            hrefAttrs={effectiveFullBleedHrefAttrs}
            {...selectProps(restProps)}
          >
            {(cardState) => {
              let overlayOpacity = 0
              if (cardState.pressed) {
                overlayOpacity = 0.2
              } else if (cardState.hover) {
                overlayOpacity = 0.1
              }

              const focusTokens = getFocusBorderTokens(cardState)
              const showFocusBorder = cardState.focus && focusTokens.borderWidth > 0

              return (
                <InteractiveCardWrapper>
                  <StackView
                    direction={contentStackDirection}
                    tokens={getStackViewTokens(columnFlex, contentStackAlign)}
                    space={0}
                  >
                    {children ? (
                      <ConditionalWrapper
                        WrapperComponent={DynamicWidthContainer}
                        wrapperProps={contentWrapperStyleProps}
                        condition={isImageWidthAdjustable}
                      >
                        <CardContent
                          tokens={{
                            ...getCardContentTokens(tokensWithoutBg, {
                              backgroundImage,
                              fullBleedContentChildrenAlign,
                              useTransparentBackground: true
                            }),
                            paddingTop:
                              tokens.paddingTop !== undefined
                                ? tokens.paddingTop
                                : allThemeTokens.paddingTop,
                            paddingBottom:
                              tokens.paddingBottom !== undefined
                                ? tokens.paddingBottom
                                : allThemeTokens.paddingBottom,
                            paddingLeft:
                              tokens.paddingLeft !== undefined
                                ? tokens.paddingLeft
                                : allThemeTokens.paddingLeft,
                            paddingRight:
                              tokens.paddingRight !== undefined
                                ? tokens.paddingRight
                                : allThemeTokens.paddingRight
                          }}
                          variant={variant}
                          withFooter={hasFooter}
                          backgroundImage={backgroundImage}
                        >
                          {children}
                        </CardContent>
                      </ConditionalWrapper>
                    ) : null}
                    {fullBleedContentPosition !== POSITION.NONE && (
                      <ConditionalWrapper
                        WrapperComponent={DynamicWidthContainer}
                        wrapperProps={imageWrapperStyleProps}
                        condition={
                          isImageWidthAdjustable || isHorizontalFullBleed || isVerticalFullBleed
                        }
                      >
                        <ConditionalWrapper
                          WrapperComponent={FullBleedPaddingWrapper}
                          wrapperProps={fullBleedPaddingValues}
                          condition={hasFullBleedPadding}
                        >
                          <FullBleedContent
                            borderRadius={fullBleedBorderRadius}
                            {...fullBleedContentPropsClean}
                            position={fullBleedContentPosition}
                            cardState={undefined}
                          />
                        </ConditionalWrapper>
                      </ConditionalWrapper>
                    )}
                  </StackView>
                  <InteractiveOverlay overlayOpacity={overlayOpacity} borderRadius={borderRadius} />
                  {showFocusBorder && (
                    <FocusBorder
                      borderWidth={`${focusTokens.borderWidth}px`}
                      borderColor={focusTokens.borderColor}
                      borderRadius={borderRadius}
                    />
                  )}
                </InteractiveCardWrapper>
              )
            }}
          </PressableCardBase>
        ) : null}
        {!fullBleedInteractive &&
        !interactiveCard?.body &&
        fullBleedContentPosition === POSITION.NONE &&
        children ? (
          <CardContent
            tokens={getCardContentTokens(tokens, {
              backgroundImage,
              fullBleedContentChildrenAlign
            })}
            variant={variant}
            withFooter={hasFooter}
            backgroundImage={backgroundImage}
          >
            {children}
          </CardContent>
        ) : null}
        {!fullBleedInteractive && fullBleedContentPosition !== POSITION.NONE ? (
          <StackView
            direction={contentStackDirection}
            tokens={getStackViewTokens(columnFlex, contentStackAlign)}
            space={0}
          >
            {children ? (
              <ConditionalWrapper
                WrapperComponent={DynamicWidthContainer}
                wrapperProps={contentWrapperStyleProps}
                condition={isImageWidthAdjustable}
              >
                <CardContent
                  tokens={getCardContentTokens(tokens, {
                    backgroundImage,
                    fullBleedContentChildrenAlign
                  })}
                  variant={variant}
                  withFooter={hasFooter}
                  backgroundImage={backgroundImage}
                >
                  {children}
                </CardContent>
              </ConditionalWrapper>
            ) : null}
            <ConditionalWrapper
              WrapperComponent={DynamicWidthContainer}
              wrapperProps={imageWrapperStyleProps}
              condition={isImageWidthAdjustable || isHorizontalFullBleed || isVerticalFullBleed}
            >
              <ConditionalWrapper
                WrapperComponent={FullBleedPaddingWrapper}
                wrapperProps={fullBleedPaddingValues}
                condition={hasFullBleedPadding}
              >
                <FullBleedContent
                  borderRadius={fullBleedBorderRadius}
                  {...fullBleedContentPropsClean}
                  position={fullBleedContentPosition}
                  cardState={undefined}
                />
              </ConditionalWrapper>
            </ConditionalWrapper>
          </StackView>
        ) : null}
        {footer && (
          <CardFooter padding={footerPadding} tokens={tokens} variant={variant}>
            {footer}
          </CardFooter>
        )}
      </CardBase>
    )
  }
)

const positionValues = Object.values(POSITION)
const alignValues = ['start', 'end', 'center', 'stretch']
const PositionedFullBleedContentPropType = PropTypes.shape({
  position: responsiveProps.getTypeOptionallyByViewport(PropTypes.oneOf(positionValues)).isRequired,
  align: responsiveProps.getTypeOptionallyByViewport(PropTypes.oneOf(alignValues)),
  contentAlign: responsiveProps.getTypeOptionallyByViewport(PropTypes.oneOf(alignValues)),
  /**
   * Make the full bleed content interactive.
   * When true, the entire card (including the full bleed content) becomes interactive.
   */
  interactive: PropTypes.bool,
  /**
   * Function to call when the full bleed content is pressed.
   * If not provided, falls back to the Card's onPress prop for backward compatibility.
   */
  onPress: PropTypes.func,
  /**
   * URL to navigate to when the full bleed content is pressed.
   * If not provided, falls back to the Card's href prop for backward compatibility.
   */
  href: PropTypes.string,
  /**
   * Additional attributes for the href link.
   * If not provided, falls back to the Card's hrefAttrs prop for backward compatibility.
   */
  hrefAttrs: PropTypes.shape(hrefAttrsProp.types),
  // eslint-disable-next-line react/forbid-foreign-prop-types
  ...FullBleedContent.propTypes
})

Card.displayName = 'Card'

Card.propTypes = {
  ...selectedSystemPropTypes,
  /**
   * Card content.
   */
  children: PropTypes.node,
  /**
   * Card footer.
   */
  footer: PropTypes.node,
  /**
   * Custom card footer padding.
   */
  footerPadding: paddingProp.propType,
  /**
   * Custom full bleed content padding.
   * When true, inherits the card's own padding (from variant/tokens).
   * When an object, provides custom padding overrides: { paddingTop, paddingBottom, paddingLeft, paddingRight }.
   * Padding is automatically adjusted based on the full bleed content's position.
   */
  fullBleedPadding: PropTypes.oneOfType([PropTypes.bool, paddingProp.propType]),
  /**
   * Full bleed image to be placed on the card, deprecated in favor of `fullBleedContent`.
   *
   * @deprecated
   */
  fullBleedImage: PositionedFullBleedContentPropType,
  /**
   * Full bleed content to be placed on the card.
   */
  fullBleedContent: PositionedFullBleedContentPropType,
  /**
   * Card tokens.
   */
  tokens: getTokensPropType('Card'),
  /**
   * Card variant.
   */
  variant: variantProp.propType,
  /**
   * Function to call on pressing the card.
   * Note: This is only available when `interactive` variant is used.
   */
  onPress: PropTypes.func,
  /**
   * Object to set interactive card's properties
   * - body: The body of the interactive card, can be any renderable node
   * - tokens: The tokens to be used for the interactive card
   * - variant: The variant to be used for the interactive card
   * - href: The href to be used for the interactive card
   * - hrefAttrs: The href attributes to be used for the interactive card
   */
  interactiveCard: PropTypes.shape({
    body: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
    tokens: getTokensPropType('Card'),
    selectionType: PropTypes.oneOf(['checkbox', 'radiogroup']),
    variant: variantProp.propType,
    href: PropTypes.string,
    hrefAttrs: PropTypes.shape(hrefAttrsProp.types)
  }),
  /**
   * Apply background image to the card.
   */
  backgroundImage: PropTypes.shape({
    // src is either a URI string or an object when used responsively to provide different image sources for different screen sizes
    src: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
    alt: PropTypes.string,
    resizeMode: responsiveProps.getTypeOptionallyByViewport(
      PropTypes.oneOf(['cover', 'contain', 'stretch', 'repeat', 'center'])
    )
  }),
  /**
   * Data set for the card.
   */
  dataSet: PropTypes.object
}

export default Card
