import { throwException } from "@/lib/error";
import qs from "qs";

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

function getAuthCredentials(): LeadsquaredAuth {
  const accessKey = process.env.LEADSQUARED_ACCESS_KEY!;
  const secretKey = process.env.LEADSQUARED_SECRET_KEY!;

  if (!accessKey || !secretKey) {
    throw new Error("Missing Leadsquared API credentials");
  }

  return {
    accessKey,
    secretKey,
  };
}

interface LeadsquaredAuth {
  accessKey: string;
  secretKey: string;
}

async function LeadsquaredFetcher<TResponse>(
  path: string,
  params = {},
  options = {},
): // @ts-expect-error TODO: Fix the return type
Promise<TResponse> {
  try {
    const { accessKey, secretKey } = getAuthCredentials();
    const mergedOptions = {
      headers: {
        "Content-Type": "application/json",
      },
      ...options,
    };

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

    const response = await fetch(requestUrl, mergedOptions);

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

export async function LeadsquaredGet<TResponse, TParams>(
  path: string,
  params?: TParams,
): Promise<TResponse> {
  return LeadsquaredFetcher(path, params ?? {}, {
    method: "GET",
  });
}

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

export async function LeadsquaredPut<TResponse, TParams>(
  path: string,
  params?: TParams,
  body = {},
): Promise<TResponse> {
  return LeadsquaredFetcher(path, params ?? {}, {
    method: "PUT",
    body: JSON.stringify(body),
  });
}

export async function LeadsquaredDelete<TResponse, TParams>(
  path: string,
  params?: TParams,
): Promise<TResponse> {
  return LeadsquaredFetcher(path, params ?? {}, {
    method: "DELETE",
  });
}
