<?php

declare(strict_types=1);

namespace App\Framework\Queue\Commands;

use App\Framework\Console\ConsoleCommand;
use App\Framework\Console\ExitCode;
use App\Framework\Core\ValueObjects\Duration;
use App\Framework\Performance\MemoryMonitor;
use App\Framework\Queue\Services\JobCleanupService;
use App\Framework\Queue\Services\JobMemoryManager;

final readonly class JobCleanupCommands
{
    public function __construct(
        private JobCleanupService $cleanupService,
        private JobMemoryManager $memoryManager,
        private MemoryMonitor $memoryMonitor
    ) {
    }

    #[ConsoleCommand(name: 'queue:cleanup:all', description: 'Run comprehensive queue cleanup with default retention periods')]
    public function runComprehensiveCleanup(): ExitCode
    {
        echo "🧹 Starting Comprehensive Queue Cleanup\n\n";

        try {
            // Show current memory status
            $memorySummary = $this->memoryMonitor->getSummary();
            echo "💾 Memory Status:\n";
            echo "   Current: {$memorySummary->getCurrentHumanReadable()}\n";
            echo "   Available: {$memorySummary->getAvailableMemory()->toHumanReadable()}\n";
            echo "   Usage: {$memorySummary->getUsagePercentageFormatted()}\n\n";

            // Show cleanup statistics
            echo "📊 Cleanup Statistics:\n";
            $stats = $this->cleanupService->getCleanupStatistics();

            echo "   Eligible for cleanup:\n";
            echo "   • Completed jobs: " . number_format($stats['eligible_completed_jobs']) . " (>{$stats['retention_days']['completed_jobs']} days)\n";
            echo "   • Failed jobs: " . number_format($stats['eligible_failed_jobs']) . " (>{$stats['retention_days']['failed_jobs']} days)\n";
            echo "   • Job metrics: " . number_format($stats['eligible_metrics']) . " (>{$stats['retention_days']['metrics']} days)\n";
            echo "   • Dead letter jobs: " . number_format($stats['eligible_dead_letter_jobs']) . " (>{$stats['retention_days']['dead_letter_jobs']} days)\n";
            echo "   • Total eligible: " . number_format($stats['total_eligible']) . "\n";
            echo "   • Estimated time: ~{$stats['estimated_cleanup_minutes']} minutes\n\n";

            if ($stats['total_eligible'] === 0) {
                echo "✅ No data eligible for cleanup\n";

                return ExitCode::SUCCESS;
            }

            echo "🔄 Starting cleanup process...\n\n";

            // Run comprehensive cleanup
            $results = $this->cleanupService->runComprehensiveCleanup();

            // Display results
            echo "✅ Cleanup Results:\n";
            echo "   • Completed jobs deleted: " . number_format($results['completed_jobs']) . "\n";
            echo "   • Failed jobs deleted: " . number_format($results['failed_jobs']) . "\n";
            echo "   • Job metrics deleted: " . number_format($results['job_metrics']) . "\n";
            echo "   • Dead letter jobs deleted: " . number_format($results['dead_letter_jobs']) . "\n";
            echo "   • Total deleted: " . number_format($results['total_deleted']) . "\n\n";

            echo "⏱️ Performance:\n";
            echo "   • Duration: {$results['duration_seconds']} seconds\n";
            echo "   • Memory used: {$results['memory_used']}\n";
            echo "   • Peak memory: {$results['memory_peak']}\n\n";

            if (! empty($results['errors'])) {
                echo "⚠️ Errors occurred:\n";
                foreach ($results['errors'] as $error) {
                    echo "   • {$error}\n";
                }

                return ExitCode::GENERAL_ERROR;
            }

            echo "✅ Cleanup completed successfully!\n";

            return ExitCode::SUCCESS;

        } catch (\Exception $e) {
            echo "❌ Error: {$e->getMessage()}\n";

            return ExitCode::GENERAL_ERROR;
        }
    }

    #[ConsoleCommand(name: 'queue:cleanup:completed', description: 'Clean up completed jobs older than specified days')]
    public function cleanupCompletedJobs(int $days = 30): ExitCode
    {
        echo "🧹 Cleaning Completed Jobs\n\n";

        try {
            if ($days < 1) {
                echo "❌ Days must be at least 1\n";

                return ExitCode::INVALID_ARGUMENT;
            }

            echo "📊 Configuration:\n";
            echo "   • Delete completed jobs older than: {$days} days\n\n";

            $duration = Duration::fromDays($days);
            $deleted = $this->cleanupService->cleanupCompletedJobs($duration);

            echo "✅ Cleanup Results:\n";
            echo "   • Completed jobs deleted: " . number_format($deleted) . "\n";

            return ExitCode::SUCCESS;

        } catch (\Exception $e) {
            echo "❌ Error: {$e->getMessage()}\n";

            return ExitCode::GENERAL_ERROR;
        }
    }

    #[ConsoleCommand(name: 'queue:cleanup:failed', description: 'Clean up failed jobs older than specified days')]
    public function cleanupFailedJobs(int $days = 90): ExitCode
    {
        echo "🧹 Cleaning Failed Jobs\n\n";

        try {
            if ($days < 1) {
                echo "❌ Days must be at least 1\n";

                return ExitCode::INVALID_ARGUMENT;
            }

            echo "📊 Configuration:\n";
            echo "   • Delete failed jobs older than: {$days} days\n\n";

            $duration = Duration::fromDays($days);
            $deleted = $this->cleanupService->cleanupFailedJobs($duration);

            echo "✅ Cleanup Results:\n";
            echo "   • Failed jobs deleted: " . number_format($deleted) . "\n";

            return ExitCode::SUCCESS;

        } catch (\Exception $e) {
            echo "❌ Error: {$e->getMessage()}\n";

            return ExitCode::GENERAL_ERROR;
        }
    }

    #[ConsoleCommand(name: 'queue:cleanup:metrics', description: 'Clean up job metrics older than specified days')]
    public function cleanupMetrics(int $days = 180): ExitCode
    {
        echo "🧹 Cleaning Job Metrics\n\n";

        try {
            if ($days < 1) {
                echo "❌ Days must be at least 1\n";

                return ExitCode::INVALID_ARGUMENT;
            }

            echo "📊 Configuration:\n";
            echo "   • Delete metrics older than: {$days} days\n\n";

            $duration = Duration::fromDays($days);
            $deleted = $this->cleanupService->cleanupJobMetrics($duration);

            echo "✅ Cleanup Results:\n";
            echo "   • Job metrics deleted: " . number_format($deleted) . "\n";

            return ExitCode::SUCCESS;

        } catch (\Exception $e) {
            echo "❌ Error: {$e->getMessage()}\n";

            return ExitCode::GENERAL_ERROR;
        }
    }

    #[ConsoleCommand(name: 'queue:cleanup:deadletter', description: 'Clean up dead letter jobs older than specified days')]
    public function cleanupDeadLetterJobs(int $days = 365): ExitCode
    {
        echo "🧹 Cleaning Dead Letter Jobs\n\n";

        try {
            if ($days < 1) {
                echo "❌ Days must be at least 1\n";

                return ExitCode::INVALID_ARGUMENT;
            }

            echo "📊 Configuration:\n";
            echo "   • Delete dead letter jobs older than: {$days} days\n\n";

            $duration = Duration::fromDays($days);
            $deleted = $this->cleanupService->cleanupDeadLetterJobs($duration);

            echo "✅ Cleanup Results:\n";
            echo "   • Dead letter jobs deleted: " . number_format($deleted) . "\n";

            return ExitCode::SUCCESS;

        } catch (\Exception $e) {
            echo "❌ Error: {$e->getMessage()}\n";

            return ExitCode::GENERAL_ERROR;
        }
    }

    #[ConsoleCommand(name: 'queue:cleanup:stats', description: 'Show cleanup statistics without performing cleanup')]
    public function showCleanupStatistics(): ExitCode
    {
        echo "📊 Queue Cleanup Statistics\n\n";

        try {
            $stats = $this->cleanupService->getCleanupStatistics();

            echo "📋 Retention Periods:\n";
            echo "   • Completed jobs: {$stats['retention_days']['completed_jobs']} days\n";
            echo "   • Failed jobs: {$stats['retention_days']['failed_jobs']} days\n";
            echo "   • Job metrics: {$stats['retention_days']['metrics']} days\n";
            echo "   • Dead letter jobs: {$stats['retention_days']['dead_letter_jobs']} days\n\n";

            echo "🗑️ Eligible for Cleanup:\n";
            echo "   • Completed jobs: " . number_format($stats['eligible_completed_jobs']) . "\n";
            echo "   • Failed jobs: " . number_format($stats['eligible_failed_jobs']) . "\n";
            echo "   • Job metrics: " . number_format($stats['eligible_metrics']) . "\n";
            echo "   • Dead letter jobs: " . number_format($stats['eligible_dead_letter_jobs']) . "\n";
            echo "   • Total eligible: " . number_format($stats['total_eligible']) . "\n\n";

            echo "⏱️ Estimated Cleanup Time: ~{$stats['estimated_cleanup_minutes']} minutes\n\n";

            // Memory recommendations
            $recommendations = $this->memoryManager->getMemoryRecommendations();
            echo "💾 Memory Recommendations:\n";
            echo "   • Current usage: {$recommendations['current_usage']}\n";
            echo "   • Available memory: {$recommendations['available']}\n";
            echo "   • Priority: {$recommendations['priority']}\n";

            foreach ($recommendations['recommendations'] as $rec) {
                echo "\n   📌 {$rec['type']}:\n";
                echo "      {$rec['message']}\n";
                if (! empty($rec['actions'])) {
                    echo "      Actions:\n";
                    foreach ($rec['actions'] as $action) {
                        echo "      • {$action}\n";
                    }
                }
            }

            return ExitCode::SUCCESS;

        } catch (\Exception $e) {
            echo "❌ Error: {$e->getMessage()}\n";

            return ExitCode::GENERAL_ERROR;
        }
    }

    #[ConsoleCommand(name: 'queue:memory:status', description: 'Show current memory status and recommendations')]
    public function showMemoryStatus(): ExitCode
    {
        echo "💾 Queue Memory Status\n\n";

        try {
            // Get memory snapshot
            $snapshot = $this->memoryManager->getJobMemorySnapshot('memory_status_check');

            echo "📊 Current Memory Usage:\n";
            echo "   • Current: {$snapshot['current']} ({$snapshot['usage_percentage']}%)\n";
            echo "   • Peak: {$snapshot['peak']}\n";
            echo "   • Limit: {$snapshot['limit']}\n";
            echo "   • Available: {$snapshot['available']}\n";
            echo "   • Status: {$snapshot['status']}\n\n";

            // Status indicators
            if ($snapshot['is_critical']) {
                echo "🔴 CRITICAL: Memory usage is critically high!\n\n";
            } elseif ($snapshot['is_warning']) {
                echo "🟡 WARNING: Memory usage is elevated.\n\n";
            } else {
                echo "🟢 NORMAL: Memory usage is within acceptable limits.\n\n";
            }

            // Get recommendations
            $recommendations = $this->memoryManager->getMemoryRecommendations();

            echo "📌 Recommendations:\n";
            foreach ($recommendations['recommendations'] as $rec) {
                echo "\n   {$rec['type']}:\n";
                echo "   {$rec['message']}\n";
                if (! empty($rec['actions'])) {
                    echo "   Suggested actions:\n";
                    foreach ($rec['actions'] as $action) {
                        echo "   • {$action}\n";
                    }
                }
            }

            return ExitCode::SUCCESS;

        } catch (\Exception $e) {
            echo "❌ Error: {$e->getMessage()}\n";

            return ExitCode::GENERAL_ERROR;
        }
    }

    #[ConsoleCommand(name: 'queue:memory:optimize', description: 'Optimize memory for job processing')]
    public function optimizeMemory(): ExitCode
    {
        echo "🔧 Optimizing Queue Memory\n\n";

        try {
            echo "📊 Before Optimization:\n";
            $beforeSnapshot = $this->memoryManager->getJobMemorySnapshot('before_optimization');
            echo "   • Memory: {$beforeSnapshot['current']} ({$beforeSnapshot['usage_percentage']}%)\n\n";

            echo "🔄 Running optimization...\n";
            $optimization = $this->memoryManager->optimizeForJob('manual_optimization');

            echo "\n📊 After Optimization:\n";
            echo "   • Memory: {$optimization['after']}\n";
            echo "   • Freed: {$optimization['freed']}\n";
            echo "   • Usage before: {$optimization['usage_before']}\n";
            echo "   • Usage after: {$optimization['usage_after']}\n\n";

            if ($optimization['freed_bytes'] > 0) {
                echo "✅ Successfully freed {$optimization['freed']} of memory\n";
            } else {
                echo "ℹ️ No significant memory was freed (system may have already been optimized)\n";
            }

            return ExitCode::SUCCESS;

        } catch (\Exception $e) {
            echo "❌ Error: {$e->getMessage()}\n";

            return ExitCode::GENERAL_ERROR;
        }
    }
}
