import Box from '../box'
import { useStyleConfig, vui, VuiComponent } from '../core'
import { cs, filterUndefined, isReactText, isString } from '../utils'
import { bannerNotificationElevation, closeButtonVariantMapping, notificationStatusMapping } from './consts'
import { NotificationProvider } from './context'
import { NotificationProps } from './notification.types'
import NotificationButton from './notificationButton'
import NotificationIcon from './notificationIcon'
import NotificationText from './notificationText'
import NotificationTitle from './notificationTitle'

/**
 * Displays informational content, like text and icon with optional action buttons.
 * Handles multiple states, like info, error or loading.
 */
export const Notification = vui<'div', NotificationProps>((props, ref) => {
  const {
    action,
    children,
    className,
    icon,
    onClose,
    size,
    status,
    statusMapping,
    text,
    title,
    variant: variantProp = 'subtleBlue',
    verticalAlign,
    ...rest
  } = props
  const statuses = { ...notificationStatusMapping, ...statusMapping }
  const { variant = variantProp } = statuses[status ?? ''] ?? {}
  const styles = useStyleConfig('Notification', { variant, ...props })

  const iconName = isString(icon) ? icon : statuses[status ?? '']?.iconProps?.name

  const context = filterUndefined<NotificationProps>({ size, status })

  const titleDisplay = action ? 'block' : 'inline-flex'

  const alignSelf = verticalAlign === 'center' ? 'center' : 'flex-start'

  return (
    <NotificationProvider value={context}>
      <Box
        borderRadius="md"
        borderWidth={1}
        className={cs('vui-notification', className)}
        elevation={variant.includes('banner') ? bannerNotificationElevation : undefined}
        ref={ref}
        role="mark"
        w="fit-content"
        {...styles.container}
        {...rest}
      >
        {iconName ? <NotificationIcon alignSelf={alignSelf} name={iconName} /> : icon}

        {children ?? (
          <NotificationText alignSelf={alignSelf}>
            {isReactText(title) ? <NotificationTitle display={titleDisplay} text={title} /> : title} {text}
          </NotificationText>
        )}

        {action}

        {onClose && (
          <NotificationButton
            alignSelf={alignSelf}
            aria-label="close"
            icon="falTimes"
            onClick={onClose}
            variant={closeButtonVariantMapping?.[variant] ?? variant}
            w="32px"
          />
        )}
      </Box>
    </NotificationProvider>
  )
}) as VuiComponent<'div', NotificationProps> & {
  Button: typeof NotificationButton
  Icon: typeof NotificationIcon
  Text: typeof NotificationText
  Title: typeof NotificationTitle
}

Notification.Button = NotificationButton
Notification.Icon = NotificationIcon
Notification.Text = NotificationText
Notification.Title = NotificationTitle
Notification.displayName = 'Notification'

export default Notification
