import "server-only"

import { GraphQLClient } from "graphql-request"
import { cache } from "react"

import { env } from "@/env/server"

import type { DocumentNode } from "graphql"

import type { Data } from "@/types/request"

const client = new GraphQLClient(env.CMS_URL, {
  cache: "force-cache",
  fetch: cache(async function (
    url: URL | RequestInfo,
    params: RequestInit | undefined
  ) {
    return fetch(url, params)
  }),
})

export async function request<T>(
  query: string | DocumentNode,
  variables?: {},
  options?: Pick<RequestInit, "cache" | "next">
): Promise<Data<T>> {
  if (options?.cache) {
    client.requestConfig.cache = options.cache
  }
  if (options?.next) {
    client.requestConfig.next = options.next
  }

  if (env.PRINT_QUERY) {
    const { print } = await import("graphql")
    const rawResponse = await client.rawRequest<T>(
      print(query as DocumentNode),
      variables,
      {
        access_token: env.CMS_ACCESS_TOKEN,
        "Content-Type": "application/json",
      }
    )

    /**
     * TODO: Send to Monitoring (Logging and Metrics)
     */
    console.log({
      complexityLimit: rawResponse.headers.get("x-query-complexity"),
    })
    console.log({
      referenceDepth: rawResponse.headers.get("x-reference-depth"),
    })
    console.log({ resolverCost: rawResponse.headers.get("x-resolver-cost") })

    return {
      data: rawResponse.data,
    }
  }

  const response = await client.request<T>({
    document: query,
    requestHeaders: {
      access_token: env.CMS_ACCESS_TOKEN,
      "Content-Type": "application/json",
    },
    variables,
  })

  return { data: response }
}
