import type { TadaDocumentNode } from 'gql.tada'
import { initGraphQLTada } from 'gql.tada'
import type {
  AnyVariables,
  SubscriptionHandler,
  UseMutationResponse,
  UseQueryArgs,
  UseQueryResponse,
  UseSubscriptionArgs,
  UseSubscriptionResponse,
} from 'urql'
import { useMutation, useQuery, useSubscription } from 'urql'
import type { introspection } from './graphql-env.d.ts'

export const graphql = initGraphQLTada<{
  introspection: introspection
  scalars: {
    Boolean: boolean
    DateTime: string
    ID: string
    Int: number
    String: string
    UUID: string
  }
}>()

/*
 * handles type inferrence issues
 * note: for suspense wrap context in useMemo
 */
export function useTypedQuery<
  Result,
  Variables extends AnyVariables = AnyVariables,
>(
  args: UseQueryArgs<Variables, Result> & {
    query: TadaDocumentNode<Result, Variables>
  }
): UseQueryResponse<Result> {
  return useQuery<Result, Variables>(args)
}
export function useTypedMutation<
  Result,
  Variables extends AnyVariables = AnyVariables,
>(
  query: TadaDocumentNode<Result, Variables>
): UseMutationResponse<Result, Variables> {
  return useMutation<Result, Variables>(query)
}
export function useTypedSubscription<
  Data,
  Result = Data,
  Variables extends AnyVariables = AnyVariables,
>(
  args: UseSubscriptionArgs<Variables, Data> & {
    query: TadaDocumentNode<Data, Variables>
  },
  handler?: SubscriptionHandler<Data, Result>
): UseSubscriptionResponse<Result> {
  return useSubscription<Data, Result, Variables>(args, handler)
}

export { readFragment } from 'gql.tada'
export type { FragmentOf, ResultOf, VariablesOf } from 'gql.tada'
