<?php

declare(strict_types=1);

namespace App\Framework\Database\QueryOptimization\Commands;

use App\Framework\Console\Attributes\ConsoleCommand;
use App\Framework\Console\ConsoleInput;
use App\Framework\Console\ExitCode;
use App\Framework\Database\QueryOptimization\NPlusOneDetectionService;
use App\Framework\Logging\Logger;
use App\Framework\Logging\ValueObjects\LogContext;

/**
 * Console Command for N+1 Query Detection
 *
 * Detects and reports N+1 query problems with actionable recommendations.
 *
 * Usage:
 *   php console.php detect:n-plus-one --profile=UserController::index
 *   php console.php detect:n-plus-one --report
 *   php console.php detect:n-plus-one --critical-only
 */
#[ConsoleCommand(
    name: 'detect:n-plus-one',
    description: 'Detect N+1 query problems and generate optimization recommendations'
)]
final readonly class DetectN+1Command
{
    public function __construct(
        private NPlusOneDetectionService $detectionService,
        private Logger $logger
    ) {}

    public function execute(ConsoleInput $input): int
    {
        $this->logger->info(
            'N+1 Query Detection started',
            LogContext::empty()
        );

        // Get command options
        $profile = $input->getOption('profile');
        $report = $input->hasOption('report');
        $criticalOnly = $input->hasOption('critical-only');

        if ($profile) {
            return $this->profileCode($profile);
        }

        if ($report) {
            return $this->generateReport($criticalOnly);
        }

        // Default: Show usage help
        $this->showUsage();

        return ExitCode::SUCCESS;
    }

    /**
     * Profile specific code and detect N+1 problems
     */
    private function profileCode(string $target): int
    {
        echo "Profiling: {$target}\n";
        echo str_repeat('=', 60) . "\n\n";

        try {
            // Start query logging
            $this->detectionService->startLogging();

            echo "Query logging started. Execute your code now...\n";
            echo "Note: This command only starts logging. You need to execute the code separately.\n";
            echo "Press Enter when done...\n";

            // Wait for user input
            fgets(STDIN);

            // Stop logging and analyze
            $this->detectionService->stopLogging();

            // Generate and display report
            $report = $this->detectionService->analyzeAndReport();
            echo $report;

            $this->logger->info(
                'N+1 detection profiling completed',
                LogContext::withData(['target' => $target])
            );

            return ExitCode::SUCCESS;
        } catch (\Exception $e) {
            echo "Error during profiling: {$e->getMessage()}\n";

            $this->logger->error(
                'N+1 detection profiling failed',
                LogContext::withData([
                    'target' => $target,
                    'error' => $e->getMessage()
                ])
            );

            return ExitCode::ERROR;
        }
    }

    /**
     * Generate N+1 detection report from logged queries
     */
    private function generateReport(bool $criticalOnly): int
    {
        echo "N+1 Query Detection Report\n";
        echo str_repeat('=', 60) . "\n\n";

        try {
            if ($criticalOnly) {
                // Only critical problems
                $problems = $this->detectionService->getCriticalProblems();

                if (empty($problems)) {
                    echo "✓ No critical N+1 problems detected\n";
                    return ExitCode::SUCCESS;
                }

                echo "Critical N+1 Problems:\n\n";

                foreach ($problems as $index => $detection) {
                    echo sprintf(
                        "[%d] %s - %s\n",
                        $index + 1,
                        $detection->getSeverityLevel(),
                        $detection->pattern->getTableName()
                    );
                    echo "    Score: {$detection->getSeverityScore()}/10\n";
                    echo "    Executions: {$detection->pattern->getExecutionCount()}\n";
                    echo "    Total time: {$detection->pattern->getTotalExecutionTimeMs()}ms\n";
                    echo "    Impact: {$detection->getPerformanceImpact()}\n\n";

                    echo "Recommendation:\n";
                    echo $this->indentText($detection->recommendation, '    ');
                    echo "\n\n";
                }
            } else {
                // Full report
                $report = $this->detectionService->analyzeAndReport();
                echo $report;
            }

            $this->logger->info(
                'N+1 detection report generated',
                LogContext::withData(['critical_only' => $criticalOnly])
            );

            return ExitCode::SUCCESS;
        } catch (\Exception $e) {
            echo "Error generating report: {$e->getMessage()}\n";

            $this->logger->error(
                'N+1 report generation failed',
                LogContext::withData(['error' => $e->getMessage()])
            );

            return ExitCode::ERROR;
        }
    }

    /**
     * Show command usage help
     */
    private function showUsage(): void
    {
        echo "N+1 Query Detection\n";
        echo str_repeat('=', 60) . "\n\n";

        echo "Usage:\n";
        echo "  php console.php detect:n-plus-one [options]\n\n";

        echo "Options:\n";
        echo "  --profile=<target>   Profile specific code (e.g., UserController::index)\n";
        echo "  --report             Generate full N+1 detection report\n";
        echo "  --critical-only      Show only critical N+1 problems (severity >= 8)\n\n";

        echo "Examples:\n";
        echo "  php console.php detect:n-plus-one --profile=UserService::getUsers\n";
        echo "  php console.php detect:n-plus-one --report\n";
        echo "  php console.php detect:n-plus-one --critical-only\n\n";

        echo "Description:\n";
        echo "  Detects N+1 query problems by analyzing executed database queries.\n";
        echo "  Provides actionable recommendations for optimization via eager loading,\n";
        echo "  batch loading, or JOIN strategies.\n\n";

        echo "Performance Impact:\n";
        echo "  Fixing N+1 problems can improve performance by 10-100x by reducing\n";
        echo "  the number of database queries from N+1 to 1-2.\n\n";
    }

    /**
     * Indent multi-line text
     */
    private function indentText(string $text, string $indent): string
    {
        $lines = explode("\n", $text);
        return implode("\n", array_map(fn($line) => $indent . $line, $lines));
    }
}
