import {useState, useCallback} from 'react'

import {Product} from '@shopify/shop-minis-platform'
import {motion, AnimatePresence} from 'motion/react'

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

interface BuyNowButtonProps {
  disabled?: boolean
  className?: string
  size?: 'default' | 'sm' | 'lg'
  /**
   * The discount code to apply to the purchase.
   */
  discountCode?: string
  /**
   * The GID of the product variant. E.g. `gid://shopify/ProductVariant/456`.
   */
  productVariantId: string
  /**
   * The product to buy now.
   */
  product?: Product
}

export function BuyNowButton({
  disabled = false,
  className,
  size = 'default',
  productVariantId,
  discountCode,
  product,
}: BuyNowButtonProps) {
  const {buyProduct} = useShopCartActions()
  const {navigateToProduct} = useShopNavigation()
  const [isPurchasing, setIsPurchasing] = useState(false)
  const {id, referral} = product ?? {}

  const {showErrorToast} = useErrorToast()

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

    if (id && referral) {
      navigateToProduct({
        productId: id,
      })

      return
    }

    if (isPurchasing) return

    try {
      if (id && productVariantId) {
        setIsPurchasing(true)

        await buyProduct({
          productId: id,
          productVariantId,
          quantity: 1,
          discountCode,
        })

        setIsPurchasing(false)
      }
    } catch (error) {
      showErrorToast({message: 'Failed to complete purchase'})
      setIsPurchasing(false)
    }
  }, [
    disabled,
    id,
    referral,
    isPurchasing,
    navigateToProduct,
    productVariantId,
    buyProduct,
    discountCode,
    showErrorToast,
  ])

  return (
    <Button
      onClick={handleClick}
      disabled={disabled || isPurchasing}
      className={cn('relative overflow-hidden', className)}
      size={size}
      aria-live="polite"
      aria-busy={isPurchasing}
    >
      <AnimatePresence mode="wait">
        <motion.span
          key="text"
          initial={{opacity: 0, y: 10}}
          animate={{opacity: 1, y: 0}}
          exit={{opacity: 0, y: -10}}
          transition={{duration: 0.2}}
        >
          {referral ? 'View product' : 'Buy now'}
        </motion.span>
      </AnimatePresence>
    </Button>
  )
}
