import { useCallback, useEffect, useRef, useState } from "react";
import Taro from "@tarojs/taro";

interface UseInfiniteListOptions<T> {
  /** Fetcher returns items for one page */
  fetcher: (page: number, pageSize: number) => Promise<{ items: T[]; total?: number }>;
  /** Page size, default 20 */
  pageSize?: number;
  /** Auto-load on mount, default true */
  autoLoad?: boolean;
}

interface UseInfiniteListResult<T> {
  items: T[];
  loading: boolean;
  loadingMore: boolean;
  hasMore: boolean;
  refreshing: boolean;
  error: string | null;
  loadMore: () => Promise<void>;
  refresh: () => Promise<void>;
  /** Prepend items (optimistic adds) */
  prepend: (item: T) => void;
  /** Remove item by index */
  remove: (index: number) => void;
}

export function useInfiniteList<T>(options: UseInfiniteListOptions<T>): UseInfiniteListResult<T> {
  const { fetcher, pageSize = 20, autoLoad = true } = options;

  const [items, setItems] = useState<T[]>([]);
  const [loading, setLoading] = useState(false);
  const [loadingMore, setLoadingMore] = useState(false);
  const [refreshing, setRefreshing] = useState(false);
  const [hasMore, setHasMore] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const pageRef = useRef(0);
  const fetchLock = useRef(false);

  const loadInitial = useCallback(async () => {
    if (fetchLock.current) return;
    fetchLock.current = true;
    setLoading(true);
    setError(null);
    try {
      const result = await fetcher(1, pageSize);
      pageRef.current = 1;
      setItems(result.items);
      setHasMore(result.items.length >= pageSize);
    } catch (e: any) {
      setError(e?.message || "加载失败");
    } finally {
      setLoading(false);
      fetchLock.current = false;
    }
  }, [fetcher, pageSize]);

  const loadMore = useCallback(async () => {
    if (fetchLock.current || !hasMore || loadingMore) return;
    fetchLock.current = true;
    setLoadingMore(true);
    const nextPage = pageRef.current + 1;
    try {
      const result = await fetcher(nextPage, pageSize);
      pageRef.current = nextPage;
      setItems((prev) => [...prev, ...result.items]);
      setHasMore(result.items.length >= pageSize);
    } catch (e: any) {
      Taro.showToast({ title: "加载更多失败", icon: "none" });
    } finally {
      setLoadingMore(false);
      fetchLock.current = false;
    }
  }, [fetcher, pageSize, hasMore, loadingMore]);

  const refresh = useCallback(async () => {
    if (fetchLock.current) return;
    fetchLock.current = true;
    setRefreshing(true);
    setError(null);
    try {
      const result = await fetcher(1, pageSize);
      pageRef.current = 1;
      setItems(result.items);
      setHasMore(result.items.length >= pageSize);
    } catch (e: any) {
      setError(e?.message || "刷新失败");
    } finally {
      setRefreshing(false);
      fetchLock.current = false;
    }
  }, [fetcher, pageSize]);

  const prepend = useCallback((item: T) => {
    setItems((prev) => [item, ...prev]);
  }, []);

  const remove = useCallback((index: number) => {
    setItems((prev) => prev.filter((_, i) => i !== index));
  }, []);

  useEffect(() => {
    if (!autoLoad) return;
    void loadInitial();
  }, [autoLoad, loadInitial]);

  return { items, loading, loadingMore, hasMore, refreshing, error, loadMore, refresh, prepend, remove };
}
