<?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 PerformanceTrendsCommand
{
    public function __construct(
        private PerformanceCollectorInterface $performanceCollector
    ) {
    }

    #[ConsoleCommand('perf:trends', 'Show console performance trends and insights')]
    public function showPerformanceTrends(ConsoleInput $input, ConsoleOutputInterface $output): ExitCode
    {
        $output->writeLine('📈 Console Performance Trends', ConsoleColor::BRIGHT_GREEN);
        $output->newLine();

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

        if (empty($consoleMetrics)) {
            $output->writeLine('No performance data available for trend analysis.', ConsoleColor::YELLOW);

            return ExitCode::SUCCESS;
        }

        $this->displayExecutionTrends($output, $consoleMetrics);
        $output->newLine();
        $this->displayMemoryTrends($output, $consoleMetrics);
        $output->newLine();
        $this->displayCommandFrequency($output, $consoleMetrics);
        $output->newLine();
        $this->displayPerformanceInsights($output, $consoleMetrics);

        return ExitCode::SUCCESS;
    }

    #[ConsoleCommand('perf:benchmark', 'Run performance benchmarks for console commands')]
    public function runBenchmarks(ConsoleInput $input, ConsoleOutputInterface $output, int $iterations = 5): ExitCode
    {
        $output->writeLine('🏃 Console Performance Benchmarks', ConsoleColor::BRIGHT_BLUE);
        $output->writeLine(sprintf('Running %d iterations of each command...', $iterations), ConsoleColor::GRAY);
        $output->newLine();

        // This would require integration with the command registry to run actual benchmarks
        $output->writeLine('⚠️  Benchmark functionality requires command registry integration', ConsoleColor::YELLOW);
        $output->writeLine('This is a placeholder for future implementation.', ConsoleColor::GRAY);

        return ExitCode::SUCCESS;
    }

    #[ConsoleCommand('perf:health', 'Check console performance health status')]
    public function checkPerformanceHealth(ConsoleInput $input, ConsoleOutputInterface $output): ExitCode
    {
        $output->writeLine('🏥 Console Performance Health Check', ConsoleColor::BRIGHT_MAGENTA);
        $output->newLine();

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

        $this->displayHealthScore($output, $healthScore);
        $output->newLine();
        $this->displayHealthDetails($output, $consoleMetrics, $healthScore);
        $output->newLine();
        $this->displayHealthRecommendations($output, $healthScore);

        return ExitCode::SUCCESS;
    }

    private function displayExecutionTrends(ConsoleOutputInterface $output, array $metrics): void
    {
        $output->writeLine('⏱️  Execution Time Trends', ConsoleColor::BRIGHT_WHITE);
        $output->writeLine('─────────────────────────', ConsoleColor::GRAY);

        $executionMetrics = array_filter(
            $metrics,
            fn ($metric) =>
            str_contains($metric->getKey(), 'console_command_') &&
            ! str_contains($metric->getKey(), '_error') &&
            ! str_contains($metric->getKey(), '_memory')
        );

        if (empty($executionMetrics)) {
            $output->writeLine('No execution time data available.', ConsoleColor::GRAY);

            return;
        }

        $fastCommands = 0;
        $mediumCommands = 0;
        $slowCommands = 0;
        $totalDuration = 0;
        $commandCount = 0;

        foreach ($executionMetrics as $metric) {
            $avgDuration = $metric->getAverageDuration();
            $totalDuration += $metric->getTotalDuration();
            $commandCount++;

            if ($avgDuration < 100) {
                $fastCommands++;
            } elseif ($avgDuration < 1000) {
                $mediumCommands++;
            } else {
                $slowCommands++;
            }
        }

        $output->writeLine(sprintf('Fast Commands (<100ms): %d', $fastCommands), ConsoleColor::GREEN);
        $output->writeLine(sprintf('Medium Commands (100-1000ms): %d', $mediumCommands), ConsoleColor::YELLOW);
        $output->writeLine(sprintf('Slow Commands (>1000ms): %d', $slowCommands), ConsoleColor::RED);

        if ($commandCount > 0) {
            $avgOverall = $totalDuration / $commandCount;
            $output->writeLine(sprintf('Overall Average: %.2fms', $avgOverall), ConsoleColor::WHITE);
        }
    }

    private function displayMemoryTrends(ConsoleOutputInterface $output, array $metrics): void
    {
        $output->writeLine('💾 Memory Usage Trends', 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;
        }

        $lowMemory = 0;
        $mediumMemory = 0;
        $highMemory = 0;
        $totalMemory = 0;
        $count = 0;

        foreach ($memoryMetrics as $metric) {
            $memory = $metric->getValue();
            $totalMemory += $memory;
            $count++;

            if ($memory < 10) {
                $lowMemory++;
            } elseif ($memory < 50) {
                $mediumMemory++;
            } else {
                $highMemory++;
            }
        }

        $output->writeLine(sprintf('Low Memory Usage (<10MB): %d commands', $lowMemory), ConsoleColor::GREEN);
        $output->writeLine(sprintf('Medium Memory Usage (10-50MB): %d commands', $mediumMemory), ConsoleColor::YELLOW);
        $output->writeLine(sprintf('High Memory Usage (>50MB): %d commands', $highMemory), ConsoleColor::RED);

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

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

        $executionCounts = [];

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

        if (empty($executionCounts)) {
            $output->writeLine('No execution frequency data available.', ConsoleColor::GRAY);

            return;
        }

        arsort($executionCounts);
        $topCommands = array_slice($executionCounts, 0, 5, true);

        foreach ($topCommands as $command => $count) {
            $bar = str_repeat('█', min(20, intval($count / max($executionCounts) * 20)));
            $output->writeLine(sprintf('  %-20s %s (%d)', $command, $bar, $count), ConsoleColor::CYAN);
        }
    }

    private function displayPerformanceInsights(ConsoleOutputInterface $output, array $metrics): void
    {
        $output->writeLine('💡 Performance Insights', ConsoleColor::BRIGHT_WHITE);
        $output->writeLine('──────────────────────', ConsoleColor::GRAY);

        $insights = $this->generateInsights($metrics);

        if (empty($insights)) {
            $output->writeLine('No specific insights available.', ConsoleColor::GRAY);

            return;
        }

        foreach ($insights as $insight) {
            $output->writeLine("  {$insight}", ConsoleColor::WHITE);
        }
    }

    private function calculateHealthScore(array $metrics): array
    {
        $score = 100;
        $issues = [];

        // Check error rate
        $totalExecutions = 0;
        $totalErrors = 0;

        foreach ($metrics as $metric) {
            if (str_contains($metric->getKey(), '_executions')) {
                $totalExecutions += $metric->getValue();
            } elseif (str_contains($metric->getKey(), '_error')) {
                $totalErrors += $metric->getValue();
            }
        }

        $errorRate = $totalExecutions > 0 ? ($totalErrors / $totalExecutions) * 100 : 0;

        if ($errorRate > 10) {
            $score -= 30;
            $issues[] = 'High error rate detected';
        } elseif ($errorRate > 5) {
            $score -= 15;
            $issues[] = 'Moderate error rate detected';
        }

        // Check for slow commands
        $slowCommandCount = 0;
        foreach ($metrics as $metric) {
            if (str_contains($metric->getKey(), 'console_command_') &&
                ! str_contains($metric->getKey(), '_error') &&
                ! str_contains($metric->getKey(), '_memory')) {
                if ($metric->getAverageDuration() > 5000) {
                    $slowCommandCount++;
                }
            }
        }

        if ($slowCommandCount > 3) {
            $score -= 20;
            $issues[] = 'Multiple slow commands detected';
        } elseif ($slowCommandCount > 0) {
            $score -= 10;
            $issues[] = 'Some slow commands detected';
        }

        // Check memory usage
        $highMemoryCount = 0;
        foreach ($metrics as $metric) {
            if (str_contains($metric->getKey(), 'memory_usage') && $metric->getValue() > 100) {
                $highMemoryCount++;
            }
        }

        if ($highMemoryCount > 0) {
            $score -= 15;
            $issues[] = 'High memory usage detected';
        }

        return [
            'score' => max(0, $score),
            'issues' => $issues,
            'total_executions' => $totalExecutions,
            'error_rate' => $errorRate,
            'slow_commands' => $slowCommandCount,
            'high_memory_commands' => $highMemoryCount,
        ];
    }

    private function displayHealthScore(ConsoleOutputInterface $output, array $health): void
    {
        $score = $health['score'];

        $color = $score >= 90 ? ConsoleColor::GREEN :
                ($score >= 70 ? ConsoleColor::YELLOW : ConsoleColor::RED);

        $status = $score >= 90 ? 'Excellent' :
                 ($score >= 70 ? 'Good' :
                 ($score >= 50 ? 'Fair' : 'Poor'));

        $output->writeLine(sprintf('Health Score: %d/100 (%s)', $score, $status), $color);
    }

    private function displayHealthDetails(ConsoleOutputInterface $output, array $metrics, array $health): void
    {
        $output->writeLine('📋 Health Details', ConsoleColor::BRIGHT_WHITE);
        $output->writeLine('───────────────', ConsoleColor::GRAY);

        $output->writeLine(sprintf('Total Executions: %d', $health['total_executions']), ConsoleColor::WHITE);
        $output->writeLine(
            sprintf('Error Rate: %.2f%%', $health['error_rate']),
            $health['error_rate'] > 5 ? ConsoleColor::RED : ConsoleColor::GREEN
        );
        $output->writeLine(
            sprintf('Slow Commands: %d', $health['slow_commands']),
            $health['slow_commands'] > 0 ? ConsoleColor::YELLOW : ConsoleColor::GREEN
        );
        $output->writeLine(
            sprintf('High Memory Commands: %d', $health['high_memory_commands']),
            $health['high_memory_commands'] > 0 ? ConsoleColor::YELLOW : ConsoleColor::GREEN
        );
    }

    private function displayHealthRecommendations(ConsoleOutputInterface $output, array $health): void
    {
        if (empty($health['issues'])) {
            $output->writeLine('🎉 No performance issues detected!', ConsoleColor::GREEN);

            return;
        }

        $output->writeLine('⚠️  Recommendations', ConsoleColor::BRIGHT_WHITE);
        $output->writeLine('─────────────────', ConsoleColor::GRAY);

        foreach ($health['issues'] as $issue) {
            $output->writeLine("  • {$issue}", ConsoleColor::YELLOW);
        }
    }

    private function generateInsights(array $metrics): array
    {
        $insights = [];

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

        if (! empty($commandCounts)) {
            $mostUsed = array_keys($commandCounts, max($commandCounts))[0];
            $insights[] = "Most frequently used command: {$mostUsed}";

            if (count($commandCounts) > 5) {
                $insights[] = "You're using a diverse set of commands (" . count($commandCounts) . " different commands)";
            }
        }

        // Memory insights
        $memoryMetrics = array_filter($metrics, fn ($metric) => str_contains($metric->getKey(), 'memory_usage'));
        if (! empty($memoryMetrics)) {
            $totalMemory = array_sum(array_map(fn ($metric) => $metric->getValue(), $memoryMetrics));
            $avgMemory = $totalMemory / count($memoryMetrics);

            if ($avgMemory < 5) {
                $insights[] = "Memory usage is very efficient (avg: " . number_format($avgMemory, 1) . "MB)";
            } elseif ($avgMemory > 50) {
                $insights[] = "Memory usage is higher than expected (avg: " . number_format($avgMemory, 1) . "MB)";
            }
        }

        return $insights;
    }
}
