<?php

declare(strict_types=1);

namespace App\Framework\Console\Commands;

use App\Framework\Console\CommandGroup;
use App\Framework\Console\ConsoleColor;
use App\Framework\Console\ConsoleCommand;
use App\Framework\Console\ConsoleInput;
use App\Framework\Console\ConsoleOutputInterface;
use App\Framework\Console\ExitCode;
use App\Framework\Performance\Contracts\PerformanceCollectorInterface;
use App\Framework\Performance\PerformanceCategory;

#[CommandGroup(
    name: 'Performance',
    description: 'Console performance monitoring and analysis commands',
    icon: '📊',
    priority: 80
)]
final readonly class PerformanceStatsCommand
{
    public function __construct(
        private PerformanceCollectorInterface $performanceCollector
    ) {
    }

    #[ConsoleCommand('perf:console', 'Show console command performance statistics')]
    public function showConsoleStats(ConsoleInput $input, ConsoleOutputInterface $output): ExitCode
    {
        $output->writeLine('📊 Console Performance Statistics', ConsoleColor::BRIGHT_CYAN);
        $output->newLine();

        $consoleMetrics = $this->performanceCollector->getMetrics(PerformanceCategory::CONSOLE);

        if (empty($consoleMetrics)) {
            $output->writeLine('No console performance metrics available.', ConsoleColor::YELLOW);
            $output->writeLine('Performance monitoring may not be enabled or no commands have been executed yet.', ConsoleColor::GRAY);

            return ExitCode::SUCCESS;
        }

        $this->displayPerformanceSummary($output, $consoleMetrics);
        $output->newLine();
        $this->displayCommandBreakdown($output, $consoleMetrics);
        $output->newLine();
        $this->displayMemoryUsage($output, $consoleMetrics);
        $output->newLine();
        $this->displayErrorStats($output, $consoleMetrics);

        return ExitCode::SUCCESS;
    }

    #[ConsoleCommand('perf:console:clear', 'Clear console performance metrics')]
    public function clearConsoleStats(ConsoleInput $input, ConsoleOutputInterface $output): ExitCode
    {
        $output->writeLine('🧹 Clearing Console Performance Metrics', ConsoleColor::BRIGHT_YELLOW);
        $output->newLine();

        $consoleMetrics = $this->performanceCollector->getMetrics(PerformanceCategory::CONSOLE);
        $metricsCount = count($consoleMetrics);

        // Clear console-specific metrics
        foreach ($consoleMetrics as $metric) {
            // Note: Actual clearing would depend on the performance collector implementation
            // This is a demonstration of the interface
        }

        $output->writeLine("✅ Cleared {$metricsCount} console performance metrics", ConsoleColor::GREEN);

        return ExitCode::SUCCESS;
    }

    #[ConsoleCommand('perf:console:export', 'Export console performance metrics to JSON')]
    public function exportConsoleStats(string $filename = 'console-performance.json'): ExitCode
    {
        $consoleMetrics = $this->performanceCollector->getMetrics(PerformanceCategory::CONSOLE);

        $exportData = [
            'timestamp' => date('c'),
            'total_metrics' => count($consoleMetrics),
            'metrics' => array_map(fn ($metric) => $metric->toArray(), $consoleMetrics),
            'summary' => $this->generateSummaryData($consoleMetrics),
        ];

        file_put_contents($filename, json_encode($exportData, JSON_PRETTY_PRINT));

        return ExitCode::SUCCESS;
    }

    private function displayPerformanceSummary(ConsoleOutputInterface $output, array $metrics): void
    {
        $summary = $this->generateSummaryData($metrics);

        $output->writeLine('🎯 Performance Summary', ConsoleColor::BRIGHT_WHITE);
        $output->writeLine('─────────────────────', ConsoleColor::GRAY);

        $output->writeLine(sprintf('Total Commands Executed: %d', $summary['total_executions']), ConsoleColor::WHITE);
        $output->writeLine(
            sprintf('Success Rate: %.1f%%', $summary['success_rate']),
            $summary['success_rate'] >= 95 ? ConsoleColor::GREEN :
            ($summary['success_rate'] >= 85 ? ConsoleColor::YELLOW : ConsoleColor::RED)
        );
        $output->writeLine(sprintf('Average Execution Time: %.2fms', $summary['average_duration']), ConsoleColor::WHITE);
        $output->writeLine(sprintf('Average Memory Usage: %.2fMB', $summary['average_memory']), ConsoleColor::WHITE);
    }

    private function displayCommandBreakdown(ConsoleOutputInterface $output, array $metrics): void
    {
        $output->writeLine('📋 Command Usage Breakdown', ConsoleColor::BRIGHT_WHITE);
        $output->writeLine('─────────────────────────', ConsoleColor::GRAY);

        $commandStats = $this->getCommandStats($metrics);

        if (empty($commandStats)) {
            $output->writeLine('No command statistics available.', ConsoleColor::GRAY);

            return;
        }

        // Sort by execution count
        arsort($commandStats);

        foreach (array_slice($commandStats, 0, 10) as $command => $count) {
            $output->writeLine(sprintf('  %s: %d executions', $command, $count), ConsoleColor::WHITE);
        }

        if (count($commandStats) > 10) {
            $output->writeLine(sprintf('  ... and %d more commands', count($commandStats) - 10), ConsoleColor::GRAY);
        }
    }

    private function displayMemoryUsage(ConsoleOutputInterface $output, array $metrics): void
    {
        $output->writeLine('💾 Memory Usage Analysis', ConsoleColor::BRIGHT_WHITE);
        $output->writeLine('───────────────────────', ConsoleColor::GRAY);

        $memoryMetrics = array_filter($metrics, fn ($metric) => str_contains($metric->getKey(), 'memory'));

        if (empty($memoryMetrics)) {
            $output->writeLine('No memory usage data available.', ConsoleColor::GRAY);

            return;
        }

        $totalMemory = 0;
        $peakMemory = 0;
        $count = 0;

        foreach ($memoryMetrics as $metric) {
            if (str_contains($metric->getKey(), 'memory_usage')) {
                $totalMemory += $metric->getValue();
                $count++;
            } elseif (str_contains($metric->getKey(), 'peak_memory')) {
                $peakMemory = max($peakMemory, $metric->getValue());
            }
        }

        if ($count > 0) {
            $averageMemory = $totalMemory / $count;
            $output->writeLine(sprintf('Average Memory Usage: %.2f MB', $averageMemory), ConsoleColor::WHITE);
        }

        if ($peakMemory > 0) {
            $output->writeLine(
                sprintf('Peak Memory Usage: %.2f MB', $peakMemory),
                $peakMemory > 100 ? ConsoleColor::RED : ($peakMemory > 50 ? ConsoleColor::YELLOW : ConsoleColor::GREEN)
            );
        }
    }

    private function displayErrorStats(ConsoleOutputInterface $output, array $metrics): void
    {
        $output->writeLine('❌ Error Statistics', ConsoleColor::BRIGHT_WHITE);
        $output->writeLine('─────────────────', ConsoleColor::GRAY);

        $errorMetrics = array_filter($metrics, fn ($metric) => str_contains($metric->getKey(), 'error'));

        if (empty($errorMetrics)) {
            $output->writeLine('No errors recorded! 🎉', ConsoleColor::GREEN);

            return;
        }

        $errorsByType = [];
        $totalErrors = 0;

        foreach ($errorMetrics as $metric) {
            $context = $metric->getContext();
            $errorType = $context['error_type'] ?? 'Unknown';
            $errorsByType[$errorType] = ($errorsByType[$errorType] ?? 0) + $metric->getValue();
            $totalErrors += $metric->getValue();
        }

        $output->writeLine(
            sprintf('Total Errors: %d', $totalErrors),
            $totalErrors > 0 ? ConsoleColor::RED : ConsoleColor::GREEN
        );

        if (! empty($errorsByType)) {
            $output->writeLine('Error Types:', ConsoleColor::WHITE);
            foreach ($errorsByType as $type => $count) {
                $output->writeLine(sprintf('  %s: %d', $type, $count), ConsoleColor::RED);
            }
        }
    }

    private function generateSummaryData(array $metrics): array
    {
        $totalExecutions = 0;
        $totalErrors = 0;
        $totalDuration = 0;
        $totalMemory = 0;
        $durationCount = 0;
        $memoryCount = 0;

        foreach ($metrics as $metric) {
            $key = $metric->getKey();

            if (str_contains($key, '_executions')) {
                $totalExecutions += $metric->getValue();
            } elseif (str_contains($key, '_error')) {
                $totalErrors += $metric->getValue();
            } elseif (str_contains($key, 'console_command_') && ! str_contains($key, '_')) {
                $totalDuration += $metric->getTotalDuration();
                $durationCount++;
            } elseif (str_contains($key, 'memory_usage')) {
                $totalMemory += $metric->getValue();
                $memoryCount++;
            }
        }

        return [
            'total_executions' => $totalExecutions,
            'total_errors' => $totalErrors,
            'success_rate' => $totalExecutions > 0 ? (($totalExecutions - $totalErrors) / $totalExecutions) * 100 : 100,
            'average_duration' => $durationCount > 0 ? $totalDuration / $durationCount : 0,
            'average_memory' => $memoryCount > 0 ? $totalMemory / $memoryCount : 0,
        ];
    }

    private function getCommandStats(array $metrics): array
    {
        $commandStats = [];

        foreach ($metrics as $metric) {
            if (str_contains($metric->getKey(), '_executions')) {
                $context = $metric->getContext();
                $commandName = $context['command_name'] ?? 'unknown';
                $commandStats[$commandName] = ($commandStats[$commandName] ?? 0) + $metric->getValue();
            }
        }

        return $commandStats;
    }
}
