// Runtime configuration for the SPA — server URL + auth token. Every fetch
// call goes through fetchWithAuth/apiBase (used by api.ts) so the SPA works
// identically whether it's served same-origin (browser prod, Vite dev proxy)
// or cross-origin (Wails webview, remote access). See
// plans/2026-07-12-wails-desktop-app.md 0.2.

export interface OikosConfig {
  apiUrl: string // e.g. "https://oikos.hubris.network", or "" for same-origin
  token?: string // bearer token for auth
}

declare global {
  interface Window {
    __OIKOS_CONFIG__?: OikosConfig
  }
}

let cfg: OikosConfig | undefined

export function initConfig(override?: OikosConfig) {
  cfg = override ?? window.__OIKOS_CONFIG__
  if (cfg?.token) {
    localStorage.setItem('oikos_token', cfg.token)
    if (cfg.apiUrl) localStorage.setItem('oikos_api_url', cfg.apiUrl)
  }
}

export function getConfig(): OikosConfig {
  if (!cfg) {
    const token = localStorage.getItem('oikos_token')
    const apiUrl = localStorage.getItem('oikos_api_url')
    if (token || apiUrl) {
      cfg = { apiUrl: apiUrl ?? '', token: token ?? undefined }
    }
  }
  return cfg ?? { apiUrl: '' }
}

export function setConfig(next: OikosConfig) {
  cfg = next
  if (next.token) localStorage.setItem('oikos_token', next.token)
  else localStorage.removeItem('oikos_token')
  if (next.apiUrl) localStorage.setItem('oikos_api_url', next.apiUrl)
  else localStorage.removeItem('oikos_api_url')
}

export function clearConfig() {
  cfg = { apiUrl: '' }
  localStorage.removeItem('oikos_token')
  localStorage.removeItem('oikos_api_url')
}

export function isConfigured(): boolean {
  return !!getConfig().token
}

// Relative paths are used in dev (Vite proxy) and when the SPA shares an
// origin with the API server (Caddy reverse proxy). Absolute paths are used
// when the API server is on a different origin (Wails webview, remote access).
export function apiBase(path: string): string {
  const c = getConfig()
  if (!c.apiUrl) return path // relative — relies on same-origin or Vite proxy
  return `${c.apiUrl}${path}`
}

// ---- Auth fetch wrapper ----
// Prepends the API base URL (absolute when configured, relative when unset
// for the Vite dev proxy / same-origin prod) and adds the Authorization
// header. Used by every fetch call in api.ts.
export async function fetchWithAuth(path: string, opts?: RequestInit): Promise<Response> {
  const headers: Record<string, string> = {
    'Content-Type': 'application/json',
    ...(opts?.headers as Record<string, string> ?? {})
  }
  const c = getConfig()
  if (c.token) {
    headers['Authorization'] = `Bearer ${c.token}`
  }

  return fetch(apiBase(path), { ...opts, headers })
}

// SSE path builder — EventSource doesn't take headers, so pass the token as
// a query parameter (the SSE handler's combinedAuth checks it alongside the
// Authorization header, only for this route).
export function sseUrl(path: string): string {
  const c = getConfig()
  const url = apiBase(path)
  if (!c.token) return url
  const sep = url.includes('?') ? '&' : '?'
  return `${url}${sep}token=${encodeURIComponent(c.token)}`
}
