const NO_REFRESH_PATHS = new Set(['/api/auth/login', '/api/auth/register', '/api/auth/refresh'])

async function getAuthStore() {
  const { useAuthStore } = await import('../stores/auth.js')
  return useAuthStore()
}

function withAuthHeaders(options, accessToken) {
  const headers = { ...(options.headers || {}) }
  if (accessToken) headers.Authorization = `Bearer ${accessToken}`
  return { ...options, headers, credentials: 'include' }
}

function clearSession(authStore) {
  authStore.accessToken = null
  authStore.user = null
}

function fetchAuthenticated(url, options, authStore) {
  return fetch(url, withAuthHeaders(options, authStore.accessToken))
}

async function refreshAndRetry(authStore, retryFn) {
  try {
    await authStore.refresh()
    return retryFn()
  } catch {
    clearSession(authStore)
    throw new Error('Session expired')
  }
}

/** Core HTTP transport for JSON-returning API endpoints. */
export async function request(path, options = {}) {
  const authStore = await getAuthStore()
  const res = await fetch(path, withAuthHeaders(options, authStore.accessToken))

  if (res.status === 401 && !options._retry && !NO_REFRESH_PATHS.has(path)) {
    return refreshAndRetry(authStore, () => request(path, { ...options, _retry: true }))
  }

  if (!res.ok) {
    let msg = `HTTP ${res.status}`
    let payload = null
    try {
      const body = await res.json()
      if (Array.isArray(body.detail)) {
        // FastAPI validation error array — summarise into one actionable message
        const parts = body.detail.map(e => {
          const loc = e.loc ? e.loc.filter(s => s !== 'body').join('.') : ''
          return loc ? `${loc}: ${e.msg}` : e.msg
        })
        msg = parts.join('; ') || `Validation error (HTTP ${res.status})`
      } else if (typeof body.detail === 'object' && body.detail !== null) {
        payload = body.detail
        msg = body.detail.message || `HTTP ${res.status}`
      } else if (body.detail) {
        msg = body.detail
      }
    } catch {}
    const err = new Error(msg)
    err.status = res.status
    if (payload) err.payload = payload
    throw err
  }
  if (res.status === 204 || res.headers.get('content-length') === '0') return null
  return res.json()
}

export function jsonRequest(path, method, body) {
  return request(path, {
    method,
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
  })
}

/** Authenticated fetch with one refresh retry for raw/blob responses. */
export async function fetchWithRetry(url, options = {}, _retry = false) {
  const authStore = await getAuthStore()
  const res = await fetchAuthenticated(url, options, authStore)

  if (res.status === 401 && !_retry) {
    return refreshAndRetry(authStore, () => fetchWithRetry(url, options, true))
  }

  return res
}
