/** * Predictive Analytics API client for the admin dashboard. * Churn prediction, health scoring, and retention campaigns. */ import { createApiClient } from '@bytelyst/api-client'; const predictiveApi = createApiClient({ baseUrl: `${process.env.PLATFORM_SERVICE_URL || 'http://localhost:4003'}/api`, defaultHeaders: { 'x-product-id': process.env.PRODUCT_ID || 'lysnrai', }, }); // ── Health Scoring ──────────────────────────────────────────── export interface HealthDimension { score: number; metrics: Record; trend: 'improving' | 'stable' | 'declining'; } export interface ProductHealth { id: string; productId: string; date: string; overallHealthScore: number; healthStatus: 'critical' | 'warning' | 'healthy'; dimensions: { acquisition: HealthDimension; activation: HealthDimension; retention: HealthDimension; engagement: HealthDimension; revenue: HealthDimension; stability: HealthDimension; }; anomalies: Array<{ metric: string; expectedValue: number; actualValue: number; deviationPercent: number; severity: 'critical' | 'warning'; suggestedCause?: string; }>; forecasts: { next7Days: { expectedHealthScore: number; confidenceInterval: [number, number] }; next30Days: { expectedHealthScore: number; confidenceInterval: [number, number] }; }; vsBaseline7Day: number; vsBaseline30Day: number; } export async function getProductHealth(productId?: string): Promise { const url = productId ? `/predictive/health?productId=${productId}` : '/predictive/health'; return predictiveApi.fetch(url); } export async function getProductHealthDetail(productId: string): Promise { return predictiveApi.fetch(`/predictive/health/${productId}`); } export async function getHealthTrends(productId: string, days = 30): Promise { return predictiveApi.fetch(`/predictive/health/${productId}/trends?days=${days}`); } // ── Churn Prediction ───────────────────────────────────────── export type RiskSegment = 'critical' | 'high' | 'medium' | 'low'; export interface RiskFactor { feature: string; contribution: number; direction: 'positive' | 'negative'; description: string; } export interface ChurnPrediction { userId: string; productId: string; churnProbability: number; riskSegment: RiskSegment; confidenceScore: number; modelVersion: string; predictionTimestamp: string; explanation: { topRiskFactors: RiskFactor[]; nlExplanation: string; suggestedActions: string[]; }; } export async function getChurnScore(userId: string, productId: string, horizon = 30): Promise { return predictiveApi.fetch('/predictive/churn-score', { method: 'POST', body: JSON.stringify({ userId, productId, horizon: String(horizon) }), }); } export interface AtRiskUser { userId: string; productId: string; churnProbability: number; riskSegment: RiskSegment; confidenceScore: number; daysSinceLastSession: number; predictionTimestamp: string; } export async function getAtRiskUsers(options: { productId?: string; segment?: RiskSegment; limit?: number; offset?: number; } = {}): Promise<{ users: AtRiskUser[]; total: number }> { const params = new URLSearchParams(); if (options.productId) params.set('productId', options.productId); if (options.segment) params.set('segment', options.segment); if (options.limit) params.set('limit', String(options.limit)); if (options.offset) params.set('offset', String(options.offset)); return predictiveApi.fetch<{ users: AtRiskUser[]; total: number }>(`/predictive/at-risk-users?${params}`); } export interface UserRiskProfile extends ChurnPrediction { interventionHistory: Array<{ action: string; timestamp: string; outcome?: 'responded' | 'ignored' | 'churned' | 'retained'; }>; } export async function getUserRiskProfile(userId: string): Promise { return predictiveApi.fetch(`/predictive/users/${userId}/risk-profile`); } // ── Model Performance ───────────────────────────────────────── export interface ModelPerformance { modelVersion: string; modelType: string; trainedAt: string; auc: number; precisionAt10: number; recallAt10: number; calibrationSlope: number; featureImportance: Array<{ feature: string; importance: number }>; } export async function getModelPerformance(): Promise { return predictiveApi.fetch('/predictive/model/performance'); } export async function getFeatureImportance(): Promise> { const res = await predictiveApi.fetch<{ features: Array<{ feature: string; importance: number }> }>('/predictive/model/features'); return res.features; } // ── Retention Campaigns ────────────────────────────────────── export type CampaignStatus = 'draft' | 'active' | 'paused' | 'completed'; export type CampaignTriggerType = 'churn_risk' | 'health_score_drop' | 'behavioral' | 'scheduled'; export type CampaignChannel = 'email' | 'push' | 'in_app' | 'slack_cs'; export interface Campaign { id: string; productId: string; name: string; description: string; status: CampaignStatus; trigger: { type: CampaignTriggerType; conditions: Array<{ field: string; operator: string; value: unknown }>; }; audience: { riskSegments?: string[]; products?: string[]; userSegments?: string[]; excludeRecentContact?: number; }; messages: Array<{ channel: CampaignChannel; templateId: string; variant?: string; delayHours?: number; }>; stats: { triggered: number; sent: number; opened: number; clicked: number; converted: number; controlChurnRate: number; treatmentChurnRate: number; }; createdAt: string; updatedAt: string; } export async function listCampaigns(productId?: string): Promise { const url = productId ? `/predictive/campaigns?productId=${productId}` : '/predictive/campaigns'; return predictiveApi.fetch(url); } export async function getCampaign(id: string): Promise { return predictiveApi.fetch(`/predictive/campaigns/${id}`); } export async function createCampaign(input: { name: string; description: string; productId: string; trigger: { type: CampaignTriggerType; conditions: Array<{ field: string; operator: string; value: unknown }>; }; audience: { riskSegments?: string[]; products?: string[]; userSegments?: string[]; excludeRecentContact?: number; }; messages: Array<{ channel: CampaignChannel; templateId: string; variant?: string; delayHours?: number; }>; }): Promise { return predictiveApi.fetch('/predictive/campaigns', { method: 'POST', body: JSON.stringify(input), }); } export async function updateCampaign(id: string, updates: Partial): Promise { return predictiveApi.fetch(`/predictive/campaigns/${id}`, { method: 'PATCH', body: JSON.stringify(updates), }); } export async function getCampaignStats(id: string): Promise { return predictiveApi.fetch(`/predictive/campaigns/${id}/stats`); } export async function triggerCampaign(id: string, testUserId?: string): Promise<{ triggered: number }> { return predictiveApi.fetch<{ triggered: number }>(`/predictive/campaigns/${id}/trigger`, { method: 'POST', body: JSON.stringify(testUserId ? { testUserId } : {}), }); }