import React, { forwardRef } from 'react'
import PropTypes from 'prop-types'
import { css } from '@mxenabled/cssinjs'
import { useTokens } from '@kyper/tokenprovider'

export const BUTTON_VARIANTS = {
  PRIMARY: 'primary',
  NEUTRAL: 'neutral',
  TRANSPARENT: 'transparent',
  TRANSPARENT_DESTRUCTIVE: 'transparent-destructive',
  TRANSPARENT_TERTIARY: 'transparent-tertiary',
  LINK: 'link',
  LINK_TERTIARY: 'link-tertiary',
  LINK_DESTRUCTIVE: 'link-destructive',
  DESTRUCTIVE: 'destructive',
}

export const BUTTON_SIZES = {
  LARGE: 'large',
  SMALL: 'small',
}

export const Button = forwardRef(
  (
    {
      children,
      className = '',
      disabled,
      onClick,
      size,
      variant = BUTTON_VARIANTS.NEUTRAL,
      ...rest
    },
    ref,
  ) => {
    const tokens = useTokens()
    const styles = getStyles(tokens, disabled, size)

    return (
      <button
        aria-disabled={disabled}
        className={`${css(styles)} kyper-button kyper-${variant} ${
          disabled ? 'kyper-button-disabled' : ''
        } ${className}`}
        onClick={!disabled ? onClick : e => e.preventDefault()}
        ref={ref}
        type="button"
        {...rest}
      >
        {children}
      </button>
    )
  },
)

const getStyles = (tokens, disabled, size) => ({
  display: 'flex',
  alignItems: 'center',
  justifyContent: 'center',
  border: 'none',
  borderRadius: tokens.BorderRadius.Button,
  cursor: disabled ? 'not-allowed' : 'pointer',
  whiteSpace: 'nowrap',
  fontSize: tokens.FontSize.Button,
  fontFamily: tokens.Font.Semibold,
  position: 'relative',
  padding: `0px ${tokens.Spacing.ButtonPadding}px`,
  margin: 0,
  width: 'auto',
  height: '44px',
  transition: `all ${tokens.Time.Short}ms ${tokens.Easing.Default}`,
  '&:focus': {
    outline: 'none',
    boxShadow: tokens.BoxShadow.FocusRingDefault,
  },
  [`&.kyper-${BUTTON_VARIANTS.PRIMARY}`]: {
    backgroundColor: tokens.BackgroundColor.ButtonPrimary,
    color: tokens.TextColor.ButtonPrimary,
    '&:not(.kyper-button-disabled):hover': {
      backgroundColor: tokens.BackgroundColor.ButtonPrimaryHover,
      color: tokens.TextColor.ButtonPrimary,
    },

    ...(disabled && {
      backgroundColor: tokens.BackgroundColor.ButtonPrimaryDisabled,
      color: tokens.TextColor.ButtonPrimaryDisabled,
    }),
  },
  [`&.kyper-${BUTTON_VARIANTS.DESTRUCTIVE}`]: {
    backgroundColor: tokens.BackgroundColor.ButtonDestructive,
    color: tokens.TextColor.ButtonDestructive,
    '&:not(.kyper-button-disabled):hover': {
      backgroundColor: tokens.BackgroundColor.ButtonDestructiveHover,
      color: tokens.TextColor.ButtonDestructive,
    },

    ...(disabled && {
      backgroundColor: tokens.BackgroundColor.ButtonDestructiveDisabled,
      color: tokens.TextColor.ButtonDestructiveDisabled,
    }),
  },
  [`&.kyper-${BUTTON_VARIANTS.NEUTRAL}`]: {
    backgroundColor: tokens.BackgroundColor.ButtonNeutral,
    border: '1px solid',
    borderColor: tokens.BorderColor.ButtonNeutral,
    color: tokens.TextColor.ButtonNeutral,
    '&:not(.kyper-button-disabled):hover': {
      color: tokens.TextColor.ButtonNeutralHover,
      backgroundColor: tokens.BackgroundColor.ButtonNeutralHover,
      borderColor: tokens.BorderColor.ButtonNeutralHover,
    },

    ...(disabled && {
      backgroundColor: tokens.BackgroundColor.ButtonNeutralDisabled,
      color: tokens.TextColor.ButtonNeutralDisabled,
    }),
  },
  [`&.kyper-${BUTTON_VARIANTS.TRANSPARENT}`]: {
    backgroundColor: 'transparent',
    color: tokens.TextColor.ButtonTransparent,
    '&:not(.kyper-button-disabled):hover': {
      color: tokens.TextColor.ButtonTransparentHover,
      backgroundColor: tokens.BackgroundColor.ButtonTransparentHover,
    },

    ...(disabled && {
      color: tokens.TextColor.ButtonTransparentDisabled,
    }),
  },
  [`&.kyper-${BUTTON_VARIANTS.TRANSPARENT_DESTRUCTIVE}`]: {
    backgroundColor: 'transparent',
    color: tokens.TextColor.Error,
    '&:not(.kyper-button-disabled):hover': {
      color: tokens.TextColor.ButtonTransparentDestructiveHover,
      backgroundColor: tokens.BackgroundColor.ButtonTransparentDestructiveHover,
    },

    ...(disabled && {
      color: tokens.TextColor.ButtonTransparentDisabled,
    }),
  },
  [`&.kyper-${BUTTON_VARIANTS.TRANSPARENT_TERTIARY}`]: {
    backgroundColor: 'transparent',
    color: tokens.TextColor.ButtonTransparentTertiary,
    '&:not(.kyper-button-disabled):hover': {
      color: tokens.TextColor.ButtonTransparentHover,
      backgroundColor: tokens.BackgroundColor.ButtonTransparentHover,
    },

    ...(disabled && {
      color: tokens.TextColor.ButtonTransparentDisabled,
    }),
  },
  [`&.kyper-${BUTTON_VARIANTS.LINK}`]: {
    backgroundColor: 'transparent',
    color: tokens.TextColor.ButtonLink,
    textDecoration: 'none',
    lineHeight: tokens.LineHeight.Body,
    height: tokens.LineHeight.Body,
    cursor: 'pointer',
    boxSizing: 'border-box',
    borderBottom: '1px solid',
    borderColor: 'transparent',
    borderRadius: '0',
    padding: '0',
    fontSize:
      size === BUTTON_SIZES.SMALL ? tokens.FontSize.ButtonLinkSmall : tokens.FontSize.Button,
    '&:not(.kyper-button-disabled):hover': {
      backgroundColor: tokens.BackgroundColor.ButtonLinkHover,
      color: tokens.TextColor.ButtonLinkHover,
      borderColor: tokens.BorderColor.ButtonLinkHover,
      outline: 'none',
    },

    ...(disabled && {
      color: tokens.TextColor.ButtonTransparentDisabled,
    }),
  },
  [`&.kyper-${BUTTON_VARIANTS.LINK_TERTIARY}`]: {
    backgroundColor: 'transparent',
    color: tokens.TextColor.ButtonLinkTertiary,
    textDecoration: 'none',
    lineHeight: tokens.LineHeight.Body,
    height: tokens.LineHeight.Body,
    cursor: 'pointer',
    boxSizing: 'border-box',
    borderBottom: '1px solid',
    borderColor: 'transparent',
    borderRadius: '0',
    padding: '0',
    fontSize:
      size === BUTTON_SIZES.SMALL ? tokens.FontSize.ButtonLinkSmall : tokens.FontSize.Button,
    '&:not(.kyper-button-disabled):hover': {
      backgroundColor: tokens.BackgroundColor.ButtonLinkHover,
      color: tokens.TextColor.ButtonLinkHover,
      borderColor: tokens.BorderColor.ButtonLinkHover,
      outline: 'none',
    },

    ...(disabled && {
      color: tokens.TextColor.ButtonTransparentDisabled,
    }),
  },
  [`&.kyper-${BUTTON_VARIANTS.LINK_DESTRUCTIVE}`]: {
    backgroundColor: 'transparent',
    color: tokens.TextColor.ButtonLinkDestructive,
    textDecoration: 'none',
    lineHeight: tokens.LineHeight.Body,
    height: tokens.LineHeight.Body,
    cursor: 'pointer',
    boxSizing: 'border-box',
    borderBottom: '1px solid',
    borderColor: 'transparent',
    borderRadius: '0',
    padding: '0',
    fontSize:
      size === BUTTON_SIZES.SMALL ? tokens.FontSize.ButtonLinkSmall : tokens.FontSize.Button,
    '&:not(.kyper-button-disabled):hover': {
      color: tokens.TextColor.ButtonLinkDestructiveHover,
      borderColor: tokens.BorderColor.ButtonLinkDestructiveHover,
      outline: 'none',
    },

    ...(disabled && {
      color: tokens.TextColor.ButtonTransparentDisabled,
    }),
  },
})

Button.propTypes = {
  className: PropTypes.string,
  /**
   * ** Disables the onClick function and adds `aria-disabled` so that the button is still tabbable for accessibility.
   */
  disabled: PropTypes.bool,
  onClick: PropTypes.func,
  /**
   * ** Allows you to change the size of the text for the `link` variants. Does not affect other button variants. You can import `BUTTON_SIZES` if you want to use the constants instead of typing the string values.
   */
  size: PropTypes.oneOf(Object.values(BUTTON_SIZES)),
  /**
   * ** You can import `BUTTON_VARIANTS` if you want to use the constants instead of typing the string values.
   */
  variant: PropTypes.oneOf(Object.values(BUTTON_VARIANTS)),
}

Button.displayName = 'Button'
