import { getBaseUrl, type BaseUrlKey } from "./baseUrls";

export type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";

export interface EndpointConfig {
  base: BaseUrlKey; // e.g. "events"
  path: string; // e.g. "/api/event/all"
  method: HttpMethod;
}

export const createEndpoint = (
  base: BaseUrlKey,
  path: string,
  method: HttpMethod = "GET"
): EndpointConfig => ({ base, path, method });

interface CallEndpointOptions<TBody> {
  body?: TBody;
  query?: Record<string, string | number | boolean | undefined>;
  headers?: Record<string, string>;
}

export async function callEndpoint<TResponse = unknown, TBody = unknown>(
  endpoint: EndpointConfig,
  options: CallEndpointOptions<TBody> = {}
): Promise<TResponse> {
  const { body, query, headers } = options;

  const baseUrl = getBaseUrl(endpoint.base);
  const url = buildUrl(baseUrl, endpoint.path, query);

  const init: RequestInit = {
    method: endpoint.method,
    headers: {
      "Content-Type": "application/json",
      ...(headers || {}),
    },
  };

  if (body && endpoint.method !== "GET") {
    // @ts-ignore body is allowed on RequestInit for fetch
    init.body = JSON.stringify(body);
  }

  // Debug log of what we're calling (without dumping full token)
  const authHeader = headers?.Authorization || "";
  const shortToken = authHeader.startsWith("Bearer ")
    ? authHeader.slice(7, 27) + "..."
    : undefined;
  // eslint-disable-next-line no-console
  console.log("[api] request", {
    url,
    method: endpoint.method,
    hasAuth: !!authHeader,
    tokenPrefix: shortToken,
  });

  const res = await fetch(url, init as any);

  if (!res.ok) {
    const text = await res.text().catch(() => "");
    // eslint-disable-next-line no-console
    console.log("[api] error response", {
      url,
      status: res.status,
      body: text,
    });
    throw new Error(text || `Request failed with status ${res.status}`);
  }

  const contentType = res.headers.get("content-type") || "";
  if (contentType.includes("application/json")) {
    return (await res.json()) as TResponse;
  }

  return (await res.text()) as unknown as TResponse;
}

function buildUrl(
  baseUrl: string,
  path: string,
  query?: Record<string, string | number | boolean | undefined>
): string {
  const trimmedBase = baseUrl.replace(/\/$/, "");
  const trimmedPath = path.startsWith("/") ? path : `/${path}`;
  const url = new URL(trimmedBase + trimmedPath);

  if (query) {
    Object.entries(query).forEach(([key, value]) => {
      if (value === undefined) return;
      url.searchParams.set(key, String(value));
    });
  }

  return url.toString();
}
