import React, { useState, useCallback, useEffect, useRef } from 'react';
import InfiniteScroll from 'react-infinite-scroll-component';
import { Loader2 } from 'lucide-react';
import type { Page } from '@/types/base';

interface InfiniteScrollListProps<T> {
  /**
   * 数据加载函数
   * @param pageNum - 页码（从 1 开始）
   * @param size - 每页大小
   * @param extraParams - 额外参数
   * @returns 分页数据
   */
  loadData: (pageNum: number, size: number, extraParams?: any) => Promise<Page<T> | undefined>;
  
  /**
   * 渲染单个数据项
   * @param item - 数据项
   * @param index - 索引
   * @param isSelected - 是否选中
   */
  renderItem: (item: T, index: number, isSelected: boolean) => React.ReactNode;
  
  /**
   * 每页大小，默认 20
   */
  pageSize?: number;
  
  /**
   * 额外的查询参数
   */
  extraParams?: any;
  
  /**
   * 容器 ID，用于滚动定位
   */
  scrollableTarget: string;
  
  /**
   * 容器样式类名
   */
  className?: string;
  
  /**
   * 列表样式类名
   */
  listClassName?: string;
  
  /**
   * 空状态显示
   */
  emptyText?: string;
  
  /**
   * 空状态图标
   */
  emptyIcon?: React.ReactNode;
  
  /**
   * 加载完成提示文字
   */
  endMessage?: string;
  
  /**
   * 是否显示初始 loading
   */
  showInitialLoading?: boolean;
  
  /**
   * 重置触发器，当这个值变化时重置列表
   */
  resetTrigger?: any;
  
  /**
   * 数据变化回调
   */
  onDataChange?: (data: T[], total: number) => void;
  
  /**
   * 搜索关键词（外部传入，组件内部会做防抖处理）
   */
  searchValue?: string;
  
  /**
   * 本地过滤函数（对已加载的数据进行过滤）
   * @param item - 数据项
   * @param searchValue - 防抖后的搜索值
   */
  localFilter?: (item: T, searchValue: string) => boolean;
  
  /**
   * 选中的项
   */
  selectedItem?: T;
  
  /**
   * 点击项的回调
   */
  onItemClick?: (item: T) => void;
  
  /**
   * 用于识别项的唯一键（用于判断是否选中）
   */
  itemKey?: keyof T;
}

export function InfiniteScrollList<T>({
  loadData,
  renderItem,
  pageSize = 20,
  extraParams,
  scrollableTarget,
  className = '',
  listClassName = 'p-2 space-y-2',
  emptyText = '暂无数据',
  emptyIcon,
  endMessage = '已加载全部数据',
  showInitialLoading = true,
  resetTrigger,
  onDataChange,
  searchValue = '',
  localFilter,
  selectedItem,
  onItemClick,
  itemKey,
}: InfiniteScrollListProps<T>) {
  const [data, setData] = useState<T[]>([]);
  const [page, setPage] = useState(1); // ✅ 从 1 开始
  const [hasMore, setHasMore] = useState(true);
  const [loading, setLoading] = useState(false);
  const [initialLoading, setInitialLoading] = useState(showInitialLoading);
  
  // ✅ 搜索防抖（300ms）
  const [debouncedSearchValue, setDebouncedSearchValue] = useState(searchValue);
  
  // 使用 ref 跟踪是否正在加载，避免重复请求
  const loadingRef = useRef(false);

  // ✅ 搜索防抖处理
  useEffect(() => {
    const timer = setTimeout(() => {
      setDebouncedSearchValue(searchValue);
    }, 300);
    return () => clearTimeout(timer);
  }, [searchValue]);

  // 加载数据
  const fetchData = useCallback(async (pageNum: number, reset: boolean = false) => {
    if (loadingRef.current) return;
    
    loadingRef.current = true;
    setLoading(true);
    
    try {
      const response = await loadData(pageNum, pageSize, extraParams);
      
      if (response) {
        const newData = response.content || [];
        
        if (reset) {
          setData(newData);
        } else {
          setData(prev => [...prev, ...newData]);
        }
        
        setPage(pageNum);
        setHasMore(!response.last);
        
        // 触发数据变化回调
        if (onDataChange) {
          const totalData = reset ? newData : [...data, ...newData];
          onDataChange(totalData, response.totalElements || 0);
        }
      }
    } catch (error) {
      console.error('Failed to load data:', error);
    } finally {
      setLoading(false);
      setInitialLoading(false);
      loadingRef.current = false;
    }
  }, [loadData, pageSize, extraParams, data, onDataChange]);

  // 加载更多
  const loadMore = useCallback(() => {
    if (!loading && hasMore) {
      fetchData(page + 1, false);
    }
  }, [loading, hasMore, page, fetchData]);

  // 重置并重新加载
  const reset = useCallback(() => {
    setData([]);
    setPage(1); // ✅ 重置为 1
    setHasMore(true);
    setInitialLoading(showInitialLoading);
    fetchData(1, true); // ✅ 从第 1 页开始
  }, [fetchData, showInitialLoading]);

  // 当 resetTrigger 或 debouncedSearchValue 变化时重置
  useEffect(() => {
    reset();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [resetTrigger, debouncedSearchValue]);

  // ✅ 本地过滤数据
  const filteredData = React.useMemo(() => {
    if (!localFilter || !debouncedSearchValue) return data;
    return data.filter(item => localFilter(item, debouncedSearchValue));
  }, [data, localFilter, debouncedSearchValue]);

  // ✅ 判断项是否被选中
  const isSelected = (item: T) => {
    if (!selectedItem || !itemKey) return false;
    return selectedItem[itemKey] === item[itemKey];
  };

  // 初始 loading 状态
  if (initialLoading && data.length === 0) {
    return (
      <div className={`flex items-center justify-center h-full ${className}`}>
        <Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
      </div>
    );
  }

  // 空状态
  if (!loading && filteredData.length === 0) {
    return (
      <div className={`flex flex-col items-center justify-center h-full text-muted-foreground ${className}`}>
        {emptyIcon || <div className="h-12 w-12 mb-2 opacity-20" />}
        <p className="text-sm">{emptyText}</p>
      </div>
    );
  }

  // 列表渲染
  return (
    <InfiniteScroll
      dataLength={filteredData.length}
      next={loadMore}
      hasMore={hasMore}
      loader={
        <div className="flex items-center justify-center py-4 text-sm text-muted-foreground">
          <Loader2 className="h-4 w-4 animate-spin mr-2" />
          加载更多...
        </div>
      }
      endMessage={
        filteredData.length > 0 ? (
          <div className="flex items-center justify-center py-4 text-sm text-muted-foreground">
            {endMessage}
          </div>
        ) : null
      }
      scrollableTarget={scrollableTarget}
      className={className || listClassName}
    >
      {filteredData.map((item, index) => {
        const selected = isSelected(item);
        return (
          <div
            key={itemKey ? String(item[itemKey]) : index}
            onClick={() => onItemClick?.(item)}
            className={onItemClick ? 'cursor-pointer' : ''}
          >
            {renderItem(item, index, selected)}
          </div>
        );
      })}
    </InfiniteScroll>
  );
}

// 导出类型供外部使用
export type { InfiniteScrollListProps };
