import { Alpine } from "./alpine";
import { showToast } from "./toast";

function getAuthHeader(): string {
  const token = localStorage.getItem("token");
  return token ? `Bearer ${token}` : "";
}

async function apiGet(url: string): Promise<Response> {
  return fetch(`/api${url}`, {
    headers: {
      Authorization: getAuthHeader(),
      "Content-Type": "application/json",
    },
  });
}

async function apiPost(url: string, data?: unknown): Promise<Response> {
  return fetch(`/api${url}`, {
    method: "POST",
    headers: {
      Authorization: getAuthHeader(),
      "Content-Type": "application/json",
    },
    body: data ? JSON.stringify(data) : undefined,
  });
}

async function apiPut(url: string, data?: unknown): Promise<Response> {
  return fetch(`/api${url}`, {
    method: "PUT",
    headers: {
      Authorization: getAuthHeader(),
      "Content-Type": "application/json",
    },
    body: data ? JSON.stringify(data) : undefined,
  });
}

async function apiDelete<T extends object>(
  url: string,
  data?: T,
): Promise<Response> {
  return fetch(`/api${url}`, {
    method: "DELETE",
    headers: {
      Authorization: getAuthHeader(),
      "Content-Type": "application/json",
    },
    body: data ? JSON.stringify(data) : undefined,
  });
}

async function apiPatch(url: string, data?: unknown): Promise<Response> {
  return fetch(`/api${url}`, {
    method: "PATCH",
    headers: {
      Authorization: getAuthHeader(),
      "Content-Type": "application/json",
    },
    body: data ? JSON.stringify(data) : undefined,
  });
}

async function handleResponse<T>(response: Response): Promise<T> {
  if (!response.ok) {
    const errorData = await response
      .json()
      .catch(() => ({ error: "Unknown error" }));
    throw new Error(errorData.error || `HTTP ${response.status}`);
  }
  return response.json();
}

async function handleVoidResponse(response: Response): Promise<void> {
  if (!response.ok) {
    const errorData = await response
      .json()
      .catch(() => ({ error: "Unknown error" }));
    throw new Error(errorData.error || `HTTP ${response.status}`);
  }
}

function handleError(error: unknown, context: string): void {
  console.error(`${context}:`, error);
  const message =
    error instanceof Error ? error.message : "An unexpected error occurred";
  showToast(message, "error");
}

export {
  apiGet,
  apiPost,
  apiPut,
  apiDelete,
  apiPatch,
  handleResponse,
  handleVoidResponse,
  handleError,
};

Alpine.data("api", () => ({
  get: apiGet,
  post: apiPost,
  put: apiPut,
  delete: apiDelete,
  patch: apiPatch,
  handleResponse: handleResponse,
  handleVoidResponse: handleVoidResponse,
  handleError: handleError,
}));
