import * as React from 'react';
import classNames from 'classnames';

interface PullToRefreshProps {
  onRefresh: () => Promise<void>;
  children: React.ReactNode;
  className?: string;
}

export function PullToRefresh({ onRefresh, children, className }: PullToRefreshProps) {
  const containerRef = React.useRef<HTMLDivElement>(null);
  const [startY, setStartY] = React.useState(0);
  const [pullDistance, setPullDistance] = React.useState(0);
  const [isRefreshing, setIsRefreshing] = React.useState(false);
  const [isPulling, setIsPulling] = React.useState(false);

  const threshold = 80;
  const maxPull = 120;
  const resistance = 2.5;

  const handleTouchStart = (e: React.TouchEvent) => {
    // Only start if scrolled to top
    if (containerRef.current && containerRef.current.scrollTop === 0) {
      setStartY(e.touches[0].clientY);
      setIsPulling(true);
    }
  };

  const handleTouchMove = (e: React.TouchEvent) => {
    if (!isPulling || isRefreshing) return;

    const currentY = e.touches[0].clientY;
    const diff = (currentY - startY) / resistance;

    if (diff > 0) {
      const distance = Math.min(maxPull, diff);
      setPullDistance(distance);

      // Prevent default scroll when pulling
      if (containerRef.current && containerRef.current.scrollTop === 0) {
        e.preventDefault();
      }
    }
  };

  const handleTouchEnd = async () => {
    if (!isPulling || isRefreshing) return;

    setIsPulling(false);

    if (pullDistance >= threshold) {
      setIsRefreshing(true);
      setPullDistance(60); // Keep indicator visible during refresh

      try {
        await onRefresh();
      } finally {
        setIsRefreshing(false);
        setPullDistance(0);
      }
    } else {
      setPullDistance(0);
    }
  };

  const progress = Math.min(1, pullDistance / threshold);
  const rotation = pullDistance * 3;

  return (
    <div
      ref={containerRef}
      className={classNames('relative overflow-auto', className)}
      onTouchStart={handleTouchStart}
      onTouchMove={handleTouchMove}
      onTouchEnd={handleTouchEnd}
    >
      {/* Pull indicator */}
      <div
        className="absolute left-1/2 transform -translate-x-1/2 z-10 transition-opacity"
        style={{
          top: pullDistance - 40,
          opacity: pullDistance > 10 ? 1 : 0,
        }}
      >
        <div
          className={classNames(
            'w-10 h-10 rounded-full bg-white shadow-lg flex items-center justify-center',
            { 'animate-spin': isRefreshing }
          )}
        >
          <svg
            xmlns="http://www.w3.org/2000/svg"
            className={classNames('h-6 w-6 text-green-600 transition-transform', {
              'animate-spin': isRefreshing,
            })}
            style={{ transform: isRefreshing ? undefined : `rotate(${rotation}deg)` }}
            fill="none"
            viewBox="0 0 24 24"
            stroke="currentColor"
          >
            <path
              strokeLinecap="round"
              strokeLinejoin="round"
              strokeWidth={2}
              d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
            />
          </svg>
        </div>
      </div>

      {/* Pull text */}
      {pullDistance > 10 && !isRefreshing && (
        <div
          className="absolute left-1/2 transform -translate-x-1/2 text-sm text-gray-500 transition-opacity z-10"
          style={{
            top: pullDistance + 5,
            opacity: progress,
          }}
        >
          {pullDistance >= threshold ? 'Release to refresh' : 'Pull to refresh'}
        </div>
      )}

      {/* Content */}
      <div
        className="transition-transform"
        style={{
          transform: `translateY(${pullDistance}px)`,
          transitionDuration: isPulling ? '0ms' : '200ms',
        }}
      >
        {children}
      </div>
    </div>
  );
}

export default PullToRefresh;
