import { useEffect, useState } from 'react'; import { Rss, Activity, TrendingUp, AlertTriangle, Globe, Database, Zap, BarChart3, LineChart, Map, Target, Radar, Grid3X3, RefreshCw, Brain, Wifi, WifiOff, Download, ExternalLink } from 'lucide-react'; import { useWidgetCommunication } from '@/contexts/WidgetContext'; import { cn } from '@/lib/utils'; import { useHealthData, useHealingStatus, useHyperEvents as useBackendHyperEvents } from '@/hooks/useBackendData'; import { useLiveData, useAlerts, useHyperEvents, useSystemMetrics, useSourcesHealth } from '@/hooks/useLiveData'; import AutonomousMetricsWidget from '@/widgets/AutonomousMetricsWidget'; import SourceDiscoveryWidget from '@/widgets/SourceDiscoveryWidget'; import ApprovalQueueWidget from '@/widgets/ApprovalQueueWidget'; interface InteractiveWidgetContentProps { type: string; widgetId: string; } // ============================================================ // SOURCE RECOMMENDATION PANEL - Suggests additional data sources // ============================================================ const SourceRecommendationPanel = ({ sources, onFetch }: { sources: Array<{ id: string; name: string; description: string; isAvailable: boolean; requiresApproval: boolean }>; onFetch: (id: string) => void; }) => { if (sources.length === 0) return null; const unavailableSources = sources.filter(s => !s.isAvailable); if (unavailableSources.length === 0) return null; return (

Anbefalede kilder:

{unavailableSources.slice(0, 3).map(source => ( ))}
); }; // ============================================================ // CONNECTION STATUS INDICATOR // ============================================================ const ConnectionIndicator = ({ status }: { status: 'connected' | 'connecting' | 'disconnected' }) => (
{status === 'connected' ? ( <>Live ) : status === 'connecting' ? ( <>Connecting... ) : ( <>Offline )}
); // ============================================================ // NEWS WIDGET - Using HyperLog Events // ============================================================ const NewsWidget = ({ widgetId }: { widgetId: string }) => { const { filters, sharedData, selectThreat } = useWidgetCommunication(widgetId); const { data, isLoading, connectionStatus, recommendedSources, fetchRecommendedSource } = useHyperEvents(15000); // Transform HyperLog events into news items const newsItems = (data?.events || []) .filter((e: any) => ['THOUGHT', 'CRITICAL_DECISION', 'DELEGATION', 'threat:detected'].includes(e.type)) .slice(0, 10) .map((e: any, i: number) => ({ id: e.id || `event-${i}`, title: e.content || e.payload?.message || 'System Event', severity: e.type === 'CRITICAL_DECISION' ? 'critical' : e.type === 'threat:detected' ? 'high' : 'medium', time: formatRelativeTime(e.timestamp), region: e.metadata?.region || 'system', agent: e.agent || 'System', })); const filteredNews = newsItems.filter((item: any) => { if (filters.severity && filters.severity !== 'all' && item.severity !== filters.severity) return false; if (filters.searchQuery && !item.title.toLowerCase().includes(filters.searchQuery.toLowerCase())) return false; return true; }); if (isLoading && newsItems.length === 0) { return
Indlæser nyheder...
; } return (
{filteredNews.length === 0 ? (

Ingen nyheder matcher filtrene

) : ( filteredNews.slice(0, 4).map((item: any) => ( )) )}
); }; // ============================================================ // ALERTS WIDGET - Using Live Alerts // ============================================================ const AlertsWidget = ({ widgetId }: { widgetId: string }) => { const { filters, sharedData, selectAlert, highlightIP } = useWidgetCommunication(widgetId); const { data: liveAlerts, isLoading, connectionStatus, recommendedSources, fetchRecommendedSource } = useAlerts(10000); // Fallback to HyperLog for alerts if no dedicated alerts endpoint const { data: hyperData } = useHyperEvents(15000); // Combine and transform alerts const alerts = (liveAlerts || []).length > 0 ? liveAlerts : (hyperData?.events || []) .filter((e: any) => ['system.alert', 'security.alert', 'failure:recorded', 'failure:recurring'].includes(e.type)) .slice(0, 10) .map((e: any, i: number) => ({ id: e.id || `alert-${i}`, type: e.type === 'failure:recurring' ? 'CRITICAL' : e.type === 'security.alert' ? 'WARNING' : 'INFO', msg: e.content || e.payload?.message || 'Alert', time: formatRelativeTime(e.timestamp), ip: e.metadata?.ip || e.payload?.sourceId || null, severity: e.type.includes('failure') ? 'critical' : 'medium', })); const filteredAlerts = alerts.filter((a: any) => { if (filters.severity && filters.severity !== 'all') { const severityMap: Record = { CRITICAL: 'critical', WARNING: 'high', INFO: 'medium' }; if (severityMap[a.type] !== filters.severity) return false; } if (filters.searchQuery && !a.msg.toLowerCase().includes(filters.searchQuery.toLowerCase())) return false; return true; }); if (isLoading && alerts.length === 0) { return
Indlæser alerts...
; } return (
{filteredAlerts.length === 0 ? (

Ingen aktive alerts

) : ( filteredAlerts.slice(0, 5).map((a: any) => ( )) )}
); }; // ============================================================ // EVENTS WIDGET - Using Live HyperLog // ============================================================ const EventsWidget = ({ widgetId }: { widgetId: string }) => { const { sharedData, highlightIP } = useWidgetCommunication(widgetId); const { data, connectionStatus } = useHyperEvents(10000); const events = (data?.events || []).slice(0, 8).map((e: any) => ({ type: e.type?.split('.')[0]?.toUpperCase().slice(0, 4) || 'SYS', msg: e.content || e.payload?.message || 'Event', ip: e.metadata?.ip || null, })); return (
{events.length === 0 ? (

Ingen events...

) : ( events.map((e: any, i: number) => ( )) )}
); }; // ============================================================ // METRICS WIDGET - Using System Metrics // ============================================================ const MetricsWidget = ({ widgetId }: { widgetId: string }) => { const { filters, sharedData } = useWidgetCommunication(widgetId); const { data, connectionStatus, recommendedSources, fetchRecommendedSource } = useSystemMetrics(15000); const { data: statsData } = useLiveData({ sourceType: 'autonomousStats', pollInterval: 30000 }); // Combine system metrics with autonomous stats const metrics = [ { label: "Decisions", value: statsData?.totalDecisions || statsData?.decisions?.total || 0, change: `${((statsData?.successRate || 0) * 100).toFixed(0)}%` }, { label: "Patterns", value: statsData?.patternsLearned || statsData?.patterns?.total || 0, change: "+∞" }, { label: "CPU", value: `${data?.cpu || 0}%`, change: "" }, { label: "Memory", value: `${data?.memory || 0}%`, change: "" }, ]; return (
{metrics.map((m, i) => (
{m.value}
{m.label}
{m.change &&
{m.change}
}
))}
); }; // ============================================================ // GLOBAL WIDGET - Region Threats (Knowledge Graph) // ============================================================ const GlobalWidget = ({ widgetId }: { widgetId: string }) => { const { filters, sharedData, selectRegion } = useWidgetCommunication(widgetId); const { data, connectionStatus, recommendedSources, fetchRecommendedSource } = useLiveData({ sourceType: 'knowledge', pollInterval: 60000, transform: (raw) => raw.compiled?.insights || raw.insights || [] }); // Transform knowledge insights into regional threat data const regions = [ { id: "north-america", name: "North America", threats: 0, up: true }, { id: "europe", name: "Europe", threats: 0, up: false }, { id: "asia-pacific", name: "Asia Pacific", threats: 0, up: true }, { id: "middle-east", name: "Middle East", threats: 0, up: false }, ].map(r => ({ ...r, threats: Math.floor(Math.random() * 200) + 50, // Placeholder - connect to real geo data })); const filteredRegions = regions.filter(r => { if (filters.region && r.id !== filters.region) return false; return true; }); return (
{filteredRegions.map((r) => ( ))}
); }; // ============================================================ // DATA STREAMS WIDGET - Using Sources Health // ============================================================ const DataStreamsWidget = ({ widgetId }: { widgetId: string }) => { const { sharedData } = useWidgetCommunication(widgetId); const { data: sources, connectionStatus } = useSourcesHealth(15000); const streams = (sources || []).slice(0, 5).map((s: any) => ({ name: s.name || 'Unknown', rate: s.latency ? `${s.latency}ms` : 'N/A', ok: s.healthy !== false, })); // Fallback if no sources if (streams.length === 0) { streams.push( { name: "Database", rate: "12ms", ok: true }, { name: "MCP Tools", rate: "45ms", ok: true }, { name: "Agent Pipeline", rate: "89ms", ok: !sharedData.activeAlert } ); } return (
{streams.map((s: any, i: number) => (
{s.name}
{s.rate}
))}
); }; // ============================================================ // STATISTICS WIDGET // ============================================================ const StatisticsWidget = ({ widgetId }: { widgetId: string }) => { const { filters } = useWidgetCommunication(widgetId); const { data } = useLiveData({ sourceType: 'autonomousStats', pollInterval: 30000 }); const severityFilter = filters.severity; const stats = [ { label: "Success Rate", value: ((data?.successRate || 0.85) * 100).toFixed(0) }, { label: "Pattern Match", value: Math.min(((data?.patternsLearned || 50) / 100) * 100, 100).toFixed(0) }, { label: "Source Health", value: ((data?.healthySources || 4) / (data?.totalSources || 5) * 100).toFixed(0) }, ]; return (
{stats.map((s, i) => (
{s.label} {s.value}%
))}
); }; // ============================================================ // TRENDS WIDGET // ============================================================ const TrendsWidget = () => { const { data } = useLiveData({ sourceType: 'decisionHistory', pollInterval: 60000 }); // Generate trend data from decisions const decisions = data || []; const trendData = [20, 35, 45, 80, 65, 90, 70].map((base, i) => { const decision = decisions[i]; return decision?.success ? base + 10 : base; }); return (
{trendData.map((v, i) => (
))}
); }; // ============================================================ // THREAT MAP WIDGET // ============================================================ const ThreatMapWidget = ({ widgetId }: { widgetId: string }) => { const { sharedData } = useWidgetCommunication(widgetId); return (
{[ { x: 20, y: 30, region: "north-america" }, { x: 45, y: 25, region: "europe" }, { x: 70, y: 40, region: "asia-pacific" }, ].map((p, i) => (
))}
); }; // ============================================================ // DATABASE WIDGET - Real Backend Data // ============================================================ const DatabaseWidget = () => { const { data: healthData, isLoading, refresh } = useHealthData(10000); const { data: healingData } = useHealingStatus(15000); const databases = healthData?.services ? Object.entries(healthData.services).map(([name, info]: [string, any]) => ({ name: name.charAt(0).toUpperCase() + name.slice(1).replace(/_/g, ' '), status: info.healthy ? 'online' : 'offline', latency: info.latency })) : [ { name: "Backend", status: healthData?.status === 'healthy' ? 'online' : 'checking', latency: undefined } ]; return (
Live Backend Status
{databases.map((db: any, i: number) => (
{db.name}
{db.latency && {db.latency}ms} {db.status}
))} {healingData && (
Self-Healing: {healingData.healthy ? 'Active' : 'Issues detected'}
)}
); }; // ============================================================ // SIMPLE WIDGETS (Visual indicators) // ============================================================ const TargetWidget = () => (
{[100, 75, 50, 25].map((size, i) => (
))}
); const RadarWidget = () => (
{[100, 66, 33].map((size, i) => (
))}
); const GridWidget = () => { const { data } = useSourcesHealth(30000); const sources = data || []; // Generate grid based on source health const grid = Array.from({ length: 16 }).map((_, i) => { const source = sources[i % sources.length]; return source ? source.healthy !== false : Math.random() > 0.75; }); return (
{grid.map((active, i) => (
))}
); }; // ============================================================ // HELPER FUNCTIONS // ============================================================ function formatRelativeTime(timestamp: number | string): string { const now = Date.now(); const ts = typeof timestamp === 'string' ? new Date(timestamp).getTime() : timestamp; const diff = now - ts; if (diff < 60000) return 'Nu'; if (diff < 3600000) return `${Math.floor(diff / 60000)}m`; if (diff < 86400000) return `${Math.floor(diff / 3600000)}t`; return `${Math.floor(diff / 86400000)}d`; } // ============================================================ // MAIN COMPONENT // ============================================================ const InteractiveWidgetContent = ({ type, widgetId }: InteractiveWidgetContentProps) => { const widgets: Record = { news: , datastreams: , metrics: , alerts: , global: , database: , events: , statistics: , trends: , threatmap: , target: , radar: , grid: , 'autonomous-metrics': , 'source-discovery': , 'approval-queue': , }; return widgets[type] ||
Widget not found
; }; export default InteractiveWidgetContent;