import { OrganizationContext } from './chunk-DD3CCMCZ.js';
import { APIClientError } from './chunk-XOPLS4S6.js';
import { createContext, useContext, useMemo, useCallback } from 'react';
import { jsx } from 'react/jsx-runtime';

var ApiClientContext = createContext(null);
function useApiClientContext() {
  const context = useContext(ApiClientContext);
  if (!context) {
    throw new Error("useApiClient must be used within ApiClientProvider");
  }
  return context;
}
function ApiClientProvider({
  children,
  getAccessToken,
  organizationId = null,
  getOrganizationId: getOrganizationIdProp,
  isOrganizationReady,
  onError
}) {
  const getOrganizationId = useMemo(
    () => getOrganizationIdProp ?? (() => organizationId ?? null),
    [getOrganizationIdProp, organizationId]
  );
  const value = useMemo(
    () => ({
      getAccessToken,
      organizationId: organizationId ?? null,
      isOrganizationReady,
      getOrganizationId,
      onError
    }),
    [getAccessToken, organizationId, isOrganizationReady, getOrganizationId, onError]
  );
  return /* @__PURE__ */ jsx(ApiClientContext.Provider, { value, children });
}

// ../core/src/platform/constants/http.ts
var HTTP_HEADERS = {
  /**
   * Organization context header
   * Note: Node.js normalizes all headers to lowercase, so we use lowercase consistently
   */
  WORKOS_ORGANIZATION_ID: "workos-organization-id",
  AGENT_ORGANIZATION: "x-agent-organization",
  AGENT_MODE: "x-agent-mode"
};

// src/api/hooks/useApiClient.ts
var DEFAULT_TIMEOUT_MS = 6e4;
function buildApiRequest(getAccessToken, getOrganizationId, apiUrl, handleResponseError) {
  return async function apiRequest(endpoint, options = {}) {
    try {
      const token = await getAccessToken();
      const organizationId = getOrganizationId();
      const headers = {
        ...options.body ? { "Content-Type": "application/json" } : {},
        ...token ? { Authorization: `Bearer ${token}` } : {},
        ...organizationId && { [HTTP_HEADERS.WORKOS_ORGANIZATION_ID]: organizationId },
        ...options.headers
      };
      const timeoutSignal = AbortSignal.timeout(DEFAULT_TIMEOUT_MS);
      const signal = options.signal ? AbortSignal.any([options.signal, timeoutSignal]) : timeoutSignal;
      const response = await fetch(`${apiUrl}/api${endpoint}`, {
        ...options,
        headers,
        signal
      });
      if (!response.ok) {
        await handleResponseError(endpoint, response, options);
      }
      if (response.status === 204) {
        return void 0;
      }
      const data = await response.json();
      return data;
    } catch (error) {
      if (error instanceof Error && error.message.includes("No access token")) {
        const headers = {
          ...options.body ? { "Content-Type": "application/json" } : {},
          ...options.headers
        };
        const fallbackTimeoutSignal = AbortSignal.timeout(DEFAULT_TIMEOUT_MS);
        const fallbackSignal = options.signal ? AbortSignal.any([options.signal, fallbackTimeoutSignal]) : fallbackTimeoutSignal;
        const response = await fetch(`${apiUrl}/api${endpoint}`, {
          ...options,
          headers,
          signal: fallbackSignal
        });
        if (!response.ok) {
          await handleResponseError(endpoint, response, options);
        }
        if (response.status === 204) {
          return void 0;
        }
        return response.json();
      }
      throw error;
    }
  };
}
function useApiClient(apiUrl) {
  const { getAccessToken, getOrganizationId, isOrganizationReady: contextOrgReady, onError } = useApiClientContext();
  const orgCtx = useContext(OrganizationContext);
  const orgReady = orgCtx ? !!orgCtx.currentWorkOSOrganizationId && !orgCtx.isInitializing && !orgCtx.isOrgRefreshing : contextOrgReady;
  const orgInitializing = orgCtx ? orgCtx.isInitializing || orgCtx.isOrgRefreshing : false;
  const handleResponseError = useCallback(
    async (endpoint, response, options) => {
      const errorData = await response.json().catch(() => ({
        error: `HTTP ${response.status}`,
        code: "INTERNAL_SERVER_ERROR"
      }));
      if (response.status >= 500 && onError) {
        onError(endpoint, new Error(errorData.error), {
          method: options.method || "GET",
          statusCode: response.status,
          requestId: errorData.requestId
        });
      }
      throw new APIClientError(
        errorData.error,
        errorData.code,
        response.status,
        errorData.requestId,
        errorData.fields,
        errorData.retryAfter
      );
    },
    [onError]
  );
  const apiRequest = useCallback(
    (endpoint, options = {}) => buildApiRequest(getAccessToken, getOrganizationId, apiUrl, handleResponseError)(endpoint, options),
    [getAccessToken, getOrganizationId, apiUrl, handleResponseError]
  );
  const deferredApiRequest = useCallback(
    async (endpoint, options = {}) => {
      if (orgInitializing) {
        throw new Error("Organization context is still initializing. Please wait.");
      }
      if (!orgReady) {
        throw new Error("No organization selected. Please select an organization.");
      }
      return apiRequest(endpoint, options);
    },
    [apiRequest, orgInitializing, orgReady]
  );
  return {
    apiRequest,
    deferredApiRequest,
    isOrganizationReady: orgReady,
    isInitializing: orgInitializing
  };
}

export { ApiClientProvider, HTTP_HEADERS, useApiClient, useApiClientContext };
