import { Sort } from "../types";
import moment from "moment";

const sortMultiple = (sortParams: any[], incomingData: any[]) => {
  const handleParams = (param: Sort, a: any, b: any) => {
    const { field, order } = param;

    //the sort method works with 1 and -1 to say go before or after. This is dynamic
    let positive = order === "asc" ? 1 : -1;
    let negative = positive * -1;

    let aValue = a[field];
    let bValue = b[field];

    let dayMonthYear: any = moment(a[field], "DD/MM/YYYY");
    let monthDayYear: any = moment(a[field], "MM/DD/YYYY");

    let isDate =
      a[field].toString().split("/").length > 2 &&
      (dayMonthYear._d != "Invalid Date" || monthDayYear._d != "Invalid Date");

    if (isDate) {
      aValue = new Date(a[field]);
      bValue = new Date(b[field]);
    }
    if (aValue > bValue) return positive;
    if (aValue < bValue) return negative;
  };

  let prevSort: any[] = [];
  sortParams.reverse().forEach((param) => {
    //* If there is a prev sort
    let arrToSort = prevSort.length ? prevSort : incomingData;

    //* sort the arr by the param settings method
    const handleSorting: any = function (a: any, b: any) {
      return handleParams(param, a, b);
    };
    const sorted = arrToSort.sort(handleSorting);

    //clear to prevent dups
    prevSort = [];
    prevSort.push(...sorted);
  });

  return prevSort;
};

const wait = async (n: number) =>
  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(true);
    }, n);
  });

const handleError = (factory: any, requestId: string, error: any) => {
  // if response.data.errors exists, it will be an object so we stringify it
  const errorData =
    error.response && error.response?.data && error.response?.data?.errors
      ? JSON.stringify(error.response.data.errors)
      : error.response && error.response.data
      ? error.response.data
      : error.response
      ? error.response
      : error;

  const msg = `Status: ${
    error.response ? error.response.status : "Fail"
  } - Status Text: ${
    error.response && error.response.statusText
      ? error.response.statusText
      : "Fail"
  } - Data: ${errorData}`;
  const errorCode = error.response?.status || "Unknown";

  // retrieve attempts remaining without changing it
  const ajaxAttemptsRemaining = factory.getAttempts(requestId);

  console.error(msg);
  console.error(`Retrying with ${ajaxAttemptsRemaining} attempts remaining`);

  factory.setFailed(requestId, true);

  //WHEN THERE ARE NO MORE REQUESTS WE SEND AN OBJECT SAYING THAT IT'S THE FINAL ERROR
  if (!ajaxAttemptsRemaining) {
    factory.remove(requestId);
    return {
      error: true,
      msg: msg,
      code: errorCode,
    };
  }

  if (ajaxAttemptsRemaining) {
    // decrease attempts remaining by 1
    factory.decrementAttempts(requestId);

    return {
      retry: true,
    };
  }
};

const generateRequestId = (length: number) => {
  const characters =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  let randomString = "";

  for (let i = 0; i < length; i++) {
    const randomIndex = Math.floor(Math.random() * characters.length);
    randomString += characters.charAt(randomIndex);
  }

  return randomString;
};

export { sortMultiple, handleError, generateRequestId, wait };
