<?php

declare(strict_types=1);

namespace Tests\Performance\Reports;

use Tests\Performance\PerformanceBenchmarkResult;
use Tests\Performance\LoadTests\LoadTestResult;

/**
 * Generates performance test reports in various formats
 */
final readonly class PerformanceReportGenerator
{
    /**
     * Generate HTML report from benchmark results
     *
     * @param array<string, PerformanceBenchmarkResult> $benchmarkResults
     * @param LoadTestResult|null $loadTestResult
     * @return string HTML content
     */
    public function generateHtmlReport(
        array $benchmarkResults,
        ?LoadTestResult $loadTestResult = null
    ): string {
        $html = <<<HTML
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Performance Test Report</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
            background: #f5f5f5;
        }
        h1 {
            color: #333;
            border-bottom: 3px solid #4CAF50;
            padding-bottom: 10px;
        }
        h2 {
            color: #555;
            margin-top: 30px;
        }
        .summary {
            background: white;
            padding: 20px;
            border-radius: 8px;
            margin-bottom: 20px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        table {
            width: 100%;
            border-collapse: collapse;
            background: white;
            margin-bottom: 20px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        th, td {
            padding: 12px;
            text-align: left;
            border-bottom: 1px solid #ddd;
        }
        th {
            background: #4CAF50;
            color: white;
            font-weight: 600;
        }
        tr:hover {
            background: #f5f5f5;
        }
        .metric {
            font-weight: 600;
            color: #333;
        }
        .good {
            color: #4CAF50;
        }
        .warning {
            color: #FF9800;
        }
        .bad {
            color: #F44336;
        }
        .timestamp {
            color: #999;
            font-size: 0.9em;
        }
    </style>
</head>
<body>
    <h1>Performance Test Report</h1>
    <div class="summary">
        <p class="timestamp">Generated: {$this->getCurrentTimestamp()}</p>
        <p><strong>Total Benchmarks:</strong> {$this->countBenchmarks($benchmarkResults)}</p>
    </div>

HTML;

        // Add benchmark results
        if (!empty($benchmarkResults)) {
            $html .= $this->generateBenchmarkSection($benchmarkResults);
        }

        // Add load test results
        if ($loadTestResult) {
            $html .= $this->generateLoadTestSection($loadTestResult);
        }

        $html .= <<<HTML
</body>
</html>
HTML;

        return $html;
    }

    /**
     * Generate JSON report
     */
    public function generateJsonReport(
        array $benchmarkResults,
        ?LoadTestResult $loadTestResult = null
    ): string {
        $report = [
            'timestamp' => date('Y-m-d H:i:s'),
            'benchmarks' => []
        ];

        foreach ($benchmarkResults as $category => $result) {
            $report['benchmarks'][$category] = $result->toArray();
        }

        if ($loadTestResult) {
            $report['load_test'] = $loadTestResult->toArray();
        }

        return json_encode($report, JSON_PRETTY_PRINT);
    }

    /**
     * Generate markdown report
     */
    public function generateMarkdownReport(
        array $benchmarkResults,
        ?LoadTestResult $loadTestResult = null
    ): string {
        $markdown = "# Performance Test Report\n\n";
        $markdown .= "_Generated: " . $this->getCurrentTimestamp() . "_\n\n";

        // Benchmark results
        if (!empty($benchmarkResults)) {
            $markdown .= "## Benchmarks\n\n";

            foreach ($benchmarkResults as $category => $result) {
                $markdown .= "### {$result->name}\n\n";
                $markdown .= "| Metric | Value |\n";
                $markdown .= "|--------|-------|\n";
                $markdown .= "| Iterations | {$result->iterations} |\n";
                $markdown .= "| Avg Time | {$result->avgTimeMs}ms |\n";
                $markdown .= "| Min Time | {$result->minTimeMs}ms |\n";
                $markdown .= "| Max Time | {$result->maxTimeMs}ms |\n";
                $markdown .= "| Median Time | {$result->medianTimeMs}ms |\n";
                $markdown .= "| P95 Time | {$result->p95TimeMs}ms |\n";
                $markdown .= "| P99 Time | {$result->p99TimeMs}ms |\n";
                $markdown .= "| Ops/Sec | " . round($result->operationsPerSecond, 2) . " |\n";
                $markdown .= "\n";
            }
        }

        // Load test results
        if ($loadTestResult) {
            $markdown .= "## Load Test Results\n\n";
            $markdown .= "| Metric | Value |\n";
            $markdown .= "|--------|-------|\n";
            $markdown .= "| Total Requests | {$loadTestResult->totalRequests} |\n";
            $markdown .= "| Successful | {$loadTestResult->successfulRequests} |\n";
            $markdown .= "| Error Rate | " . round($loadTestResult->errorRate, 2) . "% |\n";
            $markdown .= "| Avg Response Time | " . round($loadTestResult->avgResponseTimeMs, 2) . "ms |\n";
            $markdown .= "| P95 Response Time | " . round($loadTestResult->p95ResponseTimeMs, 2) . "ms |\n";
            $markdown .= "| Throughput | " . round($loadTestResult->requestsPerSecond, 2) . " req/sec |\n";
        }

        return $markdown;
    }

    /**
     * Save report to file
     */
    public function saveReport(string $content, string $filename): void
    {
        $reportsDir = __DIR__ . '/../Reports';

        if (!is_dir($reportsDir)) {
            mkdir($reportsDir, 0755, true);
        }

        $filepath = $reportsDir . '/' . $filename;
        file_put_contents($filepath, $content);
    }

    private function generateBenchmarkSection(array $benchmarkResults): string
    {
        $html = "<h2>Benchmark Results</h2>\n";
        $html .= "<table>\n";
        $html .= "<thead>\n";
        $html .= "<tr><th>Benchmark</th><th>Iterations</th><th>Avg Time</th><th>Min</th><th>Max</th><th>P95</th><th>Ops/Sec</th></tr>\n";
        $html .= "</thead>\n";
        $html .= "<tbody>\n";

        foreach ($benchmarkResults as $category => $result) {
            $colorClass = $this->getColorClass($result->avgTimeMs);
            $html .= "<tr>\n";
            $html .= "<td class='metric'>{$result->name}</td>\n";
            $html .= "<td>{$result->iterations}</td>\n";
            $html .= "<td class='{$colorClass}'>" . round($result->avgTimeMs, 2) . "ms</td>\n";
            $html .= "<td>" . round($result->minTimeMs, 2) . "ms</td>\n";
            $html .= "<td>" . round($result->maxTimeMs, 2) . "ms</td>\n";
            $html .= "<td>" . round($result->p95TimeMs, 2) . "ms</td>\n";
            $html .= "<td>" . round($result->operationsPerSecond, 2) . "</td>\n";
            $html .= "</tr>\n";
        }

        $html .= "</tbody>\n";
        $html .= "</table>\n";

        return $html;
    }

    private function generateLoadTestSection(LoadTestResult $result): string
    {
        $html = "<h2>Load Test Results</h2>\n";
        $html .= "<table>\n";
        $html .= "<thead>\n";
        $html .= "<tr><th>Metric</th><th>Value</th></tr>\n";
        $html .= "</thead>\n";
        $html .= "<tbody>\n";
        $html .= "<tr><td class='metric'>Total Requests</td><td>{$result->totalRequests}</td></tr>\n";
        $html .= "<tr><td class='metric'>Successful Requests</td><td>{$result->successfulRequests}</td></tr>\n";
        $html .= "<tr><td class='metric'>Error Rate</td><td>" . round($result->errorRate, 2) . "%</td></tr>\n";
        $html .= "<tr><td class='metric'>Avg Response Time</td><td>" . round($result->avgResponseTimeMs, 2) . "ms</td></tr>\n";
        $html .= "<tr><td class='metric'>P95 Response Time</td><td>" . round($result->p95ResponseTimeMs, 2) . "ms</td></tr>\n";
        $html .= "<tr><td class='metric'>P99 Response Time</td><td>" . round($result->p99ResponseTimeMs, 2) . "ms</td></tr>\n";
        $html .= "<tr><td class='metric'>Throughput</td><td>" . round($result->requestsPerSecond, 2) . " req/sec</td></tr>\n";
        $html .= "</tbody>\n";
        $html .= "</table>\n";

        return $html;
    }

    private function getColorClass(float $timeMs): string
    {
        if ($timeMs < 10) {
            return 'good';
        } elseif ($timeMs < 50) {
            return 'warning';
        }
        return 'bad';
    }

    private function getCurrentTimestamp(): string
    {
        return date('Y-m-d H:i:s');
    }

    private function countBenchmarks(array $benchmarkResults): int
    {
        return count($benchmarkResults);
    }
}
