
  import { tokenExpireError } from "Context/Auth";

import MkdSDK from "Utils/MkdSDK";

import {
  REQUEST_FAILED,
  REQUEST_LOADING,
  REQUEST_SUCCESS,
  RequestItems,
  SET_GLOBAL_PROPERTY,
} from "./GlobalConstants";

import { showToast } from "./GlobalContext";
import TreeSDK from "Utils/TreeSDK";

/**
 * @param {any} dispatch - Global Dispatch
 * @param {String | Number | Boolean | Object} data -
 * @param {String} property - any propert name
 */

export const setGLobalProperty = (dispatch, data, property) => {
  // console.log("property >>", property);
  dispatch({
    property,
    type: SET_GLOBAL_PROPERTY,
    payload: data,
  });
};

/**
 * @param {any} dispatch - Global Dispatch
 * @param {boolean} data - true || false
 * @param { String } item - string of the needed action
 */

export const setLoading = (dispatch, data, item, where) => {
  // console.log("setLoading data >>", data, where);
  dispatch({
    item,
    type: REQUEST_LOADING,
    payload: data,
  });
};

/**
 * @param {any} dispatch - Global Dispatch
 * @param {Array | any} data - any[]
 * @param { String } item - string of the needed action
 */

export const dataSuccess = (dispatch, data, item) => {
  dispatch({
    item,
    type: REQUEST_SUCCESS,
    payload: data,
  });
};
/**
 * @param {any} dispatch - Global Dispatch
 * @param {Array | any} data - any[]
 * @param { String } item - string of the needed action
 */

export const dataFailure = (dispatch, data, item) => {
  dispatch({
    item,
    type: REQUEST_FAILED,
    payload: data,
  });
};

/**
 * @param {any} globalDispatch - Global Dispatch
 * @param {any} authDispatch - Auth Dispatch
 * @param {String} table - table model
 * @param {Number | String} id - id
 * @param {String} method - method
 */

export const getSingleModel = async (
  globalDispatch,
  authDispatch,
  table,
  id,
  method = "GET",
  join = null
) => {
  const sdk = new MkdSDK();
  setLoading(globalDispatch, true, RequestItems.viewModel);
  try {
    sdk.setTable(table.trim());
    const result = await sdk.callRestAPI(
      { id: Number(id), ...{ ...(join ? { join: join } : null) } },
      method
    );

    if (!result?.error) {
      dataSuccess(
        globalDispatch,
        { data: result?.model },
        RequestItems.viewModel
      );
    }
    setLoading(globalDispatch, false, RequestItems.viewModel);
    // showToast(globalDispatch, "Project Saved", 4000, "info");
  } catch (error) {
    const message = error?.response?.data?.message
      ? error?.response?.data?.message
      : error?.message;
    setLoading(globalDispatch, false, RequestItems.viewModel);
    dataFailure(globalDispatch, { message, id }, RequestItems.viewModel);
    showToast(globalDispatch, message, 4000, "error");
    tokenExpireError(authDispatch, message);
  }
};

/**
 * @param {any} globalDispatch - Global Dispatch
 * @param {any} authDispatch - Auth Dispatch
 * @param {String} table - table model
 * @param {Array[Number] | Array[String]} ids - list of ids
 * @param { String } join - join table
 */

export const getManyByIds = async (
  globalDispatch,
  authDispatch,
  table,
  ids,
  join = null
) => {
  const tdk = new TreeSDK();
  setLoading(globalDispatch, true, RequestItems.listModel);
  try {
    // const filters = ids.map((id) => computeFilter("id", "in", id));
    const result = await tdk.getList(table, {
      ...{
        ...(join ? { join: join } : null),
        filter: [`id,in,${ids.join(",")}`],
      },
    });

    if (!result?.error) {
      dataSuccess(
        globalDispatch,
        { data: result?.list },
        RequestItems.listModel
      );
    }
    setLoading(globalDispatch, false, RequestItems.listModel);
    // showToast(globalDispatch, "Project Saved", 4000, "info");
  } catch (error) {
    const message = error?.response?.data?.message
      ? error?.response?.data?.message
      : error?.message;
    setLoading(globalDispatch, false, RequestItems.listModel);
    dataFailure(globalDispatch, { message, id }, RequestItems.listModel);
    showToast(globalDispatch, message, 4000, "error");
    tokenExpireError(authDispatch, message);
  }
};

/**
 * @param {any} globalDispatch - Global Dispatch
 * @param {any} authDispatch - Auth Dispatch
 * @param {String} table - table model
 * @param { Object } payload - data to create
 */

export const createRequest = async (
  globalDispatch,
  authDispatch,
  table,
  payload
) => {
  const tdk = new TreeSDK();
  setLoading(globalDispatch, true, RequestItems.createModel);
  try {
    const result = await tdk.create(table, payload);

    if (!result?.error) {
      dataSuccess(
        globalDispatch,
        { message: result?.message },
        RequestItems.createModel
      );
      setLoading(globalDispatch, false, RequestItems.createModel);
      showToast(globalDispatch, result?.message, 4000, "success");
      return { error: false };
    } else {
      setLoading(globalDispatch, false, RequestItems.createModel);
      showToast(globalDispatch, result?.message, 4000, "error");
      return { error: true };
    }
  } catch (error) {
    const message = error?.response?.data?.message
      ? error?.response?.data?.message
      : error?.message;
    setLoading(globalDispatch, false, RequestItems.createModel);
    dataFailure(globalDispatch, { message }, RequestItems.createModel);
    showToast(globalDispatch, message, 4000, "error");
    tokenExpireError(authDispatch, message);
    return { error: true };
  }
};

/**
 * @param {any} globalDispatch - Global Dispatch
 * @param {any} authDispatch - Auth Dispatch
 * @param {String} table - table model
 * @param {String | Number} id - item id
 * @param { Object } payload - data to create
 */

export const updateRequest = async (
  globalDispatch,
  authDispatch,
  table,
  id,
  payload
) => {
  const tdk = new TreeSDK();
  setLoading(globalDispatch, true, RequestItems.updateModel);
  try {
    const result = await tdk.update(table, id, payload);

    if (!result?.error) {
      // dataSuccess(globalDispatch, { message: result?.message }, RequestItems.updateModel);
      setLoading(globalDispatch, false, RequestItems.updateModel);
      showToast(globalDispatch, result?.message, 4000, "success");
      return { error: false };
    } else {
      setLoading(globalDispatch, false, RequestItems.updateModel);
      showToast(globalDispatch, result?.message, 4000, "error");
      return { error: true };
    }
  } catch (error) {
    const message = error?.response?.data?.message
      ? error?.response?.data?.message
      : error?.message;
    setLoading(globalDispatch, false, RequestItems.updateModel);
    // dataFailure(globalDispatch, { message }, RequestItems.updateModel);
    showToast(globalDispatch, message, 4000, "error");
    tokenExpireError(authDispatch, message);
    return { error: true };
  }
};

/**
 * @param {any} globalDispatch - Global Dispatch
 * @param {any} authDispatch - Auth Dispatch
 * @param {String} table - table model
 * @param { Object } options - options are filter, join, size, direction and order query
 * @param { Array } [options.filter=null] filter: []
 * @param { String } [options.join=null] join: "table1,table2,table3" - joins another table
 * @param { Number } [options.size=10] size number of items per page
 * @param { String } [options.order=id] order by any field | default is the id field
 * @param { String } [options.direction=desc] direction, desc or asc | desc is the default
 */

export const getList = async (
  globalDispatch,
  authDispatch,
  table,
  options = {}
) => {
  const tdk = new TreeSDK();
  setLoading(globalDispatch, true, table);
  try {
    const result = await tdk.getList(table, options);

    if (!result?.error) {
      // dataSuccess(globalDispatch, { message: result?.message }, table);
      setLoading(globalDispatch, false, table);
      // showToast(globalDispatch, result?.message, 4000, "success");
      return { error: false, data: result?.list };
    } else {
      setLoading(globalDispatch, false, table);
      // showToast(globalDispatch, result?.message, 4000, "error");
      return { error: true };
    }
  } catch (error) {
    const message = error?.response?.data?.message
      ? error?.response?.data?.message
      : error?.message;
    setLoading(globalDispatch, false, table);
    // dataFailure(globalDispatch, { message }, table);
    // showToast(globalDispatch, message, 4000, "error");
    tokenExpireError(authDispatch, message);
    return { error: true };
  }
};

/**
 * @param {any} globalDispatch - Global Dispatch
 * @param {any} authDispatch - Auth Dispatch
 * @param {String} endpoint - the api endpoint
 * @param { Object } payload - payload data
 * @param { String } state - a field in the global content to access the loading state
 */

export const customCreateRequest = async (
  globalDispatch,
  authDispatch,
  endpoint,
  payload,
  state
) => {
  const sdk = new MkdSDK();
  setLoading(globalDispatch, true, state);
  try {
    const result = await sdk.customCreateRequest(endpoint, payload);

    if (!result?.error) {
      // dataSuccess(globalDispatch, { message: result?.message }, state);
      setLoading(globalDispatch, false, state);
      showToast(globalDispatch, result?.message, 4000, "success");
      return { error: false };
    } else {
      setLoading(globalDispatch, false, state);
      showToast(globalDispatch, result?.message, 4000, "error");
      return { error: true, validation: result?.validation };
    }
  } catch (error) {
    const message = error?.response?.data?.message
      ? error?.response?.data?.message
      : error?.message;
    setLoading(globalDispatch, false, state);
    // dataFailure(globalDispatch, { message }, state);
    showToast(globalDispatch, message, 4000, "error");
    tokenExpireError(authDispatch, message);
    return { error: true, validation: result?.validation };
  }
};

// BASIC SETUP ABOVE

/**
 * @param {any} globalDispatch - Global Dispatch
 * @param {any} authDispatch - Auth Dispatch
 * @param {Number | String} id - project id
 */

export const getProject = async (globalDispatch, authDispatch, id) => {
  const sdk = new MkdSDK();
  setLoading(globalDispatch, true, RequestItems.Project);
  try {
    const result = await sdk.getProject(id);

    if (!result?.error) {
      dataSuccess(globalDispatch, result?.model, RequestItems.Project);
    }
    setLoading(globalDispatch, false, RequestItems.Project);
    // showToast(globalDispatch, "Project Saved", 4000, "info");
  } catch (error) {
    const message = error?.response?.data?.message
      ? error?.response?.data?.message
      : error?.message;
    setLoading(globalDispatch, false, RequestItems.Project);
    dataFailure(globalDispatch, { message, id }, RequestItems.Project);
    showToast(globalDispatch, message, 4000, "error");
    tokenExpireError(authDispatch, message);
  }
};

function computeFilter(field, operator, value) {
  return `${field},${operator},${value}`;
}
