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) => (
))}
);
};
// ============================================================
// 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) => (
))}
);
};
// ============================================================
// 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;