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");
}

// ============================================================
// Reader API Functions
// ============================================================
interface ReadingProgress {
  current_page: number;
  total_pages: number;
  cfi?: string;
  percentage?: number;
  last_read_at: string;
}
async function getReaderMetadata(mediaItemId: string): Promise<ReaderMetadata> {
  const response = await apiGet(`/media-items/${mediaItemId}`);
  return handleResponse<ReaderMetadata>(response);
}
async function updateReadingProgress(
  mediaItemId: string,
  progress: ReadingProgress,
): Promise<void> {
  const response = await apiPut(
    `/media-items/${mediaItemId}/progress`,
    progress,
  );
  await handleVoidResponse(response);
}

async function getReadingProgress(
  mediaItemId: string,
): Promise<ReadingProgress | null> {
  const response = await apiGet(`/media-items/${mediaItemId}/progress`);

  if (response.status === 404) {
    return null;
  }

  return handleResponse<ReadingProgress>(response);
}

export {
  apiGet,
  apiPost,
  apiPut,
  apiDelete,
  apiPatch,
  handleResponse,
  handleVoidResponse,
  handleError,
  getReaderMetadata,
  getReadingProgress, // ADD THIS
  updateReadingProgress,
  ReadingProgress,
};

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