import type { Credentials, DlqItem, NotificationGroup, NotificationPrefs, Task } from '../types' import { clearSession, session, setSessionToken } from '../stores/session' const API_BASE = 'http://localhost:8080/api/v1' function headers(extra?: Record) { const h: Record = { 'Content-Type': 'application/json', ...(extra ?? {}) } if (session.token) h.Authorization = `Bearer ${session.token}` return h } async function handle(response: Response): Promise { if (!response.ok) { const body = await response.text() throw new Error(body || `Request failed: ${response.status}`) } if (response.status === 204) return undefined as T return (await response.json()) as T } async function refreshAccessToken(): Promise { try { const response = await fetch(`${API_BASE}/auth/refresh`, { method: 'POST', credentials: 'include', headers: headers(), }) if (!response.ok) return false const data = (await response.json()) as { access_token: string } if (!data?.access_token) return false setSessionToken(data.access_token) return true } catch { return false } } async function request(path: string, init: RequestInit = {}, allowRefresh = true): Promise { const merged: RequestInit = { credentials: 'include', ...init, headers: headers((init.headers as Record | undefined) ?? {}), } const response = await fetch(`${API_BASE}${path}`, merged) if (response.status === 401 && allowRefresh && !path.startsWith('/auth/')) { const refreshed = await refreshAccessToken() if (refreshed) { return request(path, init, false) } clearSession() } return handle(response) } export async function register(credentials: Credentials, autoLogin = true) { return request<{ email: string; access_token?: string; expires_in?: number; session_id?: string }>('/auth/register', { method: 'POST', body: JSON.stringify({ ...credentials, auto_login: autoLogin }), }) } export async function login(credentials: Credentials) { return request<{ access_token: string; expires_in: number; session_id: string }>('/auth/login', { method: 'POST', body: JSON.stringify(credentials), }) } export async function refresh() { return request<{ access_token: string; expires_in: number; session_id: string }>('/auth/refresh', { method: 'POST', }, false) } export async function logout() { return request('/auth/logout', { method: 'POST', }, false) } export async function logoutAll() { return request('/auth/logout-all', { method: 'POST', }, false) } export async function listSessions() { return request>('/auth/sessions') } export async function revokeSession(id: string) { return request(`/auth/sessions/${id}`, { method: 'DELETE' }, false) } export async function listTasks() { return request('/tasks') } export async function createTask(payload: Partial) { return request('/tasks', { method: 'POST', body: JSON.stringify(payload), }) } export async function updateTask(id: number, payload: Partial) { return request(`/tasks/${id}`, { method: 'PUT', body: JSON.stringify(payload), }) } export async function deleteTask(id: number) { return request(`/tasks/${id}`, { method: 'DELETE', }) } export async function getNotificationPrefs() { return request('/notifications/prefs') } export async function updateNotificationPrefs(payload: NotificationPrefs) { return request('/notifications/prefs', { method: 'PUT', body: JSON.stringify(payload), }) } export async function listNotificationGroups() { return request('/notifications/groups') } export async function createNotificationGroup(payload: Omit) { return request('/notifications/groups', { method: 'POST', body: JSON.stringify(payload), }) } export async function updateNotificationGroup(id: number, payload: Omit) { return request(`/notifications/groups/${id}`, { method: 'PUT', body: JSON.stringify(payload), }) } export async function deleteNotificationGroup(id: number) { return request(`/notifications/groups/${id}`, { method: 'DELETE', }) } export async function listNotificationDlq(page = 1, pageSize = 20) { return request(`/notifications/dlq?page=${page}&page_size=${pageSize}`) }