#!/usr/bin/env node

/**
 * Performance Benchmark Report Generator
 *
 * Generates HTML and Markdown reports from benchmark-results.json
 *
 * Usage:
 *   node tests/e2e/livecomponents/generate-performance-report.js
 *   node tests/e2e/livecomponents/generate-performance-report.js --format=html
 *   node tests/e2e/livecomponents/generate-performance-report.js --format=markdown
 */

import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// Parse command line arguments
const args = process.argv.slice(2);
const format = args.find(arg => arg.startsWith('--format='))?.split('=')[1] || 'both';

// Load benchmark results
const resultsPath = path.join(process.cwd(), 'test-results', 'benchmark-results.json');

if (!fs.existsSync(resultsPath)) {
    console.error('❌ No benchmark results found. Run benchmarks first:');
    console.error('   npx playwright test performance-benchmarks.spec.js');
    process.exit(1);
}

const data = JSON.parse(fs.readFileSync(resultsPath, 'utf-8'));
const { timestamp, results, summary } = data;

// Group results by scenario
const scenarios = {};
results.forEach(result => {
    if (!scenarios[result.scenario]) {
        scenarios[result.scenario] = [];
    }
    scenarios[result.scenario].push(result);
});

/**
 * Generate Markdown Report
 */
function generateMarkdownReport() {
    let markdown = `# LiveComponents Performance Benchmark Report

**Generated:** ${new Date(timestamp).toLocaleString()}

**Summary:**
- Total Benchmarks: ${summary.total}
- Passed: ${summary.passed} ✅
- Failed: ${summary.failed} ${summary.failed > 0 ? '❌' : ''}

---

## Executive Summary

This report compares the performance characteristics of **Fragment-based rendering** vs **Full HTML rendering** in LiveComponents.

### Key Findings

`;

    // Calculate overall speedups
    const fragmentVsFull = [];
    Object.values(scenarios).forEach(scenarioResults => {
        const fragmentResult = scenarioResults.find(r => r.metric.includes('Fragment'));
        const fullResult = scenarioResults.find(r => r.metric.includes('Full'));

        if (fragmentResult && fullResult && fragmentResult.unit === 'ms' && fullResult.unit === 'ms') {
            const speedup = ((fullResult.value - fragmentResult.value) / fullResult.value * 100);
            fragmentVsFull.push({
                scenario: fragmentResult.scenario,
                speedup,
                fragmentTime: fragmentResult.value,
                fullTime: fullResult.value
            });
        }
    });

    if (fragmentVsFull.length > 0) {
        const avgSpeedup = fragmentVsFull.reduce((sum, item) => sum + item.speedup, 0) / fragmentVsFull.length;
        markdown += `**Average Performance Improvement:** ${avgSpeedup.toFixed(1)}% faster with fragments\n\n`;

        const best = fragmentVsFull.reduce((best, item) => item.speedup > best.speedup ? item : best);
        markdown += `**Best Case:** ${best.scenario} - ${best.speedup.toFixed(1)}% faster (${best.fragmentTime.toFixed(2)}ms vs ${best.fullTime.toFixed(2)}ms)\n\n`;

        const worst = fragmentVsFull.reduce((worst, item) => item.speedup < worst.speedup ? item : worst);
        markdown += `**Worst Case:** ${worst.scenario} - ${worst.speedup.toFixed(1)}% faster (${worst.fragmentTime.toFixed(2)}ms vs ${worst.fullTime.toFixed(2)}ms)\n\n`;
    }

    markdown += `---

## Detailed Results

`;

    // Generate detailed results per scenario
    Object.entries(scenarios).forEach(([scenarioName, scenarioResults]) => {
        markdown += `### ${scenarioName}\n\n`;

        markdown += `| Metric | Value | Threshold | Status |\n`;
        markdown += `|--------|-------|-----------|--------|\n`;

        scenarioResults.forEach(result => {
            const value = result.unit === 'bytes'
                ? `${(result.value / 1024).toFixed(2)} KB`
                : `${result.value.toFixed(2)} ${result.unit}`;

            const threshold = result.unit === 'bytes'
                ? `${(result.threshold / 1024).toFixed(2)} KB`
                : `${result.threshold} ${result.unit}`;

            const status = result.passed ? '✅ Pass' : '❌ Fail';

            markdown += `| ${result.metric} | ${value} | ${threshold} | ${status} |\n`;
        });

        markdown += `\n`;
    });

    markdown += `---

## Recommendations

Based on the benchmark results:

`;

    // Generate recommendations
    const recommendations = [];

    // Check if fragments are faster
    const avgFragmentTime = results
        .filter(r => r.metric.includes('Fragment') && r.unit === 'ms')
        .reduce((sum, r) => sum + r.value, 0) / results.filter(r => r.metric.includes('Fragment') && r.unit === 'ms').length;

    const avgFullTime = results
        .filter(r => r.metric.includes('Full') && r.unit === 'ms')
        .reduce((sum, r) => sum + r.value, 0) / results.filter(r => r.metric.includes('Full') && r.unit === 'ms').length;

    if (avgFragmentTime < avgFullTime) {
        const improvement = ((avgFullTime - avgFragmentTime) / avgFullTime * 100).toFixed(1);
        recommendations.push(`✅ **Use fragment rendering** for partial updates - Average ${improvement}% performance improvement`);
    }

    // Check payload sizes
    const fragmentPayload = results.find(r => r.metric === 'Fragment Payload Size');
    const fullPayload = results.find(r => r.metric === 'Full HTML Payload Size');

    if (fragmentPayload && fullPayload) {
        const reduction = ((fullPayload.value - fragmentPayload.value) / fullPayload.value * 100).toFixed(1);
        recommendations.push(`✅ **Fragment updates reduce network payload** by ${reduction}% on average`);
    }

    // Check rapid updates
    const rapidFragment = results.find(r => r.scenario === 'Rapid Updates (10x)' && r.metric.includes('Fragment'));
    const rapidFull = results.find(r => r.scenario === 'Rapid Updates (10x)' && r.metric.includes('Full'));

    if (rapidFragment && rapidFull) {
        const multiplier = (rapidFull.value / rapidFragment.value).toFixed(1);
        recommendations.push(`✅ **For rapid successive updates**, fragments are ${multiplier}x faster`);
    }

    // Check memory consumption
    const memFragment = results.find(r => r.metric === 'Fragment Updates Memory Delta');
    const memFull = results.find(r => r.metric === 'Full Renders Memory Delta');

    if (memFragment && memFull && memFragment.value < memFull.value) {
        const memReduction = ((memFull.value - memFragment.value) / memFull.value * 100).toFixed(1);
        recommendations.push(`✅ **Lower memory consumption** with fragments - ${memReduction}% less memory used`);
    }

    recommendations.forEach(rec => {
        markdown += `${rec}\n\n`;
    });

    markdown += `### When to Use Fragments

- ✅ **Small, frequent updates** (e.g., counters, notifications, status indicators)
- ✅ **Partial form updates** (e.g., validation errors, field suggestions)
- ✅ **List item modifications** (e.g., shopping cart items, task lists)
- ✅ **Real-time data updates** (e.g., live scores, stock prices)
- ✅ **Multi-section updates** (e.g., updating header + footer simultaneously)

### When to Use Full Render

- ⚠️ **Complete layout changes** (e.g., switching views, modal dialogs)
- ⚠️ **Initial page load** (no fragments to update yet)
- ⚠️ **Complex interdependent updates** (easier to re-render entire component)
- ⚠️ **Simple components** (overhead of fragment logic not worth it)

---

## Performance Metrics Glossary

- **Fragment Update Time:** Time to fetch and apply fragment-specific updates
- **Full Render Time:** Time to fetch and replace entire component HTML
- **Network Payload:** Size of data transferred from server to client
- **DOM Update:** Time spent manipulating the Document Object Model
- **Memory Delta:** Change in JavaScript heap memory usage

---

*Generated by LiveComponents Performance Benchmark Suite*
`;

    return markdown;
}

/**
 * Generate HTML Report
 */
function generateHTMLReport() {
    const markdown = generateMarkdownReport();

    // Simple markdown to HTML conversion
    let html = markdown
        .replace(/^# (.+)$/gm, '<h1>$1</h1>')
        .replace(/^## (.+)$/gm, '<h2>$1</h2>')
        .replace(/^### (.+)$/gm, '<h3>$1</h3>')
        .replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
        .replace(/`(.+?)`/g, '<code>$1</code>')
        .replace(/^- (.+)$/gm, '<li>$1</li>')
        .replace(/\n\n/g, '</p><p>')
        .replace(/^---$/gm, '<hr>');

    // Wrap in HTML template
    const htmlDoc = `<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>LiveComponents Performance Benchmark Report</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
            line-height: 1.6;
            color: #333;
            background: #f5f5f5;
            padding: 2rem;
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            padding: 3rem;
            border-radius: 8px;
            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
        }

        h1 {
            color: #2c3e50;
            border-bottom: 3px solid #3498db;
            padding-bottom: 1rem;
            margin-bottom: 2rem;
        }

        h2 {
            color: #34495e;
            margin-top: 3rem;
            margin-bottom: 1rem;
            padding-bottom: 0.5rem;
            border-bottom: 2px solid #ecf0f1;
        }

        h3 {
            color: #7f8c8d;
            margin-top: 2rem;
            margin-bottom: 1rem;
        }

        p {
            margin-bottom: 1rem;
        }

        table {
            width: 100%;
            border-collapse: collapse;
            margin: 1.5rem 0;
            background: white;
        }

        th {
            background: #3498db;
            color: white;
            padding: 1rem;
            text-align: left;
            font-weight: 600;
        }

        td {
            padding: 0.75rem 1rem;
            border-bottom: 1px solid #ecf0f1;
        }

        tr:hover {
            background: #f8f9fa;
        }

        ul {
            list-style-position: inside;
            margin: 1rem 0;
        }

        li {
            margin: 0.5rem 0;
            padding-left: 1rem;
        }

        code {
            background: #f1f3f4;
            padding: 0.2rem 0.4rem;
            border-radius: 3px;
            font-family: 'Courier New', monospace;
            font-size: 0.9em;
        }

        strong {
            color: #2c3e50;
            font-weight: 600;
        }

        hr {
            border: none;
            border-top: 2px solid #ecf0f1;
            margin: 2rem 0;
        }

        .summary-box {
            background: #e8f4f8;
            border-left: 4px solid #3498db;
            padding: 1.5rem;
            margin: 2rem 0;
            border-radius: 4px;
        }

        .recommendation {
            background: #d4edda;
            border-left: 4px solid #28a745;
            padding: 1rem;
            margin: 1rem 0;
            border-radius: 4px;
        }

        .warning {
            background: #fff3cd;
            border-left: 4px solid #ffc107;
            padding: 1rem;
            margin: 1rem 0;
            border-radius: 4px;
        }

        @media print {
            body {
                background: white;
                padding: 0;
            }

            .container {
                box-shadow: none;
                padding: 1rem;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        ${html}
    </div>
</body>
</html>`;

    return htmlDoc;
}

/**
 * Main execution
 */
function main() {
    console.log('📊 Generating Performance Benchmark Report...\n');

    const outputDir = path.join(process.cwd(), 'test-results');

    if (format === 'markdown' || format === 'both') {
        const markdown = generateMarkdownReport();
        const mdPath = path.join(outputDir, 'performance-report.md');
        fs.writeFileSync(mdPath, markdown);
        console.log(`✅ Markdown report: ${mdPath}`);
    }

    if (format === 'html' || format === 'both') {
        const html = generateHTMLReport();
        const htmlPath = path.join(outputDir, 'performance-report.html');
        fs.writeFileSync(htmlPath, html);
        console.log(`✅ HTML report: ${htmlPath}`);
    }

    console.log('\n📈 Report Generation Complete!\n');
    console.log('Summary:');
    console.log(`  Total Benchmarks: ${summary.total}`);
    console.log(`  Passed: ${summary.passed} ✅`);
    console.log(`  Failed: ${summary.failed} ${summary.failed > 0 ? '❌' : ''}`);

    if (format === 'html' || format === 'both') {
        console.log(`\n🌐 Open HTML report in browser:`);
        console.log(`  file://${path.join(outputDir, 'performance-report.html')}`);
    }
}

main();
