import React from 'react'

import { cn } from '../../services/cn'
import Button from '../Button/Button'
import ConfirmationPopoverContent from '../ConfirmationPopover/ConfirmationPopoverContent'
import Icon from '../Icons/Icon'
import isClient from '../../services/isClient'
import Popover from '../Popover/Popover'
import ToastContent from '../Toast/ToastContent'
import { type ToastContentProps } from '../Toast/ToastContent'
import { type ConfirmationItem } from '../Button/ButtonComponents/ConfirmationButton'

export type AlertTypes = 'success' | 'error' | 'warning' | 'info'

type BaseAlertProps = ToastContentProps & {
  /** Optional class can be added */
  customClass?: string
  /** Optional prop to add a test id to the Alert for QA testing */
  qaTestId?: string
}

type AlertPropsWithoutCloseButton = BaseAlertProps & {
  close?: never
}

type AlertPropsWithCloseButton = BaseAlertProps & {
  close: {
    /** Close `Alert` function. */
    callout: () => void
    /** Hide or show the close button. */
    show: boolean
    /** Optionally change the behavior for the close button. If set to `confirmation`, then a confirmation will appear when the close button is clicked. */
    confirmation?: ConfirmationItem
  }
}

export type AlertProps =
  | AlertPropsWithoutCloseButton
  | AlertPropsWithCloseButton

const typeStyles = {
  error: 'text-dark-red bg-light-red border-dark-red',
  info: 'text-dark-blue bg-light-blue border-dark-blue',
  warning: 'text-dark-yellow bg-light-yellow border-dark-yellow',
  success: 'text-dark-green bg-light-green border-dark-green',
} as const

const iconColors = {
  error: 'dark-red',
  info: 'dark-blue',
  warning: 'dark-yellow',
  success: 'dark-green',
} as const

const Alert = ({
  customClass = '',
  close,
  qaTestId = 'alert',
  ...rest
}: AlertProps): React.JSX.Element => {
  const { type } = rest

  const iconColor = iconColors[type]

  const closeIcon = (
    <Icon
      icon='x'
      iconSize='12px'
      color={iconColor}
      qaTestId={`${qaTestId}-x-icon`}
    />
  )

  return (
    <div
      className={cn(
        'flex items-center justify-between gap-4 rounded border p-4 font-semibold',
        typeStyles[type],
        customClass,
      )}
      qa-test-id={qaTestId}
      data-testid='Alert'
    >
      <ToastContent {...rest} />
      {close?.show &&
        (close.confirmation ? (
          <Popover
            position='bottom'
            noPadding
            {...(isClient ? { appendTo: document.body } : {})}
            popoverContent={({ setVisible }) => {
              const closePopover = () => setVisible(false)
              return close.confirmation ? (
                <ConfirmationPopoverContent
                  body={close.confirmation.body}
                  header={close.confirmation.header}
                  type={close.confirmation.type ?? 'green'}
                  cancelCallout={closePopover}
                  confirmCallout={() => {
                    closePopover()
                    close.confirmation?.confirmCallout()
                  }}
                  confirmButtonText={close.confirmation.confirmButtonText}
                />
              ) : (
                <></>
              )
            }}
          >
            {({ setVisible }) => (
              <Button as='unstyled' onClick={() => setVisible(true)}>
                {closeIcon}
              </Button>
            )}
          </Popover>
        ) : (
          <Button as='unstyled' onClick={close.callout}>
            {closeIcon}
          </Button>
        ))}
    </div>
  )
}

export default Alert
