const API_BASE = import.meta.env.VITE_API_URL || ""; export async function request(path, options = {}) { const url = `${API_BASE}${path}`; const response = await fetch(url, { headers: { "Content-Type": "application/json", ...options.headers, }, ...options, }); if (!response.ok) { const errText = await response.text(); let parsedErr; try { parsedErr = JSON.parse(errText); } catch { parsedErr = errText; } throw new Error(parsedErr?.detail || parsedErr || "Request failed"); } return response.json(); } export const api = { // Products getProducts: () => request("/api/products/"), getProductPriceHistory: (id) => request(`/api/products/${id}/price-history`), updateProduct: (id, data) => request(`/api/products/${id}`, { method: "PUT", body: JSON.stringify(data) }), getCategories: () => request("/api/products/categories"), // Inventory getInventories: () => request("/api/inventory/"), adjustInventoryStock: (id, change, reason) => request(`/api/inventory/${id}/adjust?qty_change=${change}&reason=${encodeURIComponent(reason)}`, { method: "POST" }), getInventoryHistory: (id) => request(`/api/inventory/${id}/history`), getReplenishmentRecommendations: () => request("/api/inventory/recommendations/replenishment"), getTransferRecommendations: () => request("/api/inventory/recommendations/transfers"), getWarehouses: () => request("/api/inventory/warehouses"), getWarehousesStatus: () => request("/api/inventory/warehouses/status"), // Orders getOrders: () => request("/api/orders/"), createOrder: (data) => request("/api/orders/", { method: "POST", body: JSON.stringify(data) }), // Simulator Controls getSimulatorStatus: () => request("/api/orders/simulator/status"), controlSimulator: (is_running, speed = 1.0, demand_type = "normal", demand_multiplier = 1.0, seasonality_level = "medium", supply_level = "medium", flash_sale_active = false, competitor_discount_active = false, scenario = "Normal Demand") => request("/api/orders/simulator/control", { method: "POST", body: JSON.stringify({ is_running, speed, demand_type, demand_multiplier, seasonality_level, supply_level, flash_sale_active, competitor_discount_active, scenario }) }), generateBulkOrders: (count = 10000) => request(`/api/orders/simulator/generate?count=${count}`, { method: "POST" }), // Pricing Decisions getPricingDecisions: () => request("/api/products/pricing-decisions/recommendations"), // Analytics getKPIs: () => request("/api/analytics/kpis"), getRevenueChart: (days = 30) => request(`/api/analytics/revenue-chart?days=${days}`), getForecastChart: (productId) => request(`/api/analytics/forecast-chart?product_id=${productId}`), // System Controls triggerPricingEngine: () => request("/api/system/trigger/pricing", { method: "POST" }), triggerForecastEngine: () => request("/api/system/trigger/forecast", { method: "POST" }), triggerAnomalyDetection: () => request("/api/system/trigger/anomaly", { method: "POST" }), triggerScenarioEvent: (eventType) => request("/api/system/trigger/event", { method: "POST", body: JSON.stringify({ event_type: eventType }) }), getAnomalies: (resolved = false) => request(`/api/system/anomalies?resolved=${resolved}`), resolveAnomaly: (id) => request(`/api/system/anomalies/${id}/resolve`, { method: "POST" }), getAuditLogs: () => request("/api/system/audit-logs"), // SSE Stream subscribeToAlerts: (onEventMap) => { const eventSource = new EventSource(`${API_BASE}/api/system/alerts/stream`); // Connect default listeners Object.entries(onEventMap).forEach(([eventName, callback]) => { eventSource.addEventListener(eventName, (e) => { try { const data = JSON.parse(e.data); callback(data); } catch (err) { console.error(`Error parsing SSE data for [${eventName}]:`, err); } }); }); eventSource.onerror = (err) => { console.warn("SSE connection error, attempting auto-reconnect:", err); }; return () => { eventSource.close(); }; } };