import type { User } from '@repo/auth/auth'
import { requestIdContext, userContext } from '@repo/auth/context'

import type { LoaderFunctionArgs } from 'react-router'

export enum HttpMethod {
  GET = 'GET',
  POST = 'POST',
  PUT = 'PUT',
  PATCH = 'PATCH',
  DELETE = 'DELETE'
}

type RequestArgs = {
  url: string
  method?: HttpMethod
  headers?: HeadersInit
  body?: BodyInit | null
  request: LoaderFunctionArgs['request']
  context: LoaderFunctionArgs['context']
}

export function request({
  url,
  method = HttpMethod.GET,
  body = null,
  headers: _headers = {},
  request: { signal },
  context
}: RequestArgs): Promise<Response> {
  const requestId = context.get(requestIdContext) as string
  const user = context.get(userContext) as User
  const url_ = new URL(url, context.cloudflare.env.API_URL)
  const headers = new Headers({
    Authorization: `Bearer ${user.accessToken}`
  })

  if (_headers instanceof Headers) {
    _headers.forEach((value, key) => headers.set(key, value))
  } else {
    Object.entries(_headers).forEach(([key, value]) => headers.set(key, value))
  }

  console.log(
    `[${new Date().toISOString()}] [${requestId}] ${method} ${url_.toString()}`
  )

  return fetch(url_.toString(), { method, headers, body, signal })
}
