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'

/**
 * Navigates directly to Shop's express checkout, bypassing the cart entirely. Use for single-item purchases, limited-time offers, or when reducing friction is critical. Best for impulse buys and focused conversion flows.
 * @publicDocs
 */
export interface BuyNowButtonProps {
  /** Whether the button is disabled */
  disabled?: boolean
  /** CSS class name */
  className?: string
  /** Button size variant */
  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, variants, selectedVariant} = product ?? {}

  // Look up the matching variant from `variants` first (productLists/savedProducts
  // path); otherwise fall back to `selectedVariant` (useProduct/useProducts marketplace path).
  const matchingVariant =
    variants?.find(variant => variant.id === productVariantId) ??
    (selectedVariant?.id === productVariantId ? selectedVariant : undefined)
  const isSoldOut = matchingVariant?.availableForSale === false
  // Referral products only navigate to the PDP — never gate them on stock so a
  // sold-out selected variant doesn't strand the user without a way to switch.
  const isDisabled = disabled || isPurchasing || (!referral && isSoldOut)

  const {showErrorToast} = useErrorToast()

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

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

      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)
    }
  }, [
    isDisabled,
    id,
    referral,
    navigateToProduct,
    productVariantId,
    buyProduct,
    discountCode,
    showErrorToast,
  ])

  const getButtonText = () => {
    if (referral) return 'View product'
    if (isSoldOut) return 'Sold out'
    return 'Buy now'
  }
  const buttonText = getButtonText()

  return (
    <Button
      onClick={handleClick}
      disabled={isDisabled}
      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}}
        >
          {buttonText}
        </motion.span>
      </AnimatePresence>
    </Button>
  )
}
