import { useCallback, useMemo } from "react";

/**
 * useApi - ApiClient 实例管理
 *
 * 用途：注入 token + 401 处理 + trace_id 透传。
 * P2 阶段：GraphQL client（urql/apollo）注入；本 hook 提供统一 fetcher 封装。
 *
 * 注意：本 hook 不直接创建 GraphQL client（由 Shell 的 GraphQLProvider 注入）。
 * 本 hook 提供"API 调用层"封装，用于非 GraphQL 场景（如文件上传 / SSE 流）。
 *
 * @example
 * const { fetchJson, fetchWithAuth } = useApi({ token, traceId });
 * const data = await fetchJson("/api/v1/upload", { method: "POST", body: formData });
 */

export interface UseApiProps {
  /** 认证 token（从 useAuth 获取） */
  token: string | null;
  /** trace_id（从 useTraceId 获取） */
  traceId?: string | null;
  /** 401 回调（通常跳转登录页） */
  onUnauthorized?: () => void;
}

export interface UseApiReturn {
  /** 带 auth + trace_id 的 fetch 封装 */
  fetchWithAuth: (url: string, init?: RequestInit) => Promise<Response>;
  /** fetchJson - 解析 JSON 响应 */
  fetchJson: <T>(url: string, init?: RequestInit) => Promise<T>;
  /** 构造带 auth 的 headers */
  authHeaders: Record<string, string>;
}

export function useApi({
  token,
  traceId,
  onUnauthorized,
}: UseApiProps): UseApiReturn {
  const authHeaders = useMemo(() => {
    const headers: Record<string, string> = {
      "Content-Type": "application/json",
    };
    if (token) {
      headers["Authorization"] = `Bearer ${token}`;
    }
    if (traceId) {
      headers["X-Trace-Id"] = traceId;
    }
    return headers;
  }, [token, traceId]);

  const fetchWithAuth = useCallback(
    async (url: string, init?: RequestInit): Promise<Response> => {
      const mergedInit: RequestInit = {
        ...init,
        headers: {
          ...authHeaders,
          ...(init?.headers ?? {}),
        },
      };

      const response = await fetch(url, mergedInit);

      if (response.status === 401) {
        onUnauthorized?.();
      }

      return response;
    },
    [authHeaders, onUnauthorized],
  );

  const fetchJson = useCallback(
    async <T>(url: string, init?: RequestInit): Promise<T> => {
      const response = await fetchWithAuth(url, init);
      if (!response.ok) {
        throw new Error(`API error: ${response.status} ${response.statusText}`);
      }
      return (await response.json()) as T;
    },
    [fetchWithAuth],
  );

  return {
    fetchWithAuth,
    fetchJson,
    authHeaders,
  };
}
