import {createPageContext, createSearchContext, usePage, useTableSearch} from '@hooks';
import {BaseListResult, GetBaseListType, ListParams, OriginalListParams} from '@models';
import {useQuery} from '@tanstack/react-query';
import {shallowEqual} from '@utils';
import {useEffect, useRef, useState} from 'react';

type UseQueryListResult<D extends BaseListResult> = [
  {
    count: number,
    data: GetBaseListType<D>[],
    isFetching: boolean,
  },
  {refetch: () => void},
];

type UseQueryListOptions<
  P extends ListParams,
  R extends BaseListResult,
> = {
  queryFn: (params: P) => R,
  params: OriginalListParams<P>,
  pageContext: ReturnType<typeof createPageContext>,
  searchContext: ReturnType<typeof createSearchContext>,
};

export function useQueryList<
  P extends ListParams,
  R extends BaseListResult,
>(
  {queryFn, params, pageContext, searchContext}: UseQueryListOptions<P, R>,
): UseQueryListResult<R> {
  const [count, setCount] = useState(0);
  const [{page, pageSize}, {onCurrentPageChange}] = usePage(pageContext);
  const prevData = useRef<R[]>([]);
  const prevParams = useRef(params);

  const {data = [], isFetching, refetch} = useQuery<GetBaseListType<R>[]>(
    [queryFn.name, page, pageSize, ...Object.values(params)],
    async function() {
      /**
       * 当参数发生改变说明请求内容发生变化
       * 如果当前页码不为1需要跳转到第1页查询
       */
      if (page !== 1 && !shallowEqual(prevParams.current, params)) {
        prevParams.current = params;
        onCurrentPageChange(1);
        return prevData.current;
      }

      /**
       * 有可能参数发生变化但是页码为1 第一步不会拦截
       * 这里确保参数是最新的参数
       */
      prevParams.current = params;

      const data = await queryFn({
        ...params,
        page: page.toString(),
        limit: pageSize.toString(),
      } as P);

      if (data.msg === '200') {
        const {total, list} = data.data;

        /**
         * 当页面只有一个数据的时候 删除了页码改为前一个 但是数据请求还是当前页码
         * 需要判断当前是否无数据并且页码大于1 满足时跳转到前一个页面
         */
        page > 1 && list.length === 0 && onCurrentPageChange(page - 1);

        setCount(total);

        return (prevData.current = list);
      }

      return [];
    },
    {
      placeholderData: [],
      keepPreviousData: true,
    },
  );

  const [, searchChange] = useTableSearch(searchContext);

  // 保持更新搜索表格的查询状态
  useEffect(function() {
    searchChange(isFetching);
  }, [isFetching, searchChange]);

  return [
    {
      count,
      data,
      isFetching,
    },
    {refetch},
  ];
}
