import { redirectOnAuthFailure } from "@/utils/auth-redirect";
import { getClerkSessionToken } from "@/utils/clerk";
import type { RequestOptions } from "./types";

// API origin - empty string = relative URLs (proxied via nginx in Docker).
// Override via VITE_API_BASE_URL, e.g. "http://localhost:5000" for local dev without Docker.
const _envOrigin = import.meta.env.VITE_API_BASE_URL as string | undefined;
export const API_ORIGIN: string = (_envOrigin !== undefined && _envOrigin !== "") ? _envOrigin : "";
export const API_BASE = `${API_ORIGIN}/api/v1`;

const parseBody = async (response: Response): Promise<unknown> => {
  const contentType = response.headers.get("content-type") || "";
  if (contentType.includes("application/json")) {
    try {
      return await response.json();
    } catch {
      return null;
    }
  }

  const text = await response.text();
  if (!text) {
    return null;
  }

  try {
    return JSON.parse(text) as unknown;
  } catch {
    return text;
  }
};

export const fetchJson = async <T>(path: string, options: RequestOptions = {}): Promise<T> => {
  // Use Clerk session token for all authenticated requests.
  const token = await getClerkSessionToken();
  const headers = new Headers(options.headers);
  if (token) {
    headers.set("Authorization", `Bearer ${token}`);
  }

  let body = options.body;
  const isFormData = typeof FormData !== "undefined" && body instanceof FormData;
  if (body !== undefined && body !== null && !isFormData && typeof body !== "string") {
    headers.set("Content-Type", "application/json");
    body = JSON.stringify(body);
  }

  try {
    const response = await fetch(`${API_BASE}${path}`, {
      method: options.method ?? (body ? "POST" : "GET"),
      headers,
      body: body as BodyInit | null | undefined,
      credentials: "include",
    });

    if (!response.ok) {
      // Don't redirect on 401 for /auth/me - it's expected when not logged in
      const isAuthMeEndpoint = path.includes("/auth/me");
      if ((response.status === 401 || response.status === 403) && !isAuthMeEndpoint) {
        redirectOnAuthFailure();
      }
      let message = `${response.status} ${response.statusText}`;
      const data = await parseBody(response);
      if (data && typeof data === "object" && "detail" in data) {
        const detail = (data as { detail?: string }).detail;
        if (detail) {
          message = detail;
        }
      } else if (typeof data === "string" && data.trim()) {
        message = data;
      }
      throw new Error(message);
    }

    if (response.status === 204) {
      return undefined as T;
    }

    const data = await parseBody(response);
    return data as T;
  } catch (error) {
    // Handle network errors (connection refused, timeout, etc.)
    if (error instanceof TypeError && error.message.includes("fetch")) {
      const networkError = new Error(
        `Không thể kết nối đến server. Vui lòng kiểm tra lại kết nối hoặc đảm bảo backend đang chạy tại ${API_ORIGIN}`
      );
      networkError.name = "NetworkError";
      throw networkError;
    }
    // Re-throw other errors as-is
    throw error;
  }
};

export const parseResourceId = (name: string): string => {
  const parts = name.split("/");
  return parts[parts.length - 1] || name;
};

