type Method = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";

interface ApiOptions {
  method?: Method;
  body?: unknown;
  headers?: Record<string, string>;
  cache?: RequestCache;
  revalidate?: number;
}

interface ApiResponse<T> {
  data: T | null;
  error: string | null;
  status: number;
}

export async function apiCall<T>(
  endpoint: string,
  options: ApiOptions = {}
): Promise<ApiResponse<T>> {
  const {
    method = "GET",
    body,
    headers = {},
    cache = "no-store",
    revalidate,
  } = options;

  const fetchOptions: RequestInit = {
    method,
    headers: {
      "Content-Type": "application/json",
      ...headers,
    },
    cache,
    ...(revalidate !== undefined && { next: { revalidate } }),
    ...(body !== undefined && { body: JSON.stringify(body) }),
  };

  try {
    const res = await fetch(endpoint, fetchOptions);

    // handle empty responses (e.g. 204 No Content)
    const data = await res.json();

    if (!res.ok) {
      return {
        data: null,
        error: (data as any)?.message ?? `Error ${res.status}`,
        status: res.status,
      };
    }

    return { data, error: null, status: res.status };
  } catch (err: any) {
    return { data: null, error: err.message ?? "Network error", status: 0 };
  }
}