import http from "k6/http";
import { defaultOptions } from "./checks.js";

export { defaultOptions };

export function getEnv() {
  const BASE = __ENV.BASE_URL;
  const MACHINE_ID = __ENV.MACHINE_ID;

  if (!BASE) {
    throw new Error("BASE_URL env var required");
  }

  const routeParams = MACHINE_ID ? { "fly-force-instance-id": MACHINE_ID } : {};
  return { BASE, MACHINE_ID, routeParams };
}

export function createHttpClient(config) {
  const {
    baseUrl,
    routeHeaders = {},
    defaultHeaders = { "Content-Type": "application/json" },
    getHeaders = null,
    getRawHeaders = null,
  } = config;

  if (!baseUrl) {
    throw new Error("baseUrl is required");
  }

  function buildHeaders(builder, setupData, extraHeaders = {}) {
    return {
      ...defaultHeaders,
      ...safeHeaders(builder, setupData),
      ...routeHeaders,
      ...extraHeaders,
    };
  }

  function request(method, path, setupData, body, extraHeaders = {}) {
    const url = `${baseUrl}${path}`;
    const headers = buildHeaders(getHeaders, setupData, extraHeaders);
    return runHttpRequest(method, url, body, headers);
  }

  function raw(method, path, body, extraHeaders = {}) {
    const url = `${baseUrl}${path}`;
    const headers = buildHeaders(getRawHeaders, null, extraHeaders);
    return runHttpRequest(method, url, body, headers);
  }

  function getWithHeaders(path, setupData, extraHeaders = {}) {
    return http.get(`${baseUrl}${path}`, {
      headers: buildHeaders(getHeaders, setupData, extraHeaders),
    });
  }

  return {
    request,
    raw,
    get(path, setupData, extraHeaders = {}) {
      return request("GET", path, setupData, null, extraHeaders);
    },
    put(path, setupData, body, extraHeaders = {}) {
      return request("PUT", path, setupData, body, extraHeaders);
    },
    post(path, setupData, body, extraHeaders = {}) {
      return request("POST", path, setupData, body, extraHeaders);
    },
    patch(path, setupData, body, extraHeaders = {}) {
      return request("PATCH", path, setupData, body, extraHeaders);
    },
    delete(path, setupData, extraHeaders = {}) {
      return request("DELETE", path, setupData, null, extraHeaders);
    },
    rawGet(path, extraHeaders = {}) {
      return raw("GET", path, null, extraHeaders);
    },
    rawPost(path, body, extraHeaders = {}) {
      return raw("POST", path, body, extraHeaders);
    },
    rawPut(path, body, extraHeaders = {}) {
      return raw("PUT", path, body, extraHeaders);
    },
    rawPatch(path, body, extraHeaders = {}) {
      return raw("PATCH", path, body, extraHeaders);
    },
    rawDelete(path, extraHeaders = {}) {
      return raw("DELETE", path, null, extraHeaders);
    },
    getWithHeaders,
  };
}

export function makeReq(baseUrl, routeHeaders = {}, getHeaders = null) {
  return createHttpClient({
    baseUrl,
    routeHeaders,
    getHeaders,
  }).request;
}

export function makeRawReq(baseUrl, routeHeaders = {}, getRawHeaders = null) {
  return createHttpClient({
    baseUrl,
    routeHeaders,
    getRawHeaders,
  }).raw;
}

export function makeGetWithHeaders(baseUrl, routeHeaders = {}, getHeaders = null) {
  return createHttpClient({
    baseUrl,
    routeHeaders,
    getHeaders,
  }).getWithHeaders;
}

function runHttpRequest(method, url, body, headers) {
  const options = { headers };

  if (method === "GET") return http.get(url, options);
  if (method === "PUT") return http.put(url, JSON.stringify(body), options);
  if (method === "POST") return http.post(url, JSON.stringify(body), options);
  if (method === "PATCH") return http.patch(url, JSON.stringify(body), options);
  if (method === "DELETE") return http.del(url, null, options);

  throw new Error(`unsupported method: ${method}`);
}

function safeHeaders(builder, setupData) {
  if (typeof builder !== "function") return {};
  return builder(setupData) || {};
}
