description(__('admin.ops_health.pipeline.no_snapshot_desc')) ->color('warning'), ]; } $totals = $this->summarizeAssets($snapshot['targets'] ?? []); $alerts = $snapshot['alerts'] ?? []; $snapshotAge = $this->formatSnapshotAge($snapshot['generated_at'] ?? null); $snapshotLabel = $snapshotAge ? __('admin.ops_health.snapshot_age', ['age' => $snapshotAge]) : __('admin.ops_health.snapshot_missing'); return [ Stat::make(__('admin.ops_health.pipeline.pending'), number_format($totals['pending'])) ->description($snapshotLabel) ->descriptionIcon('heroicon-m-clock') ->color($totals['pending'] > 0 ? 'warning' : 'success'), Stat::make(__('admin.ops_health.pipeline.failed'), number_format($totals['failed'])) ->description(__('admin.ops_health.pipeline.archived_hint', ['count' => number_format($totals['archived'])])) ->color($totals['failed'] > 0 ? 'danger' : 'success'), Stat::make(__('admin.ops_health.pipeline.total'), number_format($totals['total'])) ->description(__('admin.ops_health.pipeline.hot_hint', ['count' => number_format($totals['hot'])])) ->color('primary'), Stat::make(__('admin.ops_health.pipeline.alerts'), number_format(count($alerts))) ->color(count($alerts) > 0 ? 'danger' : 'success'), ]; } private function summarizeAssets(array $targets): array { $totals = [ 'total' => 0, 'pending' => 0, 'failed' => 0, 'hot' => 0, 'archived' => 0, ]; foreach ($targets as $target) { $assets = $target['assets'] ?? []; $totals['total'] += (int) ($assets['total'] ?? 0); $byStatus = $assets['by_status'] ?? []; foreach (['pending', 'failed', 'hot', 'archived'] as $status) { $totals[$status] += (int) ($byStatus[$status]['count'] ?? 0); } } return $totals; } private function formatSnapshotAge(?string $timestamp): ?string { if (! $timestamp) { return null; } try { return Carbon::parse($timestamp)->diffForHumans(); } catch (\Throwable) { return null; } } }