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

// 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
}))

/**
 * Showcase and guide users to another page, offering a description of that page's story.
 * Whole card is interactive, width expands based on column or container.
 *
 * - Use `tag` to show category of content
 * - Use `date` to show when the story was published
 * - Use `title` to show title of the story
 * - Use `description` to show description of the story
 * - Use `href` to set the target URL
 * - Use `fullBleedContent` to set the thumbnail image
 */
const StoryCard = React.forwardRef(
  (
    {
      tag,
      date,
      title,
      description,
      fullBleedImage,
      fullBleedContent = fullBleedImage,
      onPress,
      href,
      tokens,
      variant = {},
      ...rest
    },
    ref
  ) => {
    const { fullBleedContentPosition, contentStackDirection, fullBleedContentProps } =
      useFullBleedContentProps({
        ...fullBleedContent,
        position: 'bottom'
      })

    const generalTokens = useThemeTokens('StoryCard', tokens, variant)
    const getTokens = useThemeTokensCallback('StoryCard', tokens, variant)
    const getPressableCardTokens = (cardState) => getTokens(cardState)

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

    return (
      <PressableCardBase
        ref={ref}
        onPress={onPress}
        href={href}
        hrefAttrs={hrefAttrs}
        tokens={getPressableCardTokens}
        {...selectProps(unusedRest)}
      >
        {(cardState) => {
          const { borderRadius, borderWidth } = getPressableCardTokens(cardState)

          // Stop content jumping around as border size changes
          const borderOffset = borderWidth - generalTokens.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 } }}
              >
                <StackWrap
                  space={1}
                  tokens={{ justifyContent: 'space-between', alignItems: 'baseline' }}
                >
                  {Boolean(tag) && <Typography variant={{ size: 'eyebrow' }}>{tag}</Typography>}
                  {Boolean(date) && (
                    // TODO: get user locale and apply date formatting: "MMM DD, YYYY" for `en` and "YYYY-MM-DD" for `fr`
                    // Get locale based on decision of https://github.com/telus/universal-design-system/issues/715
                    <Typography variant={{ size: 'small' }}>{date}</Typography>
                  )}
                </StackWrap>
                <Spacer space={2} />
                <Divider variant={{ decorative: true }} />
                <Spacer space={3} />
                <Typography variant={{ size: 'h3' }}>{title}</Typography>
                <Spacer space={2} />
                <Typography>{description}</Typography>
              </Box>
              {Boolean(fullBleedContentProps.src || fullBleedContentProps.content) && (
                <FullBleedOffsetOuter borderOffset={borderOffset}>
                  <FullBleedOffsetInner borderOffset={borderOffset}>
                    <FullBleedContent
                      borderRadius={fullBleedBorderRadius}
                      {...fullBleedContentProps}
                    />
                  </FullBleedOffsetInner>
                </FullBleedOffsetOuter>
              )}
            </StackView>
          )
        }}
      </PressableCardBase>
    )
  }
)

StoryCard.displayName = 'StoryCard'

StoryCard.propTypes = {
  ...selectedSystemPropTypes,
  tokens: getTokensPropType('StoryCard'),
  /**
   * The URL of the story to be navigated to. Note that `Video` component does not play well when used within
   * a `StoryCard` 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,
  /**
   * Text stating the date a story was published.
   */
  date: PropTypes.string.isRequired,
  /**
   * Text stating the title or headline of the story.
   */
  title: PropTypes.string.isRequired,
  /**
   * Text giving a short description of the story. One paragraph of plain text.
   */
  description: 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 image to be placed on the card.
   */
  fullBleedContent: PropTypes.exact(FullBleedContent.propTypes || {})
}

export default withLinkRouter(StoryCard)
