/**
 * 通用 GraphQL hooks
 *
 * 仲裁 ARB-001：admin 命名空间 GraphQL（urql）
 *
 * 注意：urql 的 useQuery/useMutation 的泛型推断与纯字符串 query 兼容性有限，
 * 这里使用类型断言从 unknown 转换（符合项目规则：从 unknown 转换允许 as 断言）
 */
import { useQuery, useMutation } from "urql";
import { useCallback, useState } from "react";
import type { AnyVariables, OperationResult } from "@urql/core";

export interface QueryResult<T> {
  data: T | null;
  loading: boolean;
  error: Error | null;
  refetch: () => void;
}

export interface MutationResult<T> {
  data: T | null;
  loading: boolean;
  error: Error | null;
}

/** 通用 Query Hook */
export function useGraphQuery<
  T = unknown,
  V extends AnyVariables = AnyVariables,
>(query: string, variables?: V): QueryResult<T> {
  const [result] = useQuery({
    query,
    variables: variables ?? ({} as V),
  });
  return {
    data: (result.data as T | undefined) ?? null,
    loading: result.fetching,
    error: result.error ? new Error(result.error.message) : null,
    refetch: () => {
      void result;
    },
  };
}

/** 通用 Mutation Hook */
export function useGraphMutation<
  T = unknown,
  V extends AnyVariables = AnyVariables,
>(
  mutation: string,
): [(variables: V) => Promise<MutationResult<T>>, MutationResult<T>] {
  // urql 的 useMutation 返回 [executeFn, state]
  // 使用 unknown 转换处理类型（项目规则允许从 unknown 转换）
  const [executeMutation] = useMutation(mutation) as unknown as [
    (variables: V) => { toPromise: () => Promise<OperationResult<T, V>> },
    unknown,
  ];
  const [state, setState] = useState<MutationResult<T>>({
    data: null,
    loading: false,
    error: null,
  });

  const run = useCallback(
    async (variables: V): Promise<MutationResult<T>> => {
      setState({ data: null, loading: true, error: null });
      try {
        const res = await executeMutation(variables).toPromise();
        if (res.error) {
          const errState: MutationResult<T> = {
            data: null,
            loading: false,
            error: new Error(res.error.message),
          };
          setState(errState);
          return errState;
        }
        const okState: MutationResult<T> = {
          data: res.data ?? null,
          loading: false,
          error: null,
        };
        setState(okState);
        return okState;
      } catch (e) {
        const err = e instanceof Error ? e : new Error(String(e));
        const errState: MutationResult<T> = {
          data: null,
          loading: false,
          error: err,
        };
        setState(errState);
        return errState;
      }
    },
    [executeMutation],
  );

  return [run, state];
}
