import { useState, useCallback, useRef, useEffect } from 'react';
import { message } from 'antd';

interface PaginatedState<T> {
  data: T[];
  total: number;
  page: number;
  loading: boolean;
}

type FetchResult<T> = { data: T[]; total: number };
type OptionsConfig<F> = { pageSize?: number; defaultFilters: F; autoFetch?: boolean };

/**
 * 通用分页数据 Hook，封装 data / total / page / loading / fetch 逻辑。
 *
 * 支持三种签名：
 * 1. 泛型筛选 (page, pageSize, filters: F) — 带结构化筛选的列表页
 * 2. 三参数 (page, pageSize, search: string) — 带搜索的列表页
 * 3. 两参数 (page, pageSize)           — 纯分页，不含搜索
 */

// 重载签名
export function usePaginatedData<T, F>(
  fetchFn: (page: number, pageSize: number, filters: F) => Promise<FetchResult<T>>,
  options: OptionsConfig<F>,
): PaginatedResult<T, F>;

export function usePaginatedData<T>(
  fetchFn:
    | ((page: number, pageSize: number, search: string) => Promise<FetchResult<T>>)
    | ((page: number, pageSize: number) => Promise<FetchResult<T>>),
  pageSize?: number,
  autoFetch?: boolean,
): PaginatedResult<T, string>;

/* eslint-disable @typescript-eslint/no-explicit-any -- 实现签名必须兼容所有重载 */
export function usePaginatedData<T, F = string>(
  fetchFn: (...args: any[]) => Promise<FetchResult<T>>,
  pageSizeOrOptions?: number | OptionsConfig<F>,
  autoFetch = true,
): PaginatedResult<T, F> {
  /* eslint-enable @typescript-eslint/no-explicit-any */
  const isOptions = typeof pageSizeOrOptions === 'object' && pageSizeOrOptions !== null;
  const options = pageSizeOrOptions as OptionsConfig<F>;
  const pageSize = isOptions ? options.pageSize ?? 20 : (pageSizeOrOptions as number) ?? 20;
  const shouldAutoFetch = isOptions ? options.autoFetch ?? true : autoFetch;
  const defaultFilters = isOptions ? options.defaultFilters : ('' as unknown as F);

  const [state, setState] = useState<PaginatedState<T>>({
    data: [],
    total: 0,
    page: 1,
    loading: false,
  });
  const [searchText, setSearchText] = useState('');
  const [filters, setFilters] = useState<F>(defaultFilters);

  const fetchFnRef = useRef(fetchFn);

  const searchTextRef = useRef(searchText);

  const filtersRef = useRef(filters);

  const stateRef = useRef(state);

  useEffect(() => {
    fetchFnRef.current = fetchFn;
    searchTextRef.current = searchText;
    filtersRef.current = filters;
    stateRef.current = state;
  });

  // 所有 fetch 统一走 useEffect，通过 fetchTrigger 触发
  const [fetchTrigger, setFetchTrigger] = useState(0);
  const pendingPageRef = useRef<number | undefined>(undefined);
  const isFirstRender = useRef(true);

  // refresh 只负责设置目标页并递增 trigger，实际 fetch 在 useEffect 中执行
  const refresh = useCallback((p?: number) => {
    pendingPageRef.current = p;
    setFetchTrigger((t) => t + 1);
  }, []);

  useEffect(() => {
    const targetPage = pendingPageRef.current ?? stateRef.current.page;
    pendingPageRef.current = undefined;

    if (isFirstRender.current) {
      isFirstRender.current = false;
      if (!shouldAutoFetch) return;
    }

    // eslint-disable-next-line react-hooks/set-state-in-effect -- 数据获取 hook：loading → fetch → setState 是标准模式
    setState((s) => ({ ...s, loading: true }));

    let cancelled = false;
    fetchFnRef.current(targetPage, pageSize, filtersRef.current ?? searchTextRef.current)
      .then((result) => {
        if (!cancelled) {
          setState({ data: result.data, total: result.total, page: targetPage, loading: false });
        }
      })
      .catch((err) => {
        if (!cancelled) {
          console.warn('[usePaginatedData] 加载数据失败:', err);
          message.error('加载数据失败');
          setState((s) => ({ ...s, loading: false }));
        }
      });

    return () => { cancelled = true; };
    // fetchTrigger 变化 = 手动 refresh；filters 变化 = 筛选刷新
  }, [shouldAutoFetch, filters, fetchTrigger, pageSize]);

  return { ...state, searchText, setSearchText, filters, setFilters, refresh };
}

interface PaginatedResult<T, F> extends PaginatedState<T> {
  searchText: string;
  setSearchText: (text: string) => void;
  filters: F;
  setFilters: (filters: F | ((prev: F) => F)) => void;
  refresh: (page?: number) => void;
}
