import { onMounted, ref, onUnmounted, shallowRef } from "vue";
import { ActionType, PageContentProps, BeforeRequestType } from "../types";
import { mapActionToApi } from "../utils/create-operation";
import { responseHandle } from "/@/utils/responseHandle";
import { mergeParams } from "../utils/merge-params";
import { usePagination } from "./use-pagination";
import { handleTree } from "@pureadmin/utils";
import { useNav } from "/@/layout/hooks/nav";
import { useParams } from "./use-params";

export function useRequest(props: PageContentProps) {
  const dataList = ref([]);
  const isInit = shallowRef(props.contentConfig.noRequiredInit || false);
  let timer: NodeJS.Timeout = null;

  const { logout } = useNav();
  const loading = ref(false);

  const { getBasicParams, changeBasicParams } = useParams();
  const paginationConfig = usePagination(props, {
    onSearch
  });

  const { changePagination, getPagination } = paginationConfig;

  async function onSearch() {
    if (timer) window.clearTimeout(timer);
    const { contentConfig } = props;

    if (isInit.value) {
      isInit.value = false;
      return;
    }

    const {
      apis,
      root,
      isTree,
      responseCode,
      listNoRelation,
      beforeRequestList
    } = contentConfig;

    const params = mergeParams({
      pagination: getPagination ? getPagination() : {},
      basicParams: getBasicParams()
    });

    const type: BeforeRequestType = beforeRequestList
      ? beforeRequestList(params)
      : BeforeRequestType.NEXT;

    switch (type) {
      case BeforeRequestType.BREAK:
        return;
      case BeforeRequestType.EMPTY:
        dataList.value = [];
        break;
      default:
        loading.value = true;
        // eslint-disable-next-line no-case-declarations
        const { code, data, message } = await apis.httpList({
          ...params,
          ...(listNoRelation ? { noRela: true } : {})
        });

        responseHandle({
          code,
          message,
          logout,
          responseCode,
          handler: async () => {
            const untreated = Array.isArray(data) || root ? data : data.list;

            let list = contentConfig.handleData
              ? contentConfig.handleData(untreated, params)
              : untreated;

            async function handler() {
              dataList.value = isTree ? handleTree(list ?? []) : list;
              if (!contentConfig.notPagination) {
                changePagination("total", data.count);
              }
              props.onGetHandleResult && props.onGetHandleResult(list);
              props.onGetReuslt && props.onGetReuslt(data);
            }

            if (list instanceof Promise) {
              list = await Promise.resolve(list);
            }

            await handler();
          }
        });

        loading.value = false;
        break;
    }
  }

  async function onSearchPro(params = {}) {
    const { contentConfig } = props;
    const { apis, isTree, handleData, responseCode } = contentConfig;

    loading.value = true;
    const { code, data, message } = await apis.httpList({
      ...params
    });

    responseHandle({
      code,
      message,
      logout,
      responseCode,
      handler: async () => {
        const untreated = Array.isArray(data) ? data : data.list;
        let list = handleData ? handleData(untreated) : untreated;

        const handler = () => {
          dataList.value = isTree ? handleTree(list ?? []) : list;
          changePagination("total", data.count);
          props.onGetReuslt && props.onGetReuslt(data);
          props.onGetHandleResult && props.onGetHandleResult(list);
          loading.value = false;
        };

        if (list instanceof Promise) {
          list.then(res => {
            list = res;
            handler();
          });
        } else {
          handler();
        }
      }
    });
  }

  /**
   * 外部使用的请求方法
   */
  function getPageData(parmas: any = {}) {
    changePagination && changePagination("currentPage", 1);
    changeBasicParams && changeBasicParams(parmas);
    onSearch();
  }
  /**
   * 外部action执行传入数据发起请求
   */
  async function onBeforeAction(
    action: ActionType,
    data: any = {},
    responseCallback?: () => void
  ) {
    const { contentConfig } = props;
    const { apis } = contentConfig;
    const key = mapActionToApi[action];

    loading.value = true;
    const { code, message } = await apis[key](data);
    responseCallback && responseCallback();
    responseHandle({
      code,
      message,
      logout,
      handler: () => onSearch()
    });

    loading.value = false;
  }

  function isHasLockValue() {
    const parmas = getBasicParams();
    return (props.lockKey as Array<String>)
      .filter(key => key)
      .every(key => parmas && parmas[key as unknown as any]);
  }

  function initalData(params: Record<string, string> = null) {
    if (params) changeBasicParams(params);

    if (!props.lockKey || props.lockKey.length === 0) {
      return onSearch();
    }

    timer = setTimeout(() => {
      const hasLockValue = isHasLockValue();
      if (hasLockValue) {
        onSearch();
      } else {
        initalData();
      }
    }, 100);
  }

  //初始化数据
  onMounted(() => initalData());
  onUnmounted(() => timer && window.clearTimeout(timer));

  return {
    loading,
    onSearch,
    dataList,
    initalData,
    onSearchPro,
    getPageData,
    getPagination,
    onBeforeAction,
    getBasicParams,
    paginationConfig
  };
}
