info('Summary Generation Status'); $this->info('========================'); $this->newLine(); $this->displayOverallStatistics(); $this->newLine(); if ($this->option('detailed')) { $this->displayDetailedBreakdown(); $this->newLine(); } $this->displayRecentActivity(); $this->newLine(); $this->displayQueueStatus(); return self::SUCCESS; } /** * Display overall statistics. */ protected function displayOverallStatistics(): void { $totalBooks = Book::count(); $gutendexBooks = Book::gutendex()->count(); $booksWithText = Book::whereNotNull('full_text_url')->count(); $totalSummaries = Summary::count(); $completedSummaries = Summary::completed()->count(); $pendingSummaries = Summary::pending()->count(); $processingSummaries = Summary::processing()->count(); $failedSummaries = Summary::failed()->count(); $booksWithoutSummaries = Book::gutendex() ->whereNotNull('full_text_url') ->doesntHave('summary') ->count(); $completionRate = $totalSummaries > 0 ? round(($completedSummaries / $totalSummaries) * 100, 2) : 0; $this->table( ['Metric', 'Count', 'Percentage'], [ ['Total Books', number_format($totalBooks), '-'], ['Gutendex Books', number_format($gutendexBooks), round(($gutendexBooks / max($totalBooks, 1)) * 100, 1) . '%'], ['Books with Full Text', number_format($booksWithText), '-'], ['Books without Summaries', number_format($booksWithoutSummaries), '-'], ['---', '---', '---'], ['Total Summaries', number_format($totalSummaries), '-'], ['✓ Completed', number_format($completedSummaries), $completionRate . '%'], ['⏳ Pending', number_format($pendingSummaries), round(($pendingSummaries / max($totalSummaries, 1)) * 100, 1) . '%'], ['⚙ Processing', number_format($processingSummaries), round(($processingSummaries / max($totalSummaries, 1)) * 100, 1) . '%'], ['✗ Failed', number_format($failedSummaries), round(($failedSummaries / max($totalSummaries, 1)) * 100, 1) . '%'], ] ); } /** * Display detailed breakdown by model and category. */ protected function displayDetailedBreakdown(): void { $this->info('Detailed Breakdown'); $this->info('------------------'); $this->newLine(); // By model $byModel = Summary::completed() ->select('model_used', DB::raw('COUNT(*) as count')) ->groupBy('model_used') ->get(); if ($byModel->isNotEmpty()) { $this->info('Summaries by Model:'); $this->table( ['Model', 'Count'], $byModel->map(fn($item) => [ $item->model_used ?? 'Unknown', number_format($item->count), ])->toArray() ); $this->newLine(); } // By language $byLanguage = Book::gutendex() ->select('language', DB::raw('COUNT(*) as count')) ->whereNotNull('language') ->groupBy('language') ->orderByDesc('count') ->limit(10) ->get(); if ($byLanguage->isNotEmpty()) { $this->info('Books by Language (Top 10):'); $this->table( ['Language', 'Count'], $byLanguage->map(fn($item) => [ $item->language, number_format($item->count), ])->toArray() ); $this->newLine(); } } /** * Display recent activity. */ protected function displayRecentActivity(): void { $recentCount = (int) $this->option('recent'); $this->info("Recent Activity (Last {$recentCount})"); $this->info('------------------'); $this->newLine(); // Recent completed summaries $recentCompleted = Summary::completed() ->with('book') ->orderByDesc('processed_at') ->limit($recentCount) ->get(); if ($recentCompleted->isNotEmpty()) { $this->info('✓ Recently Completed:'); $this->table( ['Book ID', 'Title', 'Processed At', 'Model'], $recentCompleted->map(fn($s) => [ $s->book_id, substr($s->book?->title ?? 'Unknown', 0, 40), $s->processed_at?->diffForHumans() ?? 'N/A', $s->model_used ?? 'N/A', ])->toArray() ); $this->newLine(); } // Recent failures $recentFailed = Summary::failed() ->with('book') ->orderByDesc('updated_at') ->limit($recentCount) ->get(); if ($recentFailed->isNotEmpty()) { $this->warn('✗ Recent Failures:'); $this->table( ['Book ID', 'Title', 'Error'], $recentFailed->map(fn($s) => [ $s->book_id, substr($s->book?->title ?? 'Unknown', 0, 30), substr($s->processing_error ?? 'Unknown error', 0, 60), ])->toArray() ); $this->newLine(); } } /** * Display queue status. */ protected function displayQueueStatus(): void { $this->info('Queue Status'); $this->info('------------'); $this->newLine(); // Count pending jobs (if using database queue) try { $pendingJobs = DB::table('jobs')->count(); $failedJobs = DB::table('failed_jobs')->count(); $this->table( ['Queue', 'Count'], [ ['Pending Jobs', number_format($pendingJobs)], ['Failed Jobs', number_format($failedJobs)], ] ); if ($pendingJobs > 0) { $this->comment('Run the queue worker: php artisan queue:work'); } if ($failedJobs > 0) { $this->warn("You have {$failedJobs} failed jobs. Review with: php artisan queue:failed"); } } catch (\Exception $e) { $this->comment('Queue status unavailable (database driver not configured).'); } } }