import { cookies, headers } from "next/headers"
import { type Session } from "next-auth"

import { Lang } from "@/constants/languages"

import { auth } from "@/auth"

import { unauthorizedError } from "./errors/trpc"

typeof auth

type CreateContextOptions = {
  auth: () => Promise<Session>
  lang: Lang
  pathname: string
  uid?: string | null
  url: string
  webToken?: string
  contentType?: string
}

/** Use this helper for:
 * - testing, where we dont have to Mock Next.js' req/res
 * - trpc's `createSSGHelpers` where we don't have req/res
 **/
export function createContextInner(opts: CreateContextOptions) {
  return {
    auth: opts.auth,
    lang: opts.lang,
    pathname: opts.pathname,
    uid: opts.uid,
    url: opts.url,
    webToken: opts.webToken,
    contentType: opts.contentType,
  }
}

/**
 * This is the actual context you'll use in your router
 * @link https://trpc.io/docs/context
 **/
export function createContext() {
  const h = headers()

  const cookie = cookies()
  const webviewTokenCookie = cookie.get("webviewToken")

  return createContextInner({
    auth: async () => {
      const session = await auth()
      const webToken = webviewTokenCookie?.value
      if (!session?.token && !webToken) {
        throw unauthorizedError()
      }

      return session || ({ token: { access_token: webToken } } as Session)
    },
    lang: h.get("x-lang") as Lang,
    pathname: h.get("x-pathname")!,
    uid: h.get("x-uid"),
    url: h.get("x-url")!,
    webToken: webviewTokenCookie?.value,
    contentType: h.get("x-contenttype")!,
  })
}

export type Context = ReturnType<typeof createContext>
