import React, { ReactNode, useMemo } from 'react';
import { useInfiniteScroll } from '@/hooks/useInfiniteScroll';
import { cn } from '@/lib/utils';

interface InfiniteScrollListProps<T> {
  /**
   * 数据项数组
   */
  items: T[];
  /**
   * 渲染每个数据项的函数
   */
  renderItem: (item: T, index: number) => ReactNode;
  /**
   * 获取每个数据项的唯一key
   */
  getItemKey: (item: T, index: number) => string | number;
  /**
   * 是否有更多数据可以加载
   */
  hasNextPage: boolean;
  /**
   * 是否正在加载
   */
  isLoading: boolean;
  /**
   * 加载下一页的函数
   */
  fetchNextPage: () => void;
  /**
   * 列表容器的className
   */
  className?: string;
  /**
   * 网格列数（支持响应式）
   */
  columns?:
    | {
        xs?: number;
        sm?: number;
        md?: number;
        lg?: number;
        xl?: number;
      }
    | number;
  /**
   * 网格间距
   */
  gap?: number;
  /**
   * 加载状态的骨架屏组件
   */
  LoadingSkeleton?: React.ComponentType;
  /**
   * 加载更多时显示的组件
   */
  LoadingMore?: React.ComponentType;
  /**
   * 空状态组件
   */
  EmptyComponent?: React.ComponentType;
  /**
   * 错误状态组件
   */
  ErrorComponent?: React.ComponentType<{ onRetry: () => void }>;
  /**
   * 是否有错误
   */
  hasError?: boolean;
  /**
   * 重试函数
   */
  onRetry?: () => void;
  /**
   * 触发加载的阈值(px)
   */
  threshold?: number;
  /**
   * 是否启用无限滚动
   */
  enabled?: boolean;
}

/**
 * 通用的无限滚动列表组件
 * 支持网格布局、骨架屏、错误状态等功能
 */
export function InfiniteScrollList<T>({
  items,
  renderItem,
  getItemKey,
  hasNextPage,
  isLoading,
  fetchNextPage,
  className,
  columns = 4,
  gap = 4,
  LoadingSkeleton,
  LoadingMore,
  EmptyComponent,
  ErrorComponent,
  hasError = false,
  onRetry,
  threshold = 200,
  enabled = true,
}: InfiniteScrollListProps<T>) {
  const { loadMoreRef, isFetching } = useInfiniteScroll({
    hasNextPage,
    isLoading,
    fetchNextPage,
    threshold,
    enabled,
    isError: hasError,
  });

  // 生成网格列数的CSS类名映射
  const gridColsClass = useMemo(() => {
    if (typeof columns === 'number') {
      const gridClassMap: Record<number, string> = {
        1: 'grid-cols-1',
        2: 'grid-cols-2',
        3: 'grid-cols-3',
        4: 'grid-cols-4',
        5: 'grid-cols-5',
        6: 'grid-cols-6',
      };
      return gridClassMap[columns] || 'grid-cols-4';
    }

    // 使用完整的类名字符串，让 Tailwind 能够正确识别
    const classes: string[] = [];

    // xs 断点
    if (columns.xs === 1) classes.push('xs:grid-cols-1');
    if (columns.xs === 2) classes.push('xs:grid-cols-2');
    if (columns.xs === 3) classes.push('xs:grid-cols-3');
    if (columns.xs === 4) classes.push('xs:grid-cols-4');
    if (columns.xs === 5) classes.push('xs:grid-cols-5');
    if (columns.xs === 6) classes.push('xs:grid-cols-6');

    // sm 断点
    if (columns.sm === 1) classes.push('sm:grid-cols-1');
    if (columns.sm === 2) classes.push('sm:grid-cols-2');
    if (columns.sm === 3) classes.push('sm:grid-cols-3');
    if (columns.sm === 4) classes.push('sm:grid-cols-4');
    if (columns.sm === 5) classes.push('sm:grid-cols-5');
    if (columns.sm === 6) classes.push('sm:grid-cols-6');

    // md 断点
    if (columns.md === 1) classes.push('md:grid-cols-1');
    if (columns.md === 2) classes.push('md:grid-cols-2');
    if (columns.md === 3) classes.push('md:grid-cols-3');
    if (columns.md === 4) classes.push('md:grid-cols-4');
    if (columns.md === 5) classes.push('md:grid-cols-5');
    if (columns.md === 6) classes.push('md:grid-cols-6');

    // lg 断点
    if (columns.lg === 1) classes.push('lg:grid-cols-1');
    if (columns.lg === 2) classes.push('lg:grid-cols-2');
    if (columns.lg === 3) classes.push('lg:grid-cols-3');
    if (columns.lg === 4) classes.push('lg:grid-cols-4');
    if (columns.lg === 5) classes.push('lg:grid-cols-5');
    if (columns.lg === 6) classes.push('lg:grid-cols-6');

    // xl 断点
    if (columns.xl === 1) classes.push('xl:grid-cols-1');
    if (columns.xl === 2) classes.push('xl:grid-cols-2');
    if (columns.xl === 3) classes.push('xl:grid-cols-3');
    if (columns.xl === 4) classes.push('xl:grid-cols-4');
    if (columns.xl === 5) classes.push('xl:grid-cols-5');
    if (columns.xl === 6) classes.push('xl:grid-cols-6');

    return classes.join(' ');
  }, [columns]);

  // 生成间距类名
  const gapClass = useMemo(() => {
    const gapClassMap: Record<number, string> = {
      1: 'gap-1',
      2: 'gap-2',
      3: 'gap-3',
      4: 'gap-4',
      5: 'gap-5',
      6: 'gap-6',
      8: 'gap-8',
    };
    return gapClassMap[gap] || 'gap-4';
  }, [gap]);

  // 错误状态
  if (hasError && ErrorComponent && onRetry) {
    return <ErrorComponent onRetry={onRetry} />;
  }

  // 首次加载状态
  if (isLoading && items.length === 0) {
    if (LoadingSkeleton) {
      return (
        <div className={cn('grid', gridColsClass, gapClass, className)}>
          {Array.from({ length: 8 }).map((_, index) => (
            <LoadingSkeleton key={index} />
          ))}
        </div>
      );
    }

    return (
      <div className={cn('grid', gridColsClass, gapClass, className)}>
        {Array.from({ length: 8 }).map((_, index) => (
          <div
            key={index}
            className="bg-surface-nest-normal aspect-[3/4] animate-pulse rounded-2xl"
          />
        ))}
      </div>
    );
  }

  // 空状态
  if (items.length === 0 && EmptyComponent) {
    return <EmptyComponent />;
  }

  return (
    <div className="w-full">
      {/* 主要内容 */}
      <div className={cn('grid', gridColsClass, gapClass, className)}>
        {items.map((item, index) => (
          <React.Fragment key={getItemKey(item, index)}>{renderItem(item, index)}</React.Fragment>
        ))}
      </div>

      {/* 加载更多触发器 - 只在没有错误时显示 */}
      {hasNextPage && !hasError && (
        <div ref={loadMoreRef} className="mt-8 flex justify-center">
          {LoadingMore ? (
            <LoadingMore />
          ) : (
            <div className="flex items-center gap-2">
              {(isFetching || isLoading) && (
                <div className="h-4 w-4 animate-spin rounded-full border-2 border-white/20 border-t-white" />
              )}
              <span className="text-txt-tertiary-normal txt-label-s">
                {isFetching || isLoading ? 'Loading...' : ''}
              </span>
            </div>
          )}
        </div>
      )}
    </div>
  );
}
