import { API_URL } from '@shared/config/env'
import { getCsrfToken } from './csrf'
import { tokenStore, refreshAccessToken } from './tokenStore'

async function doRequest<T>(path: string, options: RequestInit, allowRetry: boolean): Promise<T> {
  const csrf = await getCsrfToken()
  const bearer = tokenStore.get()

  const headers: HeadersInit = {
    'Content-Type': 'application/json',
    'X-CSRF-Token': csrf,
    ...(bearer ? { Authorization: `Bearer ${bearer}` } : {}),
    ...options.headers,
  }

  const res = await fetch(`${API_URL}${path}`, { ...options, credentials: 'include', headers })

  if (res.status === 401 && allowRetry) {
    try {
      await refreshAccessToken()
      return doRequest<T>(path, options, false)
    } catch {
      tokenStore.clear()
      throw new Error('Unauthorized')
    }
  }

  const data = await res.json()
  if (!res.ok) throw data
  return data as T
}

export const api = {
  get: <T>(path: string) => doRequest<T>(path, {}, true),
  post: <T>(path: string, body: unknown) =>
    doRequest<T>(path, { method: 'POST', body: JSON.stringify(body) }, true),
}
