import * as React from 'react'

import {type Product} from '@shopify/shop-minis-platform'
import {cva, type VariantProps} from 'class-variance-authority'
import {Star} from 'lucide-react'
import {Slot as SlotPrimitive} from 'radix-ui'

import {useShopNavigation} from '../../hooks/navigation/useShopNavigation'
import {useSavedProductsActions} from '../../hooks/user/useSavedProductsActions'
import {formatMoney} from '../../lib/formatMoney'
import {cn} from '../../lib/utils'
import {Touchable} from '../atoms/touchable'
import {Card, CardContent, CardAction} from '../ui/card'

import {FavoriteButton} from './favorite-button'

const productLinkVariants = cva('', {
  variants: {
    layout: {
      horizontal: 'w-full !flex-row items-center gap-3 px-4 py-3',
      vertical: 'flex-col',
    },
    discount: {
      none: '',
      small: '',
      large: '',
    },
  },
  defaultVariants: {
    layout: 'horizontal',
    discount: 'none',
  },
})

// Primitive components (building blocks)
export interface ProductLinkRootProps
  extends React.ComponentProps<typeof Card>,
    VariantProps<typeof productLinkVariants> {
  layout?: 'horizontal' | 'vertical'
  asChild?: boolean
  onPress?: () => void
}

function ProductLinkRoot({
  className,
  layout,
  discount,
  asChild = false,
  onPress,
  ...props
}: ProductLinkRootProps) {
  const Comp = asChild ? SlotPrimitive.Root : Card

  return (
    <Touchable
      onClick={onPress}
      whileTap={{opacity: 0.7}}
      transition={{
        opacity: {type: 'tween', duration: 0.08, ease: 'easeInOut'},
      }}
    >
      <Comp
        className={cn(
          productLinkVariants({layout, discount}),
          'border-0 bg-white rounded-xl shadow-lg shadow-black/10',
          className
        )}
        {...props}
      />
    </Touchable>
  )
}

function ProductLinkImage({
  className,
  layout = 'horizontal',
  ...props
}: React.ComponentProps<'div'> & {layout?: 'horizontal' | 'vertical'}) {
  return (
    <div
      data-slot="product-link-image"
      className={cn(
        'overflow-hidden rounded-md bg-muted',
        layout === 'horizontal'
          ? 'h-16 w-16 flex-shrink-0'
          : 'aspect-square w-full',
        className
      )}
      {...props}
    />
  )
}

function ProductLinkInfo({
  className,
  layout = 'horizontal',
  ...props
}: React.ComponentProps<typeof CardContent> & {
  layout?: 'horizontal' | 'vertical'
}) {
  return (
    <CardContent
      className={cn(
        layout === 'horizontal'
          ? 'flex-1 min-w-0 space-y-1 px-0 py-0'
          : 'space-y-2',
        className
      )}
      {...props}
    />
  )
}

function ProductLinkTitle({
  className,
  children,
  ...props
}: React.ComponentProps<'h3'>) {
  return (
    <h3
      data-slot="product-link-title"
      className={cn(
        'text-sm font-medium leading-tight text-gray-900 truncate overflow-hidden whitespace-nowrap text-ellipsis',
        className
      )}
      {...props}
    >
      {children}
    </h3>
  )
}

function ProductLinkPrice({className, ...props}: React.ComponentProps<'div'>) {
  return (
    <div
      data-slot="product-link-price"
      className={cn('flex items-center gap-2', className)}
      {...props}
    />
  )
}

function ProductLinkCurrentPrice({
  className,
  ...props
}: React.ComponentProps<'span'>) {
  return (
    <span
      data-slot="product-link-current-price"
      className={cn('text-sm font-semibold text-gray-900', className)}
      {...props}
    />
  )
}

function ProductLinkOriginalPrice({
  className,
  ...props
}: React.ComponentProps<'span'>) {
  return (
    <span
      data-slot="product-link-original-price"
      className={cn('text-sm text-gray-500 line-through', className)}
      {...props}
    />
  )
}

function ProductLinkDiscountPrice({
  className,
  ...props
}: React.ComponentProps<'span'>) {
  return (
    <span
      data-slot="product-link-discount-price"
      className={cn('text-sm font-semibold text-red-600', className)}
      {...props}
    />
  )
}

function ProductLinkRating({className, ...props}: React.ComponentProps<'div'>) {
  return (
    <div
      data-slot="product-link-rating"
      className={cn(
        'flex items-center gap-1 text-xs text-muted-foreground',
        className
      )}
      {...props}
    />
  )
}

function ProductLinkActions({
  className,
  hideFavoriteAction = false,
  onPress,
  filled = false,
  customAction,
  ...props
}: React.ComponentProps<typeof CardAction> & {
  hideFavoriteAction?: boolean
  onPress?: () => void
  filled?: boolean
  customAction?: React.ReactNode
}) {
  const favoriteAction = hideFavoriteAction ? null : (
    <FavoriteButton filled={filled} onClick={onPress} />
  )

  return (
    <CardAction
      className={cn('flex-shrink-0 self-center px-0 py-0', className)}
      {...props}
    >
      <Touchable
        stopPropagation
        onClick={onPress}
        whileTap={{opacity: 0.7, scale: 0.95}}
        transition={{
          opacity: {type: 'tween', duration: 0.08, ease: 'easeInOut'},
          scale: {type: 'tween', duration: 0.08, ease: 'easeInOut'},
        }}
      >
        {customAction ? <>{customAction}</> : favoriteAction}
      </Touchable>
    </CardAction>
  )
}

export type ProductLinkProps = {
  product: Product
  hideFavoriteAction?: boolean
  onClick?: (product: Product) => void
} & (
  | {
      customAction?: never
      onCustomActionClick?: never
    }
  | {
      customAction: React.ReactNode
      onCustomActionClick: () => void
    }
)

// Composed ProductLink component
function ProductLink({
  product,
  hideFavoriteAction = false,
  onClick,
  customAction,
  onCustomActionClick,
}: ProductLinkProps) {
  const {navigateToProduct} = useShopNavigation()
  const {saveProduct, unsaveProduct} = useSavedProductsActions()

  const {
    id,
    title,
    featuredImage,
    reviewAnalytics,
    price,
    compareAtPrice,
    isFavorited,
    selectedVariant,
    defaultVariantId,
    shop,
  } = product

  // Local state for optimistic UI updates
  const [isFavoritedLocal, setIsFavoritedLocal] = React.useState(isFavorited)

  const averageRating = reviewAnalytics?.averageRating
  const reviewCount = reviewAnalytics?.reviewCount
  const amount = price?.amount
    ? formatMoney(price?.amount, price?.currencyCode)
    : undefined
  const imageUrl = featuredImage?.url
  const imageAltText = featuredImage?.altText || title
  const compareAtPriceAmount = compareAtPrice?.amount
    ? formatMoney(compareAtPrice?.amount, compareAtPrice?.currencyCode)
    : undefined
  const hasDiscount = compareAtPriceAmount && compareAtPriceAmount !== amount

  const handlePress = React.useCallback(() => {
    navigateToProduct({
      productId: id,
    })
    onClick?.(product)
  }, [navigateToProduct, id, onClick, product])

  const handleActionPress = React.useCallback(async () => {
    if (customAction || onCustomActionClick) {
      onCustomActionClick?.()
      return
    }

    const previousState = isFavoritedLocal

    // Optimistic update
    setIsFavoritedLocal(!previousState)

    try {
      if (previousState) {
        await unsaveProduct({
          productId: id,
          shopId: shop.id,
          productVariantId: selectedVariant?.id || defaultVariantId,
        })
      } else {
        await saveProduct({
          productId: id,
          shopId: shop.id,
          productVariantId: selectedVariant?.id || defaultVariantId,
        })
      }
    } catch (error) {
      // Revert optimistic update on error
      setIsFavoritedLocal(previousState)
    }
  }, [
    customAction,
    onCustomActionClick,
    isFavoritedLocal,
    unsaveProduct,
    id,
    shop.id,
    selectedVariant?.id,
    defaultVariantId,
    saveProduct,
  ])

  return (
    <ProductLinkRoot
      layout="horizontal"
      discount={hasDiscount ? 'small' : 'none'}
      onPress={handlePress}
    >
      <ProductLinkImage layout="horizontal">
        {imageUrl ? (
          <img
            src={imageUrl}
            alt={imageAltText}
            className="h-full w-full object-cover"
          />
        ) : (
          <div className="h-full w-full bg-muted flex items-center justify-center text-muted-foreground text-xs">
            No Image
          </div>
        )}
      </ProductLinkImage>

      <ProductLinkInfo layout="horizontal">
        <ProductLinkTitle>{title}</ProductLinkTitle>

        {reviewCount && averageRating ? (
          <ProductLinkRating>
            <div className="flex items-center gap-1">
              {Array.from({length: 5}, (_, i) => (
                <Star
                  key={i}
                  fill={
                    i < Math.floor(averageRating!) ? 'currentColor' : 'none'
                  }
                  className={cn(
                    'h-3 w-3',
                    i < Math.floor(averageRating!)
                      ? 'text-primary'
                      : 'text-gray-300'
                  )}
                />
              ))}
              <span className="text-xs text-gray-600 ml-1">
                ({reviewCount})
              </span>
            </div>
          </ProductLinkRating>
        ) : null}

        <ProductLinkPrice>
          {hasDiscount ? (
            <>
              <ProductLinkDiscountPrice>{amount}</ProductLinkDiscountPrice>
              <ProductLinkOriginalPrice>
                {compareAtPriceAmount}
              </ProductLinkOriginalPrice>
            </>
          ) : (
            <ProductLinkCurrentPrice>{amount}</ProductLinkCurrentPrice>
          )}
        </ProductLinkPrice>
      </ProductLinkInfo>

      <ProductLinkActions
        filled={isFavoritedLocal}
        onPress={handleActionPress}
        customAction={customAction}
        hideFavoriteAction={hideFavoriteAction}
      />
    </ProductLinkRoot>
  )
}

export {ProductLink}
