import React from 'react'
import PropTypes from 'prop-types'
import {
  Icon,
  selectSystemProps,
  Typography,
  useThemeTokens,
  useViewport,
  getTokensPropType
} from '@telus-uds/components-base'
import styled from 'styled-components'
import Image from '../Image'
import { htmlAttrs } from '../utils'

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

const TestimonialContainer = styled.figure(({ testimonialContainerGap }) => ({
  display: 'flex',
  flexDirection: 'column',
  gap: testimonialContainerGap,
  margin: 0
}))

const QuoteContainer = styled.div(({ quoteContainerGap }) => ({
  display: 'flex',
  alignItems: 'center',
  gap: quoteContainerGap
}))

const Divider = styled.div(({ dividerBorder, dividerBackgroundColor }) => ({
  height: dividerBorder,
  background: dividerBackgroundColor,
  width: '100%'
}))

const BlockQuote = styled.blockquote({
  margin: 0
})

const AuthorInfoContainer = styled.div({
  display: 'flex',
  flexDirection: 'column'
})

const Figcaption = styled.figcaption(({ figcaptionGap }) => ({
  display: 'flex',
  alignItems: 'center',
  gap: figcaptionGap
}))

const Testimonial = React.forwardRef(
  (
    {
      showDivider,
      testimonial,
      title,
      imageSrc,
      image = imageSrc,
      additionalInfo,
      testimonialStyle = 'large',
      tokens,
      copy = 'en',
      variant = {},
      ...rest
    },
    ref
  ) => {
    const viewport = useViewport()
    const {
      testimonialContainerGap,
      quoteContainerGap,
      dividerBorder,
      dividerBackgroundColor,
      figcaptionGap,
      textColor,
      icon,
      iconFr,
      iconColor,
      imageSize,
      testimonialFontSizeLarge,
      testimonialLineHeightLarge,
      testimonialFontWeightLarge,
      testimonialFontSizeHeading,
      testimonialLineHeightHeading,
      testimonialFontNameHeading,
      testimonialFontWeightHeading,
      authorFontSize,
      authorLineHeight,
      authorFontName,
      authorFontWeight,
      additionalFontSize,
      additionalLineHeight,
      additionalFontName,
      additionalFontWeight
    } = useThemeTokens('Testimonial', tokens, variant, { viewport })

    const getQuoteTestimonial = (open) => {
      let quote = ''

      if (copy === 'en') quote = open ? '\u201C' : '\u201D'
      else quote = open ? '\u00AB ' : ' \u00BB'

      return quote
    }

    return (
      <TestimonialContainer
        testimonialContainerGap={testimonialContainerGap}
        ref={ref}
        {...selectProps(rest)}
      >
        <QuoteContainer quoteContainerGap={quoteContainerGap}>
          <Icon
            tokens={{ color: iconColor }}
            variant={{ size: 'micro' }}
            icon={copy === 'en' ? icon : iconFr}
          />
          {showDivider && (
            <Divider
              dividerBackgroundColor={dividerBackgroundColor}
              dividerBorder={dividerBorder}
              role="separator"
            />
          )}
        </QuoteContainer>
        <BlockQuote>
          <Typography
            variant={{ size: testimonialStyle === 'large' ? 'large' : 'h3' }}
            tokens={{
              color: textColor,
              fontSize:
                testimonialStyle === 'heading'
                  ? testimonialFontSizeHeading
                  : testimonialFontSizeLarge,
              lineHeight:
                testimonialStyle === 'heading'
                  ? testimonialLineHeightHeading
                  : testimonialLineHeightLarge,
              fontName: testimonialFontNameHeading,
              fontWeight:
                testimonialStyle === 'heading'
                  ? testimonialFontWeightHeading
                  : testimonialFontWeightLarge
            }}
          >
            {`${getQuoteTestimonial(true)}${testimonial}${getQuoteTestimonial()}`}
          </Typography>
        </BlockQuote>
        {(image || title || additionalInfo) && (
          <Figcaption figcaptionGap={figcaptionGap}>
            {image &&
              (typeof image === 'string' ? (
                <Image
                  rounded="circle"
                  src={image}
                  alt={title}
                  width={imageSize}
                  height={imageSize}
                />
              ) : (
                image
              ))}
            {(title || additionalInfo) && (
              <AuthorInfoContainer>
                {title && (
                  <Typography
                    variant={{ size: 'small' }}
                    tokens={{
                      color: textColor,
                      fontSize: authorFontSize,
                      lineHeight: authorLineHeight,
                      fontName: authorFontName,
                      fontWeight: authorFontWeight
                    }}
                  >
                    {title}
                  </Typography>
                )}
                {additionalInfo && (
                  <Typography
                    variant={{ size: 'small' }}
                    tokens={{
                      color: textColor,
                      fontSize: additionalFontSize,
                      lineHeight: additionalLineHeight,
                      fontName: additionalFontName,
                      fontWeight: additionalFontWeight
                    }}
                  >
                    {additionalInfo}
                  </Typography>
                )}
              </AuthorInfoContainer>
            )}
          </Figcaption>
        )}
        {showDivider && (
          <Divider
            dividerBackgroundColor={dividerBackgroundColor}
            dividerBorder={dividerBorder}
            role="separator"
          />
        )}
      </TestimonialContainer>
    )
  }
)

Testimonial.displayName = 'Testimonial'

Testimonial.propTypes = {
  ...selectedSystemPropTypes,
  tokens: getTokensPropType('Testimonial'),
  /**
   * Testimonial content
   */
  testimonial: PropTypes.string.isRequired,
  /**
   * Testimonial author or source
   */
  title: PropTypes.string,
  /**
   * Additional information on the author or source
   */
  additionalInfo: PropTypes.string,
  /**
   * Testimonial style
   */
  testimonialStyle: PropTypes.oneOf(['large', 'heading']),
  /**
   * Whether to show or not dividers at the top and the bottom of the testimonial
   */
  showDivider: PropTypes.bool,
  /**
   * The src attribute for the Image component or custom JSX content to render instead
   */
  image: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
  /**
   * The src attribute for the `Image` component to be displayed on the testimonial
   * @deprecated please use the `image` prop instead
   */
  imageSrc: PropTypes.string
}

export default Testimonial
