import React from 'react'
import PropTypes from 'prop-types'
import omit from 'lodash.omit'
import {
  Box,
  getThemeTokens,
  hrefAttrsProp,
  PressableCardBase,
  selectSystemProps,
  Spacer,
  StackView,
  Typography,
  a11yProps,
  focusHandlerProps,
  viewProps,
  withLinkRouter,
  useTheme,
  getTokensPropType
} from '@telus-uds/components-base'
import styled from 'styled-components'
import FullBleedContent, {
  getFullBleedBorderRadius,
  useFullBleedContentProps
} from '../shared/FullBleedContent'
import AuthorDate from './AuthorDate'

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

// Stop changes to the card's inner border width causing the size and
// apparent position of the full bleed image to change.
const FullBleedOffsetOuter = styled.div(({ borderOffset }) => ({
  overflow: 'hidden',
  marginTop: borderOffset * 2
}))
const FullBleedOffsetInner = styled.div(({ borderOffset }) => ({
  position: 'relative',
  margin: 0 - borderOffset
}))

const defaultTokens = {
  minWidth: 0,
  shadow: null,
  contentAlignItems: 'stretch',
  contentJustifyContent: 'flex-start',
  contentFlexGrow: 0,
  contentFlexShrink: 0
}

/**
 * Showcase and guide users to another page, with a preview containing title and a footer.
 * Whole card is interactive, width expands based on column or container.
 *
 * - Use `tag` to show category of content
 * - Use `title` to show title of the story
 * - Use `footer` to show text such as the author / date
 * - Use `href` to set the target URL
 * - Use `fullBleedContent` to set the thumbnail image
 */
const PreviewCard = React.forwardRef(
  (
    {
      tag,
      title,
      footer,
      fullBleedImage,
      fullBleedContent = fullBleedImage,
      onPress,
      href,
      ...rest
    },
    ref
  ) => {
    const { fullBleedContentPosition, contentStackDirection, fullBleedContentProps } =
      useFullBleedContentProps({
        ...fullBleedContent,
        position: 'bottom'
      })
    const {
      components: { PreviewCard: theme }
    } = useTheme()
    const getPressableCardTokens = (cardState) => ({
      ...omit(getThemeTokens(theme, {}, {}, cardState), 'separatorColor'),
      ...defaultTokens
    })

    const { hrefAttrs, rest: unusedRest } = hrefAttrsProp.bundle(rest)

    return (
      <PressableCardBase
        onPress={onPress}
        href={href}
        hrefAttrs={hrefAttrs}
        tokens={getPressableCardTokens}
        ref={ref}
        {...selectProps(unusedRest)}
      >
        {(cardState) => {
          const { borderRadius, borderWidth } = getPressableCardTokens(cardState)
          // Stop content jumping around as border size changes
          const borderOffset = borderWidth - theme.tokens.borderWidth

          const fullBleedBorderRadius = getFullBleedBorderRadius(
            borderRadius + borderOffset,
            fullBleedContentPosition
          )

          return (
            <StackView
              direction={contentStackDirection}
              tokens={{ justifyContent: 'space-between', flexGrow: 1 }}
            >
              <Box
                horizontal={{ xs: 4, lg: 5, options: { subtract: borderOffset } }}
                vertical={{ xs: 5, lg: 7, options: { subtract: borderOffset } }}
              >
                {Boolean(tag) && (
                  <>
                    <Typography variant={{ size: 'eyebrow' }}>{tag}</Typography>
                    <Spacer space={2} />
                  </>
                )}
                <Typography variant={{ size: 'h4' }}>{title}</Typography>
                {Boolean(footer) && (
                  <>
                    <Spacer space={2} />
                    {typeof footer === 'string' ? (
                      <Typography variant={{ size: 'small' }}>{footer}</Typography>
                    ) : (
                      footer
                    )}
                  </>
                )}
              </Box>
              {Boolean(fullBleedContentProps.src || fullBleedContentProps.content) && (
                <FullBleedOffsetOuter borderOffset={borderOffset}>
                  <FullBleedOffsetInner borderOffset={borderOffset}>
                    <FullBleedContent
                      borderRadius={fullBleedBorderRadius}
                      {...fullBleedContentProps}
                    />
                  </FullBleedOffsetInner>
                </FullBleedOffsetOuter>
              )}
            </StackView>
          )
        }}
      </PressableCardBase>
    )
  }
)

PreviewCard.displayName = 'PreviewCard'

// Provide standard author/date footer as a preset with the export
PreviewCard.AuthorDate = AuthorDate

PreviewCard.propTypes = {
  ...selectedSystemPropTypes,
  tokens: getTokensPropType('PreviewCard'),
  /**
   * The URL of the story to be navigated to. Note that `Video` component does not play well when used within
   * a `PreviewCard` with `href` prop set (the volume and progress sliders can be clicked but are not draggable).
   * Please use `onPress` prop instead `href` to organize navigation in cases like this.
   *
   * @see https://github.com/telus/allium-design-system/issues/6
   */
  href: PropTypes.string,
  /**
   * Optional function to be called on press e.g. for within-page navigation.
   */
  onPress: PropTypes.func,
  /**
   * Text stating the category of the content.
   */
  tag: PropTypes.string,
  /**
   * Section containing additional information, such as author and date.
   * Use `<PreviewCard.AuthorDate author={...} date={...} />` here for author and date.
   */
  footer: PropTypes.oneOfType([PropTypes.node, PropTypes.string]),
  /**
   * Text stating the title or headline of the story.
   */
  title: PropTypes.string.isRequired,
  /**
   * Full bleed image to be placed on the card, deprecated in favor of `fullBleedContent`.
   *
   * @deprecated
   */
  fullBleedImage: PropTypes.exact(FullBleedContent.propTypes || {}),
  /**
   * Full bleed content to be placed on the card.
   */
  fullBleedContent: PropTypes.exact(FullBleedContent.propTypes || {})
}

export default withLinkRouter(PreviewCard)
