import { notifyAuthCleared } from './authSessionManager'
import { AUTH_TOKEN_KEY } from './authConstants'

const API_URL = (import.meta.env.VITE_API_URL ?? '').replace(/\/$/, '')
const API_LABEL = API_URL || 'same-origin /api'

export class ApiRequestError extends Error {
  status: number | null

  constructor(message: string, status: number | null = null) {
    super(message)
    this.name = 'ApiRequestError'
    this.status = status
  }
}

function getAuthToken() {
  if (typeof window === 'undefined') return null
  return window.localStorage.getItem(AUTH_TOKEN_KEY)
}

function clearAuthToken() {
  if (typeof window === 'undefined') return
  window.localStorage.removeItem(AUTH_TOKEN_KEY)
  notifyAuthCleared()
}

async function parseError(response: Response, path: string) {
  const error = await response.text().catch(() => '')
  const message = extractErrorMessage(error) || `API request failed for ${path}`
  throw new ApiRequestError(message, response.status)
}

function extractErrorMessage(error: string) {
  if (!error.trim()) return ''

  try {
    const parsed = JSON.parse(error) as { message?: unknown; title?: unknown; detail?: unknown }
    const message = parsed.message ?? parsed.detail ?? parsed.title
    return typeof message === 'string' ? message : error
  } catch {
    return error
  }
}

export async function requestJson<TResponse>(
  path: string,
  options: RequestInit = {},
): Promise<TResponse> {
  const token = getAuthToken()
  const headers = new Headers(options.headers)

  if (token) {
    headers.set('Authorization', `Bearer ${token}`)
  }

  const response = await fetch(`${API_URL}${path}`, {
    ...options,
    headers,
  }).catch(() => {
    throw new ApiRequestError(`API nicht erreichbar (${API_LABEL}). Bitte Backend starten.`)
  })

  if (!response.ok) {
    if (response.status === 401 || response.status === 403) {
      clearAuthToken()
    }
    await parseError(response, path)
  }

  return response.json() as Promise<TResponse>
}
