/**
 * GraphQL Provider 组件（ai14）
 *
 * ARB-002 裁裁：Shell 暴露 GraphQL client 单例。
 * - MF 模式（NEXT_PUBLIC_MF_ENABLED=true）：优先使用 Shell 暴露的 useGraphQLClient；
 *   若 Shell 尚未暴露，降级为独立 client（打印警告）
 * - 独立模式（NEXT_PUBLIC_MF_ENABLED=false）：使用 createStandaloneClient() 单例
 *
 * 用法：
 *   <GraphQLProvider>
 *     <App />
 *   </GraphQLProvider>
 *
 * MF 模式下 Shell 也可通过 client prop 注入：
 *   <GraphQLProvider client={shellClient}>
 *     <App />
 *   </GraphQLProvider>
 */

"use client";

import { useEffect, useState } from "react";
import type { ReactNode } from "react";
import { Provider } from "urql";
import type { Client } from "urql";
import { createStandaloneClient, getGraphQLClient, isMfMode } from "./client";

/** GraphQLProvider 组件 Props */
export interface GraphQLProviderProps {
  /** 子组件树 */
  children: ReactNode;
  /**
   * 外部注入的 client（MF 模式下由 Shell 注入）
   * 未提供时：
   * - 独立模式：使用 getGraphQLClient() 单例
   * - MF 模式：尝试从 Shell 动态加载，失败则降级为独立 client
   */
  client?: Client;
}

/**
 * 尝试动态加载 Shell 暴露的 useGraphQLClient hook
 *
 * ARB-002：Shell 通过 @edu/hooks 暴露 useGraphQLClient。
 * 当前 @edu/hooks 尚未实现该 hook，此处做运行时探测：
 * - 若可用：返回 Shell 的 client
 * - 若不可用：返回 null（降级为独立 client）
 *
 * @returns Promise<Client | null>
 */
async function tryLoadShellClient(): Promise<Client | null> {
  try {
    const mod = await import("@edu/hooks");
    const hooks = mod as Record<string, unknown>;
    const useGraphQLClient = hooks["useGraphQLClient"];
    if (typeof useGraphQLClient === "function") {
      // useGraphQLClient 是 React Hook，无法在异步上下文调用
      // 此处仅做存在性检测；实际使用由 MF Shell 在上层 Provider 注入
      // 当 Shell 就绪后，应通过 client prop 传入或由 Shell Provider 包裹
      return null;
    }
    return null;
  } catch {
    // @edu/hooks 加载失败（可能 MF 未启用或包未就绪）
    return null;
  }
}

/**
 * GraphQLProvider — 提供 urql client 给组件树
 *
 * 根据运行模式自动选择 client：
 * 1. 若 client prop 提供（Shell 注入）：直接使用
 * 2. 独立模式：使用 getGraphQLClient() 单例
 * 3. MF 模式（无 client prop）：尝试动态加载 Shell client，失败降级为独立 client
 */
export function GraphQLProvider({
  children,
  client: clientProp,
}: GraphQLProviderProps): ReactNode {
  const [activeClient, setActiveClient] = useState<Client>(() => {
    // 优先使用外部注入的 client
    if (clientProp) {
      return clientProp;
    }
    // 独立模式直接返回单例
    if (!isMfMode()) {
      return getGraphQLClient();
    }
    // MF 模式：先用独立 client 作为降级，后续异步尝试加载 Shell client
    return getGraphQLClient();
  });

  // MF 模式下异步探测 Shell 是否暴露 useGraphQLClient
  useEffect(() => {
    if (!isMfMode() || clientProp) {
      return;
    }

    let mounted = true;
    tryLoadShellClient().then((shellClient) => {
      if (!mounted || !shellClient) {
        // Shell 未就绪，保持独立 client（已在初始 state 中设置）
        if (isMfMode()) {
          console.warn(
            "[student-portal] ARB-002：Shell 未暴露 useGraphQLClient，降级为独立 urql client",
          );
        }
        return;
      }
      setActiveClient(shellClient);
    });

    return (): void => {
      mounted = false;
    };
  }, [clientProp]);

  return <Provider value={activeClient}>{children}</Provider>;
}

/**
 * 用于测试场景的 Provider（强制独立 client，不受 MF 配置影响）
 * @param props 组件 Props
 * @returns ReactNode
 */
export function StandaloneGraphQLProvider({
  children,
}: {
  children: ReactNode;
}): ReactNode {
  const client = createStandaloneClient();
  return <Provider value={client}>{children}</Provider>;
}
