import { API_URL } from '@/lib/api'; export const VELOCITY_TOKEN_KEY = 'velocity-api-token'; export interface VelocityUserProfile { user_id: string; role: string; } export interface VelocityLoginResponse { access_token: string; token_type: string; expires_in: number; } export interface AdminHealthSnapshot { status: string; timestamp: string; database: { connected: boolean; latency_ms: number; }; queues: { pending_transcriptions: number; pending_synthetic_jobs: number; pending_admin_actions: number; pending_inventory_batches: number; }; active_sessions: { total: number; by_surface: Record; }; } export interface AdminQueueSnapshot { transcription_jobs: Record; synthetic_jobs: Record; inventory_batches: Record; admin_actions: Record; timestamp: string; } export interface AdminInstallSnapshot { installs: Array<{ surface_type: string; app_version: string; session_count: number; last_seen: string | null; }>; timestamp: string; } export interface AdminActionRecord { action_event_id: string; action_id: string; action_type: string; target_type: string; target_id: string; requested_by: string; status: string; result_message?: string | null; executed_at?: string | null; created_at: string; } export interface AdminActionRequest { action_type: string; target_type: string; target_id: string; payload?: Record; idempotency_key?: string; } export interface MobileEdgeAlertSnapshot { pending_insights: number; upcoming_calendar_events_24h: number; pending_transcriptions: number; generated_at: string; } export interface MobileCalendarEvent { calendar_event_id: string; lead_id?: string | null; title: string; description?: string | null; start_at: string; end_at: string; all_day: boolean; status: string; reminder_minutes: number[]; created_by: string; location?: string | null; metadata: Record; created_at: string; } export interface MobileCommunicationEvent { event_id: string; lead_id: string; channel: string; direction: string; provider?: string | null; capture_mode: string; consent_state: string; timestamp: string; duration_seconds?: number | null; summary?: string | null; raw_reference?: string | null; recording_ref?: string | null; provider_metadata: Record; created_at: string; } export interface InventoryImportBatchSummary { batch_id: string; source_type: string; submitted_by: string; status: string; total_rows: number; accepted_rows: number; rejected_rows: number; created_at: string; completed_at?: string | null; } export interface InventoryPropertySummary { property_id: string; project_name: string; developer_name: string; property_type: string; location: Record; price_bands: Array>; unit_mix: Array>; status: string; ingested_at?: string | null; created_at?: string | null; } function buildHeaders(init?: HeadersInit, includeJson = true): Headers { const headers = new Headers(init); if (includeJson && !headers.has('Content-Type')) { headers.set('Content-Type', 'application/json'); } if (!headers.has('Accept')) { headers.set('Accept', 'application/json'); } const token = getVelocityToken(); if (token && !headers.has('Authorization')) { headers.set('Authorization', `Bearer ${token}`); } return headers; } async function platformFetch(path: string, init?: RequestInit): Promise { const response = await fetch(`${API_URL}${path}`, { ...init, headers: buildHeaders(init?.headers, init?.body !== undefined), }); if (!response.ok) { const body = await response.json().catch(() => ({})); throw new Error( typeof body?.detail === 'string' ? body.detail : typeof body?.message === 'string' ? body.message : `Request failed: ${response.status}`, ); } return response.json() as Promise; } export function setVelocityToken(token: string) { localStorage.setItem(VELOCITY_TOKEN_KEY, token); } export function getVelocityToken(): string | null { return localStorage.getItem(VELOCITY_TOKEN_KEY); } export function clearVelocityToken() { localStorage.removeItem(VELOCITY_TOKEN_KEY); } export function normalizeVelocityRole(role: string | null | undefined): string { return (role ?? '').trim().toUpperCase(); } export function isAdminRole(role: string | null | undefined): boolean { const normalized = normalizeVelocityRole(role); return normalized === 'ADMIN' || normalized === 'SUPERADMIN'; } export async function loginVelocity(email: string, password: string): Promise { const auth = await platformFetch('/api/auth/login', { method: 'POST', body: JSON.stringify({ email, password }), }); setVelocityToken(auth.access_token); return getVelocityMe(); } export async function getVelocityMe(): Promise { return platformFetch('/api/auth/me', { method: 'GET', }); } export async function getAdminHealth(): Promise { return platformFetch('/api/admin-surface/health'); } export async function getAdminQueues(): Promise { return platformFetch('/api/admin-surface/queues'); } export async function getAdminInstalls(): Promise { return platformFetch('/api/admin-surface/installs'); } export async function listAdminActions(limit = 20): Promise<{ actions: AdminActionRecord[] }> { return platformFetch<{ actions: AdminActionRecord[] }>( `/api/admin-surface/actions?limit=${encodeURIComponent(String(limit))}`, ); } export async function submitAdminAction(body: AdminActionRequest): Promise<{ action_event_id: string; action_id: string; status: string; created_at: string; }> { return platformFetch('/api/admin-surface/actions', { method: 'POST', body: JSON.stringify(body), }); } export async function getMobileAlerts(): Promise { return platformFetch('/api/mobile-edge/alerts'); } export async function getMobileCalendarEvents(): Promise<{ events: MobileCalendarEvent[] }> { return platformFetch<{ events: MobileCalendarEvent[] }>('/api/mobile-edge/calendar'); } export async function getMobileEventsByLead( leadId: string, limit = 20, ): Promise<{ events: MobileCommunicationEvent[] }> { const params = new URLSearchParams({ lead_id: leadId, limit: String(limit), }); return platformFetch<{ events: MobileCommunicationEvent[] }>(`/api/mobile-edge/events?${params.toString()}`); } export async function listInventoryImportBatches(limit = 10): Promise<{ batches: InventoryImportBatchSummary[] }> { return platformFetch<{ batches: InventoryImportBatchSummary[] }>( `/api/inventory/import-batches?limit=${encodeURIComponent(String(limit))}`, ); } export async function listInventoryProperties(limit = 100): Promise<{ properties: InventoryPropertySummary[] }> { return platformFetch<{ properties: InventoryPropertySummary[] }>( `/api/inventory/properties?limit=${encodeURIComponent(String(limit))}`, ); }