import {PurchaseScreenDataList} from '@models';
import {useTimeout} from 'ahooks';
import {debounce} from 'lodash-es';
import {useEffect, useMemo, useRef, useState} from 'react';
import {FixedSizeList, ListOnScrollProps} from 'react-window';

function nextTick(fn: () => void) {
  Promise.resolve().then(fn);
}

type ListData = {
  idx: number;
  company: string;
  materialCode: string;
  materialName: string;
  order: string;
  date: string;
  num: number;
};

export function useInfiniteScroll(data: PurchaseScreenDataList[]) {
  const scrollRef = useRef<FixedSizeList>(null);
  const prevSize = useRef(0);
  const timer = useRef<NodeJS.Timer>();
  const [scroll, setScroll] = useState(false);
  const nowIdx = useRef(0);

  const listData = useMemo<ListData[]>(
    function () {
      const temp = data.map(function (
        {
          wllbCode,
          materialName,
          supplierName,
          orderCode,
          arrivalNum,
          arrivalTime,
        },
        idx,
      ) {
        return {
          idx: idx + 1,
          company: supplierName,
          materialCode: wllbCode,
          materialName,
          order: orderCode,
          date: arrivalTime,
          num: Number(arrivalNum),
        };
      });

      return scroll ? [...temp, ...temp] : temp;
    },
    [data, scroll],
  );

  useEffect(
    function () {
      if (timer.current) {
        clearInterval(timer.current);
      }

      if (!scroll) return;

      timer.current = setInterval(function () {
        nowIdx.current++;

        scrollRef.current?.scrollToItem(nowIdx.current, 'start');
      }, 3000);

      return () => clearInterval(timer.current);
    },
    [scroll],
  );

  const [smooth, setSmooth] = useState(true);
  const [delay, setDelay] = useState(false);
  useTimeout(
    function () {
      setSmooth(true);
      setDelay(false);
    },
    delay ? 500 : void 0,
  );

  function scrollToTop() {
    nowIdx.current = 0;

    nextTick(function () {
      setSmooth(false);
      setDelay(true);
    });

    scrollRef.current?.scrollTo(0);
  }

  const onScroll = debounce(
    function (e: ListOnScrollProps) {
      const {length} = data;
      e.scrollOffset >= length * 54 && scrollToTop();
    },
    50,
    {leading: false, trailing: true},
  );

  function jungleNeedScroll(height?: number) {
    const {length} = data;

    // 每次需要切换是否滚动时(e.g 数据切换) 切换到最顶部
    scrollToTop();

    // 如果超出显示区域确认需要进行滚动
    nextTick(function () {
      setScroll(length * 54 > (height ?? prevSize.current));
    });
  }

  function onElementSizeChange(height: number) {
    if (prevSize.current === height) return;
    prevSize.current = height;

    jungleNeedScroll(height);
  }

  useEffect(jungleNeedScroll, [data]);

  return [
    {scrollRef, listData, smooth},
    {onElementSizeChange, onScroll},
  ] as const;
}
