import { type ReactNode } from "react";
import { Loader2 } from "lucide-react";
import { usePullToRefresh } from "../hooks/usePullToRefresh";

const THRESHOLD = 64;

interface PullToRefreshProps {
  children: ReactNode;
  onRefresh: () => Promise<void> | void;
  enabled?: boolean;
}

/**
 * Touch gesture wrapper that triggers a refresh after pulling down 64px.
 * Shows a visual indicator with "Pull to refresh" / "Release to refresh" text.
 */
export function PullToRefresh({ children, onRefresh, enabled = true }: PullToRefreshProps) {
  const { containerRef, pullDistance, isRefreshing, setIsRefreshing } = usePullToRefresh({
    onRefresh: () => {
      const result = onRefresh();
      if (result instanceof Promise) {
        result.finally(() => setIsRefreshing(false));
      } else {
        setIsRefreshing(false);
      }
    },
    threshold: THRESHOLD,
    maxPull: 96,
    enabled,
  });

  const isVisible = pullDistance > 0 || isRefreshing;
  const indicatorOpacity = isRefreshing ? 1 : pullDistance / THRESHOLD;
  const indicatorTranslateY = isRefreshing
    ? 0
    : Math.min(pullDistance - THRESHOLD / 2, 0);

  return (
    <div ref={containerRef} className="relative h-full overflow-y-auto">
      {/* Pull indicator */}
      {isVisible && (
        <div
          className="absolute left-0 right-0 top-0 z-10 flex flex-col items-center justify-end pb-2"
          style={{
            height: isRefreshing ? 48 : Math.max(pullDistance, 0),
            opacity: indicatorOpacity,
            transform: isRefreshing ? undefined : `translateY(${indicatorTranslateY}px)`,
          }}
          aria-live="polite"
          aria-label={
            isRefreshing
              ? "Refreshing"
              : pullDistance >= THRESHOLD
                ? "Release to refresh"
                : "Pull to refresh"
          }
        >
          <Loader2 className="h-6 w-6 animate-spin text-primary" />
          {!isRefreshing && (
            <span className="mt-1 text-xs text-muted-foreground">
              {pullDistance >= THRESHOLD ? "Release to refresh" : "Pull to refresh"}
            </span>
          )}
        </div>
      )}

      {/* Content — pushed down by pull distance when pulling */}
      <div
        style={{
          transform:
            pullDistance > 0
              ? `translateY(${Math.min(pullDistance, 96)}px)`
              : undefined,
          transition: pullDistance === 0 ? "transform 200ms ease-out" : undefined,
        }}
      >
        {children}
      </div>
    </div>
  );
}
