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

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

const RibbonWrapper = styled.div`
  width: fit-content;
  position: ${({ left, top }) => (left ?? top ? 'absolute' : 'relative')};
  z-index: 1;
  left: ${({ left }) => left && `${left}px`};
  top: ${({ top }) => top && `${top}px`};
`

const RibbonContainer = styled.div`
  display: flex;
  justify-content: center;
  background: ${({ backgroundColor }) => backgroundColor};
  padding: ${({ padding }) => `${padding}`};
  border-radius: ${({ borderRadius }) => borderRadius};
  width: fit-content;
  box-shadow: ${({ boxShadow, shouldWrap }) => shouldWrap && boxShadow};
  border-bottom-right-radius: ${({ borderRadiusBottomLeft }) => borderRadiusBottomLeft};
  border-bottom-left-radius: ${({ borderRadiusBottomRight }) => borderRadiusBottomRight};
`

const RibbonCurve = styled.div`
  background: ${({ curveBackgroundColor }) => curveBackgroundColor};
  width: ${({ curveWidth }) => curveWidth};
  height: ${({ curveHeight }) => curveHeight};
  margin-top: -${({ curveMarginTop }) => curveMarginTop};
  border-radius: 0 0 0 100%;
  position: relative;
  z-index: -1;
  overflow: hidden;
  &::after {
    content: '';
    border-bottom-left-radius: ${({ curveAfterRadius }) => curveAfterRadius};
    position: absolute;
    height: ${({ curveAfterHeight }) => curveAfterHeight};
    background: ${({ curveAfterBackgroundColor }) => curveAfterBackgroundColor};
    width: ${({ curveAfterWidth }) => curveAfterWidth};
  }
`

const Ribbon = React.forwardRef(
  ({ children, tokens, wrap: shouldWrap = false, left, top, variant = {}, ...rest }, ref) => {
    const {
      backgroundColor,
      borderRadius,
      boxShadowPaddingBottom,
      boxShadowPaddingLeft,
      boxShadowPaddingRight,
      boxShadowPaddingTop,
      boxShadowColor,
      curveAfterBackgroundColor,
      curveAfterHeight,
      curveAfterWidth,
      curveBackgroundColor,
      curveHeight,
      curveAfterRadius,
      curveWidth,
      curveMarginTop,
      paddingBottom,
      paddingLeft,
      paddingRight,
      paddingTop,
      gradient,
      fontColor,
      borderRadiusBottomLeft,
      borderRadiusBottomRight,
      fontName,
      fontWeight,
      fontSize,
      lineHeight
    } = useThemeTokens('Ribbon', tokens, { ...variant, wrap: shouldWrap })

    let background = backgroundColor
    if (gradient) {
      const { type: gradientType, angle: gradientAngle, stops: gradientColors } = gradient
      const gradientBackground = `${gradientType}-gradient(${gradientAngle}deg, ${gradientColors[0].color}, ${gradientColors[1].color})`
      background = gradientBackground
    }
    return (
      <RibbonWrapper
        left={left}
        top={top}
        data-testid="ribbon-wrapper"
        ref={ref}
        {...selectProps(rest)}
      >
        <RibbonContainer
          shouldWrap={shouldWrap}
          backgroundColor={background}
          padding={`${paddingTop}px ${paddingRight}px ${paddingBottom}px ${paddingLeft}px`}
          borderRadius={`${borderRadius}px`}
          boxShadow={`${boxShadowPaddingTop}px ${boxShadowPaddingRight}px ${boxShadowPaddingBottom}px ${boxShadowPaddingLeft}px ${boxShadowColor}`}
          borderRadiusBottomLeft={`${borderRadiusBottomLeft}px`}
          borderRadiusBottomRight={`${borderRadiusBottomRight}px`}
        >
          <Typography
            variant={{ bold: true, inverse: true }}
            tokens={{
              color: fontColor,
              fontName,
              fontWeight,
              fontSize,
              lineHeight
            }}
          >
            {children}
          </Typography>
        </RibbonContainer>
        {shouldWrap && (
          <RibbonCurve
            data-testid="ribbon-curve"
            backgroundColor={backgroundColor}
            curveMarginTop={`${curveMarginTop}px`}
            curveWidth={`${curveWidth}px`}
            curveHeight={`${curveHeight}px`}
            curveBackgroundColor={curveBackgroundColor}
            curveAfterRadius={`${curveAfterRadius}px`}
            curveAfterWidth={`${curveAfterWidth}px`}
            curveAfterHeight={`${curveAfterHeight}px`}
            curveAfterBackgroundColor={curveAfterBackgroundColor}
          />
        )}
      </RibbonWrapper>
    )
  }
)

Ribbon.displayName = 'Ribbon'

Ribbon.propTypes = {
  ...selectedSystemPropTypes,
  tokens: getTokensPropType('Ribbon'),
  children: PropTypes.node,
  /** show/hide the ribbon fold
   * @deprecated please don't rely on `wrap` to turn off the wrapping (use `Badge` instead) as it will be removed in the future
   */
  wrap: PropTypes.bool,
  /** sets the left offset (triggers absolute positioning) */
  left: PropTypes.number,
  /** sets the top offset (triggers absolute positioning) */
  top: PropTypes.number
}

export default Ribbon
