import React from "react"; import { Document, Page, Text, View } from "@react-pdf/renderer"; import { sharedStyles } from "./sharedPdfStyles"; interface AgentPdfDocumentProps { data: any; agentLabel: string; agentUuid: string; reportDateStr: string; } interface TableColumn { header: string; width: string; align?: "center" | "right" | "left"; cell: (row: any) => string | number; } function formatBytes(bytes: number): string { if (!bytes || bytes === 0) return "0 B"; const k = 1000; const sizes = ["B", "KB", "MB", "GB", "TB"]; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i]; } function formatIndonesiaTime(dateStr: string | Date): string { if (!dateStr) return "Never"; try { const d = new Date(dateStr); return d.toLocaleString("id-ID", { timeZone: "Asia/Jakarta", day: "2-digit", month: "2-digit", year: "numeric", hour: "2-digit", minute: "2-digit", second: "2-digit", }) + " WIB"; } catch (e) { return String(dateStr); } } function RenderPdfTable({ title, columns, data }: { title: string; columns: TableColumn[]; data: any[] }) { return ( {title} {columns.map((col, idx) => ( {col.header} ))} {data.length === 0 ? ( No Data ) : ( data.map((row, rowIdx) => ( {columns.map((col, colIdx) => ( {col.cell(row)} ))} )) )} ); } export default function AgentPdfDocument({ data, agentLabel, agentUuid, reportDateStr, }: AgentPdfDocumentProps) { const summary = data.summary || {}; // Sort by total bandwidth (download + upload) descending for PDF export const sortByBandwidth = (arr: any[]) => [...arr].sort((a, b) => ((b.download ?? b.bytes_download ?? 0) + (b.upload ?? b.bytes_upload ?? 0)) - ((a.download ?? a.bytes_download ?? 0) + (a.upload ?? a.bytes_upload ?? 0)) ); const devices = sortByBandwidth(data.devices || []).slice(0, 50); const flows = sortByBandwidth(data.flows || []).slice(0, 50); const topApps = sortByBandwidth(data.top_apps || []).slice(0, 50); const macBw = sortByBandwidth(data.mac_bandwidth || []).slice(0, 50); // Security alerts: not sorted by bandwidth — keep original order const insecure = (data.security?.insecure_protocols || []).slice(0, 50); const reputation = (data.security?.ip_reputation || []).slice(0, 50); const events = (data.events || []).slice(0, 50); return ( {/* Header */} Deep Package Inspection Security & Traffic Analytics Dashboard Network Agent Report Generated at: {reportDateStr} {/* Agent Info */} Agent Identification Agent Name {agentLabel || "N/A"} Agent UUID {agentUuid || "N/A"} Active Devices {summary.total_devices ?? 0} Active Flows {summary.active_flows ?? 0} {/* Bandwidth Usage */} Bandwidth Metrics TOTAL DOWNLOAD {formatBytes(summary.bandwidth_down)} TOTAL UPLOAD {formatBytes(summary.bandwidth_up)} {/* Top Apps */} r.app_label || "Unknown" }, { header: "Category", width: "20%", cell: (r) => r.category || "—" }, { header: "Download", width: "20%", align: "right", cell: (r) => formatBytes(r.download) }, { header: "Upload", width: "20%", align: "right", cell: (r) => formatBytes(r.upload) }, ]} /> {/* Monitored Devices */} r.ip_address || "N/A" }, { header: "OS / Manufacturer", width: "28%", cell: (r) => r.os_label || r.manufacturer || "Unknown" }, { header: "Download", width: "15%", align: "right", cell: (r) => formatBytes(r.download) }, { header: "Upload", width: "15%", align: "right", cell: (r) => formatBytes(r.upload) }, { header: "Last Seen", width: "20%", cell: (r) => r.last_seen ? formatIndonesiaTime(r.last_seen) : "Never" }, ]} /> {/* Recent Network Flows */} r.src_ip || "—" }, { header: "Destination IP", width: "20%", cell: (r) => r.dst_ip || "—" }, { header: "Port", width: "10%", align: "center", cell: (r) => r.dst_port || "—" }, { header: "App / Protocol", width: "20%", cell: (r) => r.app_label || r.protocol || "Unknown" }, { header: "Download", width: "15%", align: "right", cell: (r) => formatBytes(r.download) }, { header: "Upload", width: "15%", align: "right", cell: (r) => formatBytes(r.upload) }, ]} /> {/* Insecure Protocols */} r.ip_address || "—" }, { header: "Protocol", width: "15%", cell: (r) => r.protocol || "—" }, { header: "Risk Level", width: "15%", cell: (r) => r.risk || "—" }, { header: "Destination", width: "25%", cell: (r) => r.dst_ip ? `${r.dst_ip}:${r.dst_port ?? ""}` : "—" }, { header: "Bytes Traced", width: "20%", align: "right", cell: (r) => formatBytes((r.download ?? 0) + (r.upload ?? 0)) }, ]} /> {/* IP Reputation Log */} r.ip_address || "—" }, { header: "Local IP", width: "30%", cell: (r) => r.local_ip || "—" }, { header: "Reputation", width: "20%", cell: (r) => r.reputation || "—" }, { header: "Risk Score", width: "20%", align: "right", cell: (r) => r.score ?? "—" }, ]} /> {/* Security Events */} r.event_type || "—" }, { header: "Severity", width: "15%", align: "center", cell: (r) => r.severity || "—" }, { header: "IP Address", width: "20%", cell: (r) => r.ip_address || "—" }, { header: "Description", width: "25%", cell: (r) => r.description || "—" }, { header: "Event Time", width: "20%", cell: (r) => r.event_at ? formatIndonesiaTime(r.event_at) : "—" }, ]} /> {/* MAC Bandwidth */} r.mac_address || "—" }, { header: "Manufacturer", width: "30%", cell: (r) => r.manufacturer || "Unknown" }, { header: "Download", width: "20%", align: "right", cell: (r) => formatBytes(r.download) }, { header: "Upload", width: "20%", align: "right", cell: (r) => formatBytes(r.upload) }, ]} /> ); }