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

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

const StyledSup = styled.sup(
  ({ $fontSize, $lineHeight, $paddingLeft, $paddingRight, $fontName, $fontWeight, $color }) => {
    return {
      border: 0,
      color: $color ?? 'inherit',
      cursor: 'pointer',
      // we want to fallback on 'smaller' but have a valid size when a custom font size is provided.
      fontSize: $fontSize ? `${$fontSize}px` : 'smaller',
      lineHeight: $lineHeight ?? `${$fontSize * 2}px`,
      margin: 0,
      paddingVertical: 0,
      paddingLeft: $paddingLeft,
      paddingRight: $paddingRight,
      textDecoration: 'underline',
      // apply font family
      ...applyTextStyles({ fontName: $fontName, fontWeight: $fontWeight })
    }
  }
)

/**
 * Use `FootnoteLink` to open `Footnote` component and display related legal content.
 *
 * ## Usage Criteria
 *
 * - Use FootnoteLink to open a Footnote component and display related legal content.
 * - Avoid using FootnoteLink if there is only one annotation on a page. Consider including
 *   the annotation as part of the content whenever possible.
 */
export const FootnoteLink = React.forwardRef(
  ({ copy = 'en', number = [], onClick, fontSize, tokens, variant = {}, ...rest }, ref) => {
    const themeTokens = useThemeTokens('FootnoteLink', tokens, variant)
    const numbers = Array.isArray(number) ? number : [number]
    const refs = numbers.map(() => React.createRef())
    const handleClick = (index) => {
      onClick(numbers[index], refs[index])
    }
    const getCopy = useCopy({ dictionary, copy })

    const handleOnClick = (event, index) => {
      event.preventDefault()
      event.stopPropagation()
      handleClick(index)
    }

    const handleOnKeyDown = (event, index) => {
      if (event.key === 'Enter' || event.key === 13) {
        handleClick(index)
      }
    }

    return (
      <span ref={ref}>
        {numbers.map((num, index) => (
          <StyledSup
            onKeyDown={(event) => handleOnKeyDown(event, index)}
            role="button"
            aria-label={getCopy('a11yLabel')}
            key={num}
            ref={refs[index]}
            onClick={(event) => handleOnClick(event, index)}
            tabIndex={0}
            {...selectProps(rest)}
            $fontSize={fontSize ?? themeTokens.fontSize}
            $lineHeight={themeTokens.lineHeight}
            $paddingLeft={themeTokens.paddingLeft}
            $paddingRight={themeTokens.paddingRight}
            $fontName={themeTokens.fontName}
            $fontWeight={themeTokens.fontWeight}
            $color={themeTokens.color}
          >
            {`${num}${index !== numbers.length - 1 ? ',' : ''}`}
          </StyledSup>
        ))}
      </span>
    )
  }
)

FootnoteLink.displayName = 'FootnoteLink'

const copyShape = PropTypes.shape({
  a11yLabel: PropTypes.string.isRequired
})

FootnoteLink.propTypes = {
  ...selectedSystemPropTypes,
  variant: variantProp.propType,
  /**
   * Use the `copy` prop to either select provided English or French copy by passing 'en' or 'fr' respectively.
   * To provide your own, pass a JSON object with the key `a11yLabel`.
   */
  copy: PropTypes.oneOfType([PropTypes.oneOf(['en', 'fr']), copyShape]),
  /**
   * The footnote number, or multiple numbers if passed as an array.
   * If using an array, a comma-separated group of numbers will be rendered as superscript.
   */
  number: PropTypes.oneOfType([
    PropTypes.number,
    PropTypes.arrayOf(PropTypes.number),
    PropTypes.string,
    PropTypes.arrayOf(PropTypes.string)
  ]).isRequired,
  /**
   * A callback function to handle the click of a FootnoteLink.
   */
  onClick: PropTypes.func.isRequired,
  /**
   * Override default `fontSize` to set specific font size value
   */
  fontSize: PropTypes.oneOfType([PropTypes.number, PropTypes.string])
}
