import * as React from 'react'
import {useState, useCallback} from 'react'

import {CheckIcon} from 'lucide-react'
import {motion, AnimatePresence} from 'motion/react'

import {useErrorToast, useShopCartActions} from '../../hooks'
import {cn} from '../../lib/utils'
import {Button} from '../atoms/button'

interface AddToCartButtonProps {
  disabled?: boolean
  className?: string
  size?: 'default' | 'sm' | 'lg'
  /**
   * The discount codes to apply to the cart.
   */
  discountCodes?: string[]
  /**
   * The GID of the product. E.g. `gid://shopify/Product/123`.
   */
  productId: string
  /**
   * The GID of the product variant. E.g. `gid://shopify/ProductVariant/456`.
   */
  productVariantId: string
}

export function AddToCartButton({
  disabled = false,
  className,
  size = 'default',
  productId,
  productVariantId,
  discountCodes,
}: AddToCartButtonProps) {
  const {addToCart} = useShopCartActions()
  const [isAdded, setIsAdded] = useState(false)
  const timeoutRef = React.useRef<number | undefined>(undefined)

  const {showErrorToast} = useErrorToast()

  const handleClick = useCallback(async () => {
    if (isAdded || disabled) return

    try {
      // Call the callback if provided
      if (productId && productVariantId) {
        // Optimistic update with error toast
        addToCart({
          productId,
          productVariantId,
          quantity: 1,
          discountCodes,
        })
          .then(() => {})
          .catch(() => {
            showErrorToast({message: 'Failed to add to cart'})
          })
      }

      // Show success state
      setIsAdded(true)

      // Clear any existing timeout
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current)
      }

      // Reset to initial state after delay
      timeoutRef.current = window.setTimeout(() => {
        setIsAdded(false)
      }, 2000)
    } catch (error) {
      // Handle error - reset to initial state
      setIsAdded(false)
      console.error('Failed to add to cart:', error)
    }
  }, [
    isAdded,
    disabled,
    addToCart,
    productId,
    productVariantId,
    discountCodes,
    showErrorToast,
  ])

  // Cleanup timeout on unmount
  React.useEffect(() => {
    return () => {
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current)
      }
    }
  }, [])

  return (
    <Button
      onClick={handleClick}
      disabled={disabled}
      className={cn(
        'relative overflow-hidden transition-all duration-300',
        className
      )}
      size={size}
    >
      <div className="relative flex items-center justify-center">
        <AnimatePresence>
          {isAdded && (
            <motion.div
              initial={{scale: 0, rotate: -180}}
              animate={{scale: 1, rotate: 0}}
              exit={{scale: 0, rotate: 180}}
              transition={{
                duration: 0.4,
                ease: [0.175, 0.885, 0.32, 1.275], // bounce effect
              }}
              className="absolute left-0"
              style={{x: -8}}
            >
              <CheckIcon className="size-4" />
            </motion.div>
          )}
        </AnimatePresence>
        <span className={cn(isAdded && 'pl-5', 'transition-all duration-300')}>
          {isAdded ? 'Added to cart' : 'Add to cart'}
        </span>
      </div>
    </Button>
  )
}
