import React, { useState, useEffect } from 'react'; import { motion } from 'framer-motion'; import { useUserStore } from '@/store/userStore'; import { useLiveStore } from '@/store/liveStore'; import apiService from '@/services/api'; import SimulatorKPICard from './SimulatorKPICard'; import SimulatorChart from './SimulatorChart'; import ScenarioCard from './ScenarioCard'; import VariableControl from './VariableControl'; import { Target, DollarSign, TrendingUp, ShieldCheck, BarChart3, RefreshCcw, Zap, ArrowRight, Download, Maximize2, Sparkles, Brain, Sliders, Activity, FileText } from 'lucide-react'; import { ResponsiveContainer, PieChart as RPieChart, Pie, Cell, Tooltip, } from 'recharts'; interface OverviewTabProps { onRunSimulation?: (variables: Record) => void; onTabChange?: (tab: string) => void; } const OverviewTab: React.FC = ({ onRunSimulation, onTabChange }) => { const { isDark } = useUserStore(); const { getSimulatorCache, setSimulatorCache } = useLiveStore(); const [overview, setOverview] = useState(null); const [variables, setVariables] = useState([]); const [values, setValues] = useState>({}); const [autoUpdate, setAutoUpdate] = useState(true); const [simResult, setSimResult] = useState(null); const [loading, setLoading] = useState(true); const [simulating, setSimulating] = useState(false); const [importance, setImportance] = useState(null); const [suggestedScenarios, setSuggestedScenarios] = useState([]); useEffect(() => { const fetchAll = async () => { setLoading(true); try { const [ovRes, varRes, impRes, sugRes] = await Promise.allSettled([ apiService.getSimulatorOverview(), apiService.getSimulatorVariables(), apiService.getFeatureImportance(), apiService.getSuggestedScenarios(), ]); let ovData = null, varsData = [], impData = null, sugData = []; let initValues: Record = {}; if (ovRes.status === 'fulfilled') ovData = ovRes.value.data; if (varRes.status === 'fulfilled' && varRes.value.data) { varsData = varRes.value.data; varsData.forEach((v: any) => { initValues[v.name || v.display_name] = v.current_value; }); } if (impRes.status === 'fulfilled') impData = impRes.value.data; if (sugRes.status === 'fulfilled') sugData = sugRes.value.data?.scenarios || []; setOverview(ovData); setVariables(varsData); setValues(initValues); setImportance(impData); setSuggestedScenarios(sugData); if (Object.keys(initValues).length > 0) { try { const runRes = await apiService.runSimulation(initValues); setSimResult(runRes.data); setSimulatorCache('overview_bundle', { overview: ovData, variables: varsData, values: initValues, importance: impData, suggestedScenarios: sugData, simResult: runRes.data, }); } catch {} } } catch (err) { console.error('Overview fetch error:', err); } finally { setLoading(false); } }; fetchAll(); }, []); const handleSimulate = async (customValues?: Record) => { const targetVals = customValues || values; if (Object.keys(targetVals).length === 0) return; setSimulating(true); try { const res = await apiService.runSimulation(targetVals); setSimResult(res.data); setSimulatorCache('overview_bundle', { overview, variables, values: targetVals, importance, suggestedScenarios, simResult: res.data, }); } catch (err) { console.error('Simulation error:', err); } finally { setSimulating(false); } }; const handleVariableChange = (name: string, val: any) => { const nextVals = { ...values, [name]: val }; setValues(nextVals); if (autoUpdate) { clearTimeout((window as any).__simTimer); (window as any).__simTimer = setTimeout(() => { handleSimulate(nextVals); }, 500); } }; const handleReset = () => { const init: Record = {}; variables.forEach((v: any) => { init[v.name || v.display_name] = v.current_value; }); setValues(init); if (autoUpdate) setTimeout(() => handleSimulate(init), 100); }; const cardBg = isDark ? 'rgba(255,255,255,0.03)' : '#ffffff'; const cardBorder = isDark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.06)'; const textPrimary = isDark ? '#f8fafc' : '#0f172a'; const textMuted = isDark ? '#94a3b8' : '#64748b'; if (loading) { return (
); } if (variables.length === 0) { return (

No Simulation Data Available

Upload a dataset in the Data Hub and train a model to start running simulations. The simulator uses your dataset columns as variables you can adjust.

{onTabChange && ( )}
); } const kpis = overview?.kpis || {}; const modelInfo = overview?.model_info || {}; const targetName = simResult?.target_name || modelInfo.target_name || modelInfo.target_column || 'Target Metric'; const summaryData = overview?.simulation_summary || { total: 0, completed: 0, running: 0, failed: 0 }; const pieData = [ { name: 'Completed', value: summaryData.completed, color: '#6366f1' }, { name: 'Running', value: summaryData.running, color: '#22c55e' }, { name: 'Failed', value: summaryData.failed, color: '#ef4444' }, ]; return (
{/* KPI Row */}
= 0 ? 'up' : 'down'} icon={} accent="#6366f1" /> } accent="#10b981" /> } accent="#f59e0b" /> } accent="#22c55e" /> } accent="#8b5cf6" />
{/* Main Grid: Variables | Chart | Insights */}
{/* Input Variables */}

Input Variables

{variables.slice(0, 8).map((v: any) => ( handleVariableChange(v.name, val)} minValue={v.min_value} maxValue={v.max_value} step={v.step} unit={v.unit} options={v.options} description={v.description} /> ))}
{/* Target Metric Forecast Chart */}

Target Metric Forecast ({targetName})

{simResult?.chart_data ? ( ) : (

Run a simulation to see forecast

)} {/* Forecast Summary Row */} {simResult && (

Expected Target

{simResult.formatted_prediction}

Baseline Target

{simResult.formatted_baseline}

Best Case

{simResult.chart_data?.[simResult.chart_data.length - 1]?.best_case?.toLocaleString() || simResult.formatted_prediction}

Worst Case

{simResult.chart_data?.[simResult.chart_data.length - 1]?.worst_case?.toLocaleString() || simResult.formatted_baseline}

)}
{/* AI Business Insights */}

AI Business Insights

{/* Key Insight */} {simResult?.insights?.summary && (

💡 Key Insight

{simResult.insights.summary}

)} {/* Positive Drivers */}

Top Positive Drivers

{(simResult?.insights?.positive_drivers || []).length > 0 ? ( (simResult.insights.positive_drivers).slice(0, 4).map((d: any, i: number) => (
{d.feature}
+{Math.abs(d.impact).toFixed(1)}%
)) ) : (

Adjust variable sliders to test positive drivers

)}
{/* Negative Drivers */}

Top Negative Drivers

{(simResult?.insights?.negative_drivers || []).length > 0 ? ( (simResult.insights.negative_drivers).slice(0, 4).map((d: any, i: number) => (
{d.feature}
{d.impact.toFixed(1)}%
)) ) : (

Adjust variable sliders to test negative drivers

)}
{/* AI Suggested Scenarios + Variable Importance */}
{/* AI Suggested Scenarios */}

AI Suggested Scenarios

{suggestedScenarios.slice(0, 4).map((s: any) => ( {}} /> ))}
{/* Variable Importance */}

Variable Importance

SHAP Method
{(importance?.features || []).slice(0, 7).map((f: any, i: number) => (
{f.feature}
{Math.abs(f.importance).toFixed(3)}
))}
{/* Bottom Row: Recent Simulations | Simulation Summary | Quick Actions */}
{/* Recent Simulations */}

Recent Simulations

{['Scenario Name', 'Created By', 'Target Metric', 'Change', 'Status'].map((h) => ( ))} {(overview?.recent_simulations || []).slice(0, 4).map((sim: any, i: number) => ( ))}
{h}
{sim.name} {sim.created_by || 'You'} {sim.prediction ? sim.prediction.toLocaleString() : (sim.target_metric || 'N/A')} = 0 ? 'text-emerald-500' : 'text-red-500'}`}> {(sim.impact || 0) >= 0 ? '↑' : '↓'} {Math.abs(sim.impact || 0).toFixed(1)}% {sim.status || 'Completed'}
{/* Simulation Summary Donut */}

Simulation Summary

{pieData.map((entry, i) => ( ))}
{summaryData.total.toLocaleString()} Total Simulations
{pieData.map((d, i) => (
{d.name}
{d.value.toLocaleString()}
))}
{/* Quick Actions */}

Quick Actions

{[ { icon: , label: 'Scenario Sandbox', action: 'builder', color: '#6366f1' }, { icon: , label: 'Forecast Timeline', action: 'forecast', color: '#10b981' }, { icon: , label: 'AI Insights', action: 'ai-insights', color: '#f59e0b' }, { icon: , label: 'AI Scenarios', action: 'ai-suggested', color: '#ef4444' }, { icon: , label: 'Optimize Goals', action: 'optimization', color: '#8b5cf6' }, { icon: , label: 'Generate Report', action: 'reports', color: '#ec4899' }, ].map((act, i) => ( ))}
); }; export default OverviewTab;