import { useEffect, useRef } from 'react';
import type { ReactNode } from 'react';
import { cn } from '@/lib/utils';

type TimelineProps<T extends { id: number | string }> = {
    items: T[];
    renderItem: (item: T) => ReactNode;
    hasMore?: boolean;
    isLoadingMore?: boolean;
    onLoadMore?: () => void;
    emptyState?: ReactNode;
    maxHeight?: string;
    className?: string;
};

export function Timeline<T extends { id: number | string }>({
    items,
    renderItem,
    hasMore = false,
    isLoadingMore = false,
    onLoadMore,
    emptyState,
    maxHeight = '480px',
    className,
}: TimelineProps<T>) {
    const sentinelRef = useRef<HTMLDivElement>(null);

    useEffect(() => {
        const sentinel = sentinelRef.current;
        if (!sentinel || !onLoadMore) return;

        const observer = new IntersectionObserver(
            (entries) => {
                if (entries[0].isIntersecting && hasMore && !isLoadingMore) {
                    onLoadMore();
                }
            },
            { threshold: 0.1 },
        );

        observer.observe(sentinel);
        return () => observer.disconnect();
    }, [hasMore, isLoadingMore, onLoadMore]);

    if (items.length === 0 && !isLoadingMore) {
        return <>{emptyState}</>;
    }

    return (
        <div
            className={cn('overflow-y-auto pr-1', className)}
            style={{ maxHeight }}
        >
            <div className="space-y-3">
                {items.map((item) => (
                    <div key={item.id}>{renderItem(item)}</div>
                ))}
            </div>

            {/* sentinel for IntersectionObserver */}
            <div ref={sentinelRef} className="h-1" />

            {isLoadingMore && (
                <div className="flex items-center justify-center py-4">
                    <div className="h-4 w-4 animate-spin rounded-full border-2 border-muted-foreground border-t-transparent" />
                </div>
            )}
        </div>
    );
}
