const API_BASE_URL = String(import.meta.env.VITE_API_BASE_URL || '').replace(/\/$/, '')

let accessToken = ''
let refreshHandler = null

export function setAccessToken(token) {
  accessToken = token || ''
}

export function clearAccessToken() {
  accessToken = ''
}

export function setRefreshHandler(handler) {
  refreshHandler = handler
}

function buildUrl(path) {
  if (!API_BASE_URL) return path
  if (/^https?:\/\//i.test(path)) return path
  return `${API_BASE_URL}${path.startsWith('/') ? '' : '/'}${path}`
}

async function readBody(res) {
  if (res.status === 204) return null
  const contentType = res.headers.get('content-type') || ''
  if (contentType.includes('application/json')) return res.json()
  return res.text()
}

function normalizeError(data) {
  if (!data) return new Error('Request failed')
  if (typeof data === 'string') return new Error(data)
  if (typeof data?.message === 'string') return new Error(data.message)
  return new Error('Request failed')
}

async function tryRefresh() {
  if (!refreshHandler) return false
  try {
    const token = await refreshHandler()
    if (!token) {
      clearAccessToken()
      return false
    }
    setAccessToken(token)
    return true
  } catch {
    clearAccessToken()
    return false
  }
}

export async function apiRequest(
  path,
  { method = 'GET', body, headers = {}, skipAuth = false, skipRefresh = false } = {},
) {
  const url = buildUrl(path)

  const finalHeaders = new Headers(headers)
  if (!skipAuth && accessToken) {
    finalHeaders.set('Authorization', `Bearer ${accessToken}`)
  }

  let finalBody = body
  if (body && !(body instanceof FormData) && typeof body === 'object') {
    finalHeaders.set('Content-Type', 'application/json')
    finalBody = JSON.stringify(body)
  }

  const res = await fetch(url, {
    method,
    headers: finalHeaders,
    body: finalBody,
    credentials: 'include',
  })

  if (res.status === 401 && !skipRefresh) {
    const refreshed = await tryRefresh()
    if (refreshed) {
      return apiRequest(path, { method, body, headers, skipAuth, skipRefresh: true })
    }
  }

  const data = await readBody(res)

  if (!res.ok) {
    throw normalizeError(data)
  }

  return data
}
