import React, { useCallback, useContext, useMemo } from "react";
import {
  AuthContext,
  tokenExpireError as tokenExpiredError,
} from "Src/authContext";
import {
  GlobalContext,
  RequestItems,
  setGLobalProperty,
  showToast as toast,
  setLoading as dispatchLoading,
  dataSuccess,
  dataFailure,
  getList,
  getManyByIds,
  getSingleModel,
  createRequest,
  updateRequest,
  deleteRequest,
  customRequest,
} from "Src/globalContext";

const useContexts = () => {
  const { state: globalState, dispatch: globalDispatch } =
    useContext(GlobalContext);
  const { state: authState, dispatch: authDispatch } = useContext(AuthContext);

  const showToast = useCallback(
    (message, duration = 5000, status = "success") => {
      console.log("showToast >>", message);
      toast(globalDispatch, message, duration, status);
    },
    [globalDispatch]
  );

  const setLoading = useCallback(
    (state, value) => {
      dispatchLoading(globalDispatch, value, state);
    },
    [globalDispatch]
  );

  const setGlobalState = useCallback(
    (state, value) => {
      setGLobalProperty(globalDispatch, value, state);
    },
    [globalDispatch]
  );

  const tokenExpireError = useCallback(
    (message) => {
      console.log("tokenExpireError >>", message);
      tokenExpiredError(authDispatch, message);
    },
    [authDispatch]
  );

  const getMany = useCallback(
    (table, options = {}, state) => {
      return (async () => {
        return await getList(
          globalDispatch,
          authDispatch,
          table,
          options,
          state
        );
      })();
    },
    [globalDispatch, authDispatch]
  );

  const getManyById = useCallback(
    (table, ids = [], join, allowToast = true) => {
      return (async () => {
        return await getManyByIds(
          globalDispatch,
          authDispatch,
          table,
          ids,
          join,
          allowToast
        );
      })();
    },
    [globalDispatch, authDispatch]
  );

  const getSingle = useCallback(
    (
      table,
      id,
      options = {
        isPublic: false,
        method: "GET",
        join: [],
        state: null,
        allowToast: true,
      }
    ) => {
      return (async () => {
        console.log("options >> ", options, id);
        return await getSingleModel(globalDispatch, authDispatch, table, id, {
          ...options,
        });
      })();
    },
    [globalDispatch, authDispatch]
  );

  const create = useCallback(
    (table, payload, allowToast = true) => {
      return (async () => {
        return await createRequest(
          globalDispatch,
          authDispatch,
          table,
          payload,
          allowToast
        );
      })();
    },
    [globalDispatch, authDispatch]
  );

  const update = useCallback(
    (table, id, payload, allowToast = true) => {
      return (async () => {
        return await updateRequest(
          globalDispatch,
          authDispatch,
          table,
          id,
          payload,
          allowToast
        );
      })();
    },
    [globalDispatch, authDispatch]
  );

  const deleteOne = useCallback(
    (table, id, payload, allowToast = true) => {
      return (async () => {
        return await deleteRequest(
          globalDispatch,
          authDispatch,
          table,
          id,
          payload,
          allowToast
        );
      })();
    },
    [globalDispatch, authDispatch]
  );

  const custom = useCallback(
    (
      options = {
        method: "GET",
        endpoint: "",
        payload: null,
      },
      state,
      allowToast = true,
      signal = null
    ) => {
      return (async () => {
        return await customRequest(
          globalDispatch,
          authDispatch,
          options,
          state,
          allowToast,
          signal
        );
      })();
    },
    [globalDispatch, authDispatch]
  );

  return {
    authState,
    showToast,
    setLoading,
    globalState,
    RequestItems,
    authDispatch,
    globalDispatch,
    tokenExpireError,
    setGlobalState,
    getManyById,
    deleteOne,
    getSingle,
    getMany,
    create,
    update,
    custom,
  };
};

export default useContexts;
