import { useCallback, useEffect, useState } from 'react'
import { createPortal } from 'react-dom'
import { CheckCircle2, X, XCircle } from 'lucide-react'
import { m } from 'framer-motion'

import './Notification.scss'
import { uiFadeTransition } from '../../shared/lib/motion'

export type NotificationVariant = 'success' | 'error'

type NotificationProps = {
  variant: NotificationVariant
  title: string
  description?: string
  actionLabel?: string
  autoCloseMs?: number
  showProgress?: boolean
  onAction?: () => void
  onClose: () => void
}

export function Notification({
  variant,
  title,
  description,
  actionLabel,
  autoCloseMs = 4200,
  showProgress = false,
  onAction,
  onClose,
}: NotificationProps) {
  const [isVisible, setIsVisible] = useState(false)

  const handleClose = useCallback(() => {
    setIsVisible(false)

    window.setTimeout(() => {
      onClose()
    }, 220)
  }, [onClose])

  useEffect(() => {
    const frameId = window.requestAnimationFrame(() => {
      setIsVisible(true)
    })

    const timeoutId = window.setTimeout(() => {
      handleClose()
    }, autoCloseMs)

    return () => {
      window.cancelAnimationFrame(frameId)
      window.clearTimeout(timeoutId)
    }
  }, [autoCloseMs, handleClose])

  function handleAction() {
    onAction?.()
    handleClose()
  }

  const Icon = variant === 'success' ? CheckCircle2 : XCircle

  if (typeof document === 'undefined') return null

  return createPortal(
    <m.div
      className={`notification notification--${variant}`}
      role="status"
      aria-live="polite"
      initial={{
        opacity: 0,
        y: 14,
        scale: 0.98,
      }}
      animate={
        isVisible
          ? {
              opacity: 1,
              y: 0,
              scale: 1,
            }
          : {
              opacity: 0,
              y: 14,
              scale: 0.98,
            }
      }
      transition={uiFadeTransition}
    >
      <Icon className="notification__icon" size={26} />

      <div className="notification__content">
        <div className="notification__title">{title}</div>

        {description && (
          <div className="notification__description">{description}</div>
        )}

        {actionLabel && onAction && (
          <button
            className="notification__action"
            type="button"
            onClick={handleAction}
          >
            {actionLabel}
          </button>
        )}
      </div>

      <button
        className="notification__close"
        type="button"
        onClick={handleClose}
        aria-label="Закрыть уведомление"
      >
        <X size={20} />
      </button>

      {showProgress && (
        <span
          className="notification__progress"
          style={{ animationDuration: `${autoCloseMs}ms` }}
        />
      )}
    </m.div>,
    document.body,
  )
}
