import { parseApiError } from '@/lib/auth-api'; const API_PREFIX = '/api'; function getBaseUrl(): string { return import.meta.env.VITE_API_BASE_URL ?? ''; } let getToken: () => string | null = () => null; let getPropertyId: () => string | null = () => null; /** Register token + property scope for hotel API paths (call once from the auth store module). */ export function registerHotelApiContext(ctx: { getToken: () => string | null; getPropertyId: () => string | null; }) { getToken = ctx.getToken; getPropertyId = ctx.getPropertyId; } /** Paths that stay unscoped (mock-only or non-hotel). */ function shouldRewriteForHotel(path: string): boolean { const first = path.split('?')[0]; if (first.startsWith('/auth')) return false; if (first.startsWith('/properties')) return false; return true; } function rewriteHotelPath(path: string): string { const pid = getPropertyId(); if (!pid || !shouldRewriteForHotel(path)) return path; const [pathname, query] = path.split('?'); const q = query ? `?${query}` : ''; if (pathname === '/dashboard') { return `/properties/${pid}/hotel/dashboard/summary${q}`; } return `/properties/${pid}/hotel${pathname}${q}`; } async function request( method: string, path: string, body?: unknown, init?: RequestInit, ): Promise { const token = getToken(); const resolved = rewriteHotelPath(path); const headers: Record = { ...(init?.headers as Record), }; if (body !== undefined) headers['Content-Type'] = 'application/json'; if (token) headers.Authorization = `Bearer ${token}`; const url = `${getBaseUrl()}${API_PREFIX}${resolved}`; return fetch(url, { ...init, method, headers, body: body !== undefined ? JSON.stringify(body) : init?.body, }); } export async function apiGet(path: string, init?: RequestInit): Promise { const res = await request('GET', path, undefined, init); if (!res.ok) throw new Error(await parseApiError(res)); return res.json() as Promise; } export async function apiPost(path: string, body: unknown, init?: RequestInit): Promise { const res = await request('POST', path, body, init); if (!res.ok) throw new Error(await parseApiError(res)); return res.json() as Promise; } export async function apiPatch(path: string, body: unknown, init?: RequestInit): Promise { const res = await request('PATCH', path, body, init); if (!res.ok) throw new Error(await parseApiError(res)); return res.json() as Promise; } export async function apiDelete(path: string, init?: RequestInit): Promise { const res = await request('DELETE', path, undefined, init); if (!res.ok) throw new Error(await parseApiError(res)); } /** Authenticated binary download (e.g. CSV export). */ export async function apiDownloadBlob( path: string, init?: RequestInit, ): Promise<{ blob: Blob; filename: string | undefined }> { const token = getToken(); const resolved = rewriteHotelPath(path); const headers: Record = { ...(init?.headers as Record) }; if (token) headers.Authorization = `Bearer ${token}`; const url = `${getBaseUrl()}${API_PREFIX}${resolved}`; const res = await fetch(url, { ...init, method: 'GET', headers }); if (!res.ok) throw new Error(await parseApiError(res)); const cd = res.headers.get('Content-Disposition'); let filename: string | undefined; const m = cd?.match(/filename="?([^";]+)"?/); if (m) filename = m[1]; const blob = await res.blob(); return { blob, filename }; }