import { useMemo } from 'react'

import { styled, useStyleConfig, vui, VuiComponent } from '../core'
import { cs, filterUndefined, isReactText, isString } from '../utils'
import { LinkProvider } from './context'
import { LinkProps } from './link.types'
import LinkIcon from './linkIcon'
import LinkText from './linkText'

export const LinkBase = styled.aBox.attrs((props: LinkProps) => ({
  isUnderlined: props.isUnderlined || false,
}))`
  align-items: center;
  border-radius: none;
  cursor: pointer;
  display: inline-flex;
  line-height: normal;
  outline: none;
  text-decoration: none;
  transition-duration: instant;
  width: fit-content;
  position: relative;

  &:not(.vui-listItemLink)::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    height: ${props => (props.isUnderlined ? '1px' : '0')};
    background-color: currentColor;
    opacity: ${props => (props.isUnderlined ? '1' : '0')};
  }

  &:hover::after {
    height: 2px;
    opacity: 1;
  }
`

/**
 * Displays a link item. Handles different underline scenarios and opening external links in new tab.
 * Exposes some props to the children via context.
 */
export const Link = vui<'a', LinkProps>((props, ref) => {
  const {
    children,
    className,
    fontWeight,
    iconLeft,
    iconRight,
    isExternal,
    isUnderlined,
    size,
    text,
    variant,
    weight,
    ...rest
  } = props
  const styles = useStyleConfig('Link', props)

  const context = useMemo(() => filterUndefined({ size, variant }), [size, variant])

  const aliasedProps = filterUndefined({
    fontWeight: weight || fontWeight,
    rel: isExternal ? 'noopener' : undefined,
    target: isExternal ? '_blank' : undefined,
  })

  return (
    <LinkProvider value={context}>
      <LinkBase
        className={cs('vui-link', className)}
        focusRing={2}
        isUnderlined={isUnderlined}
        ref={ref}
        {...styles.container}
        {...aliasedProps}
        {...rest}
      >
        {isString(iconLeft) ? <LinkIcon mr={1} name={iconLeft} /> : iconLeft}
        {children ?? (isReactText(text) ? <LinkText text={text} /> : text)}
        {isString(iconRight) ? <LinkIcon ml={1} name={iconRight} /> : iconRight}
      </LinkBase>
    </LinkProvider>
  )
}) as VuiComponent<'a', LinkProps> & {
  Icon: typeof LinkIcon
  Text: typeof LinkText
}

Link.Icon = LinkIcon
Link.Text = LinkText
Link.displayName = 'Link'
export default Link
