import axios from "axios";

export const Ajax = {
  async request(method = "", action = "", data = {}) {
    let url = archm_admin.ajax_url + "?action=" + action + "&nonce=" + archm_admin.nonce;

    let fetch_options = {
      method: method == "POST" ? "POST" : "GET",
      headers: {
        "Content-Type": "application/json",
      }
    };

    if (!data) data = {};
 
    if (method == "GET") {
      url += "&" + new URLSearchParams(data).toString();
    } else {
      fetch_options.body = JSON.stringify(data);
    }
    console.log(fetch_options.body)
    const res = await fetch(url, fetch_options);

    try {
      return await res.json();
    } catch (e) {
      try {
        return await res.text();
      } catch (e) {
        return res;
      }
    }
  },

  async post(action = "", data = {}) {
    return await Ajax.request("POST", action, data);
  },

  async get(action = "", data = {}) {
    return await Ajax.request("GET", action, data);
  },
};

export function serialize(mixedValue) {
  let val, key, okey;
  let ktype = "";
  let vals = "";
  let count = 0;
  const _utf8Size = function (str) {
    return ~-encodeURI(str).split(/%..|./).length;
  };
  const _getType = function (inp) {
    let match;
    let key;
    let cons;
    let types;
    let type = typeof inp;
    if (type === "object" && !inp) {
      return "null";
    }
    if (type === "object") {
      if (!inp.constructor) {
        return "object";
      }
      cons = inp.constructor.toString();
      match = cons.match(/(\w+)\(/);
      if (match) {
        cons = match[1].toLowerCase();
      }
      types = ["boolean", "number", "string", "array"];
      for (key in types) {
        if (cons === types[key]) {
          type = types[key];
          break;
        }
      }
    }
    return type;
  };
  const type = _getType(mixedValue);
  switch (type) {
    case "function":
      val = "";
      break;
    case "boolean":
      val = "b:" + (mixedValue ? "1" : "0");
      break;
    case "number":
      val =
        (Math.round(mixedValue) === mixedValue ? "i" : "d") + ":" + mixedValue;
      break;
    case "string":
      val = "s:" + _utf8Size(mixedValue) + ':"' + mixedValue + '"';
      break;
    case "array":
    case "object":
      val = "a";
      /*
      if (type === 'object') {
        var objname = mixedValue.constructor.toString().match(/(\w+)\(\)/);
        if (objname === undefined) {
          return;
        }
        objname[1] = serialize(objname[1]);
        val = 'O' + objname[1].substring(1, objname[1].length - 1);
      }
      */
      for (key in mixedValue) {
        if (mixedValue.hasOwnProperty(key)) {
          ktype = _getType(mixedValue[key]);
          if (ktype === "function") {
            continue;
          }
          okey = key.match(/^[0-9]+$/) ? parseInt(key, 10) : key;
          vals += serialize(okey) + serialize(mixedValue[key]);
          count++;
        }
      }
      val += ":" + count + ":{" + vals + "}";
      break;
    case "undefined":
    default:
      // Fall-through
      // if the JS object has a property which contains a null value,
      // the string cannot be unserialized by PHP
      val = "N";
      break;
  }
  if (type !== "object" && type !== "array") {
    val += ";";
  }
  return val;
}

export const makeApiRequest = async (endpoint, method = 'GET', data = null) => {
  try {
    const nonce = typeof appObj !== 'undefined' ? appObj.apiNonce : (window?.archm_admin?.rest_nonce || '');
    let base = typeof appObj !== 'undefined' ? appObj.baseEndpoint : (window?.archm_admin?.rest_url || '');
    
    // If using fallback from archm_admin.rest_url, we need to append the namespace
    if (typeof appObj === 'undefined' && base) {
      // Ensure base ends with a slash
      base = base.endsWith('/') ? base : `${base}/`;
      base = `${base}archm/v1/`;
    }

    const requestOptions = {
      method: method,
      headers: {
        'Content-Type': 'application/json',
        'X-WP-Nonce': nonce
      },
      credentials: 'same-origin'
    }

    if (data && (method === 'POST' || method === 'PUT')) {
      requestOptions.body = JSON.stringify(data)
    }

    const url = `${base}${endpoint}`
    console.log(`API Request: ${url}`)
    
    const response = await fetch(url, requestOptions)

    console.log(response)

    if (!response.ok) {
      let errorinfo = await response.json()

      if('disabled_pdo_sqlite' === errorinfo.code){
        return {
          success : false,
          message : errorinfo.message
        }
      }

      // Extract error message from WordPress REST API error response
      // WordPress REST API returns WP_Error in format: { code: 'error_code', message: 'error message', data: { status: 400 } }
      const errorMessage = errorinfo.message || 'There are no orders to archive according to your selected option. Update the old order range to archive older orders.'
      
      return {
        success : false,
        message : errorMessage,
        code : errorinfo.code || 'archive_failed',
        status : errorinfo.data?.status || response.status
      }
    }

    return await response.json()
  } catch (error) {
    return {
      success : false,
      message : 'API Request failed: '+ error
    }
  }
}
