import apiClient from '../api/client'; import { normalizeChannelsPayload } from './businessProfile'; import { getRuntimeApplicationId, getRuntimeCompanyId } from './runtimeContext'; const FDK_BOOTSTRAP_ATTEMPT_PREFIX = 'sms_fdk_bootstrap_attempt'; const FDK_BOOTSTRAP_TTL_MS = 2 * 60 * 1000; const FDK_BOOTSTRAP_REDIRECT_CODE = 'FDK_AUTH_BOOTSTRAP_REDIRECT'; const FDK_SESSION_UNAVAILABLE_CODE = 'FDK_SESSION_UNAVAILABLE'; function getBootstrapStorageKey(companyId) { return `${FDK_BOOTSTRAP_ATTEMPT_PREFIX}:${companyId}`; } function readBootstrapAttempt(companyId) { if (!companyId || typeof sessionStorage === 'undefined') return 0; try { return Number(sessionStorage.getItem(getBootstrapStorageKey(companyId)) || 0); } catch { return 0; } } function writeBootstrapAttempt(companyId) { if (!companyId || typeof sessionStorage === 'undefined') return; try { sessionStorage.setItem(getBootstrapStorageKey(companyId), String(Date.now())); } catch { // Ignore storage failures and still attempt bootstrap redirect. } } function clearBootstrapAttempt(companyId) { if (!companyId || typeof sessionStorage === 'undefined') return; try { sessionStorage.removeItem(getBootstrapStorageKey(companyId)); } catch { // Ignore storage failures. } } function shouldBootstrapSession(companyId) { const lastAttempt = readBootstrapAttempt(companyId); if (!lastAttempt) return true; return (Date.now() - lastAttempt) > FDK_BOOTSTRAP_TTL_MS; } function buildFdkInstallUrl(companyId) { if (!companyId || typeof window === 'undefined') return ''; const search = new URLSearchParams({ company_id: companyId, redirect_path: window.location.href, }); const applicationId = getRuntimeApplicationId(); if (applicationId) { search.set('application_id', applicationId); } return `/fp/install?${search.toString()}`; } function createBootstrapRedirectError() { const error = new Error('Redirecting to FDK auth bootstrap'); error.code = FDK_BOOTSTRAP_REDIRECT_CODE; return error; } function createSessionUnavailableError(message = 'FDK session is unavailable') { const error = new Error(message); error.code = FDK_SESSION_UNAVAILABLE_CODE; return error; } function shouldAttemptBootstrap(sessionStatus = {}) { return Boolean(sessionStatus?.configured) && Boolean(sessionStatus?.needsBootstrap); } async function getSessionStatus() { const response = await apiClient.get('/api/platform/session-status'); return response?.data || {}; } async function ensureFdkPlatformSession(companyId) { if (!companyId) { throw createSessionUnavailableError('Missing company id for FDK session bootstrap'); } const sessionStatus = await getSessionStatus(); if (sessionStatus?.authenticated) { clearBootstrapAttempt(companyId); return sessionStatus; } if (shouldAttemptBootstrap(sessionStatus) && shouldBootstrapSession(companyId)) { const installUrl = buildFdkInstallUrl(companyId); if (installUrl && typeof window !== 'undefined') { writeBootstrapAttempt(companyId); window.location.replace(installUrl); throw createBootstrapRedirectError(); } } throw createSessionUnavailableError( sessionStatus?.reason ? `FDK session unavailable: ${sessionStatus.reason}` : 'FDK session is unavailable' ); } export async function fetchActiveSalesChannels() { const companyId = getRuntimeCompanyId(); try { await ensureFdkPlatformSession(companyId); const response = await apiClient.get('/api/platform/sales-channels'); clearBootstrapAttempt(companyId); return normalizeChannelsPayload( response?.data?.salesChannels || response?.data?.channels || response?.data?.items || [] ); } catch (error) { const status = error?.response?.status; if (status === 401 && companyId && shouldBootstrapSession(companyId)) { const installUrl = buildFdkInstallUrl(companyId); if (installUrl && typeof window !== 'undefined') { writeBootstrapAttempt(companyId); window.location.replace(installUrl); throw createBootstrapRedirectError(); } } throw error; } }