import { throwException } from "@/lib/error";
import { HTTPException } from "hono/http-exception";
import type { ContentfulStatusCode } from "hono/utils/http-status";
import qs from "qs";

function getBaseURL(path = ""): string {
  const BASE_API = process.env.KARMA_API!;
  if (!BASE_API) {
    throw new Error("Missing Karma endpoint");
  }
  return `${BASE_API}${path}`;
}

export interface KarmaHeaders {
  ["x-account"]: string;
  ["x-contact"]: string;
}
async function KarmaFetcher<TResponse>(
  path: string,
  headers: KarmaHeaders,
  params = {},
  options = {},
): // @ts-expect-error TODO: Fix the return type
Promise<TResponse> {
  try {
    const API_KEY = process.env.KARMA_API_KEY!;
    if (!API_KEY) {
      throw new Error("Missing Karma API key");
    }
    const mergedOptions = {
      headers: {
        "x-api-key": API_KEY,
        "Content-Type": "application/json",
        ...headers,
      },
      ...options,
    };

    const queryStr = qs.stringify(params);
    const requestUrl = `${getBaseURL(
      `${path}${queryStr ? `?${queryStr}` : ""}`,
    )}`;

    const response = await fetch(requestUrl, mergedOptions);

    if (!response.ok) {
      const data = (await response.json()) as { message: string };
      throw new HTTPException(response.status as ContentfulStatusCode, {
        message: JSON.stringify(data),
      });
    }

    return (await response.json()) as TResponse;
  } catch (error) {
    throwException(error);
  }
}

export async function KarmaGet<TResponse, TParams>(
  path: string,
  headers: KarmaHeaders,
  params?: TParams,
): Promise<TResponse> {
  return KarmaFetcher(path, headers, params ?? {}, {
    method: "GET",
  });
}

export async function KarmaPost<TResponse, TParams>(
  path: string,
  headers: KarmaHeaders,
  params?: TParams,
  body = {},
): Promise<TResponse> {
  return KarmaFetcher(path, headers, params ?? {}, {
    method: "POST",
    body: JSON.stringify(body),
  });
}
