'use client';

import { useEffect, useRef, useState } from 'react';
import { Loader } from 'lucide-react';
import WorkoutCard from './WorkoutCard';

const PAGE_SIZE = 50;

interface Filters {
  q?: string;
  dateFrom?: string;
  dateTo?: string;
}

export default function WorkoutsList({
  initialWorkouts,
  initialHasMore,
  filters,
}: {
  // Loose typing — WorkoutCard accepts the same shape getWorkouts returns,
  // both client- and server-side. Avoids importing Prisma types into a
  // client component which drags PrismaClient into the client bundle.
  initialWorkouts: any[];
  initialHasMore: boolean;
  filters: Filters;
}) {
  const [items, setItems] = useState(initialWorkouts);
  const [hasMore, setHasMore] = useState(initialHasMore);
  const [loadingMore, setLoadingMore] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const sentinelRef = useRef<HTMLDivElement>(null);

  // Reset when filters or initial data change (URL-driven re-render)
  useEffect(() => {
    setItems(initialWorkouts);
    setHasMore(initialHasMore);
    setError(null);
  }, [initialWorkouts, initialHasMore]);

  useEffect(() => {
    if (!hasMore || !sentinelRef.current) return;
    const sentinel = sentinelRef.current;
    const observer = new IntersectionObserver(
      (entries) => {
        if (!entries[0]?.isIntersecting) return;
        if (loadingMore || !hasMore) return;
        setLoadingMore(true);
        const params = new URLSearchParams({
          offset: String(items.length),
          limit: String(PAGE_SIZE),
        });
        if (filters.q) params.set('q', filters.q);
        if (filters.dateFrom) params.set('dateFrom', filters.dateFrom);
        if (filters.dateTo) params.set('dateTo', filters.dateTo);
        fetch(`/api/workouts?${params}`)
          .then(async (res) => {
            if (!res.ok) {
              setError(`Failed to load more (${res.status})`);
              setHasMore(false);
              return;
            }
            const body = await res.json();
            setItems((prev) => [...prev, ...(body.data ?? [])]);
            setHasMore(!!body.meta?.hasMore);
          })
          .catch(() => {
            setError('Failed to load more');
            setHasMore(false);
          })
          .finally(() => setLoadingMore(false));
      },
      { rootMargin: '300px' },
    );
    observer.observe(sentinel);
    return () => observer.disconnect();
  }, [hasMore, loadingMore, items.length, filters.q, filters.dateFrom, filters.dateTo]);

  return (
    <>
      <div className="space-y-3 pb-20 sm:pb-6">
        {items.map((workout) => (
          <WorkoutCard key={workout.id} workout={workout} />
        ))}
      </div>
      {hasMore && (
        <div ref={sentinelRef} className="flex justify-center py-6">
          {loadingMore ? (
            <Loader className="w-5 h-5 animate-spin text-zinc-500" />
          ) : (
            <span className="text-xs text-zinc-600 uppercase tracking-wider">
              Loading more...
            </span>
          )}
        </div>
      )}
      {!hasMore && items.length >= PAGE_SIZE && (
        <p className="text-center text-xs text-zinc-600 uppercase tracking-wider py-6">
          End of history · {items.length} workouts
        </p>
      )}
      {error && (
        <div className="rounded bg-red-900/50 px-3 py-2 mt-3 border border-red-800 text-xs text-red-400">
          {error}
        </div>
      )}
    </>
  );
}
