import {forwardRef, useEffect, useState} from 'react'

import {cn} from '../../lib/utils'

export interface PullToRefreshIndicatorProps {
  pullDistance: number
  threshold: number
  isRefreshing: boolean
  canRefresh: boolean
  className?: string
}

export const RefreshIndicator = forwardRef<
  HTMLDivElement,
  PullToRefreshIndicatorProps
>(({pullDistance, threshold, isRefreshing, canRefresh, className}, ref) => {
  const [showBumpAnimation, setShowBumpAnimation] = useState(false)

  const progress = Math.min(pullDistance / threshold, 1)

  const spinnerProgress = 0.54 + progress * (1 - 0.54)

  const scale = isRefreshing ? 1 : 0.5 + progress * 0.5

  const opacity = isRefreshing ? 1 : Math.min(progress * 1.5, 1)

  const translateY = isRefreshing ? 0 : progress * 3

  useEffect(() => {
    if (isRefreshing && !showBumpAnimation) {
      setShowBumpAnimation(true)
      const timer = setTimeout(() => setShowBumpAnimation(false), 360)
      return () => clearTimeout(timer)
    }
    return undefined
  }, [isRefreshing, showBumpAnimation])

  return (
    <div
      ref={ref}
      className={cn(
        'flex items-center justify-center w-full h-full',
        'transition-all duration-200 ease-out',
        className
      )}
      style={{
        transform: `translateY(${translateY}px)`,
      }}
    >
      <div
        className={cn(
          'flex flex-col items-center space-y-2 rounded-full px-4 py-2 backdrop-blur-sm transition-all duration-200',
          canRefresh || isRefreshing
            ? 'bg-primary/20 border-2 border-primary/40'
            : 'bg-background/90'
        )}
        style={{
          opacity,
          transform: `scale(${scale})`,
        }}
      >
        <div
          className={cn(
            'h-8 w-8 transition-all duration-200',
            showBumpAnimation && 'animate-bump'
          )}
        >
          <svg
            viewBox="0 0 52 58"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
            className={cn(
              'h-full w-full transition-colors duration-200',
              canRefresh || isRefreshing
                ? 'text-primary'
                : 'text-muted-foreground'
            )}
          >
            <path
              className={cn(
                'shop-spinner-path',
                !isRefreshing && 'shop-spinner-progress',
                isRefreshing && 'animate-shop-spin'
              )}
              d="M3 13C5 11.75 10.4968 6.92307 21.5 6.4999C34.5 5.99993 42 13 45 23C48.3 34 42.9211 48.1335 30.5 51C17.5 54 6.6 46 6 37C5.46667 29 10.5 25 14 23"
              stroke="currentColor"
              strokeWidth="8"
              strokeLinecap="square"
              strokeLinejoin="miter"
              style={
                {
                  '--spinner-progress': isRefreshing ? '1' : spinnerProgress,
                } as React.CSSProperties
              }
            />
          </svg>
        </div>
      </div>
    </div>
  )
})

RefreshIndicator.displayName = 'RefreshIndicator'
