#!/usr/bin/env node
/**
 * Lighthouse Audit for All Locales
 * Runs PageSpeed Insights API tests for all three language versions (de, en, sr)
 * Documents Core Web Vitals (LCP, CLS, INP) for both mobile and desktop modes
 */

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

// Disable SSL verification for local testing (network proxy issue)
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';

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

const API_KEY = 'AIzaSyA4qo0LfLy_ps-SyTQTQpFrFRjDnAUn_K4';
const BASE_URL = 'https://www.damjan-savic.com';
const LOCALES = ['de', 'en', 'sr'];
const STRATEGIES = ['mobile', 'desktop'];

const REPORTS_DIR = path.join(__dirname, '..', '.auto-claude', 'specs', '001-suche-nach-optimierungsvorschl-gen', 'lighthouse-reports');

function httpsGet(url) {
    return new Promise((resolve, reject) => {
        https.get(url, (res) => {
            let data = '';
            res.on('data', chunk => data += chunk);
            res.on('end', () => {
                try {
                    resolve(JSON.parse(data));
                } catch (e) {
                    reject(new Error(`JSON Parse Error: ${e.message}`));
                }
            });
        }).on('error', reject);
    });
}

async function runPageSpeedTest(url, strategy = 'mobile') {
    const apiUrl = `https://pagespeedonline.googleapis.com/pagespeedonline/v5/runPagespeed?url=${encodeURIComponent(url)}&key=${API_KEY}&strategy=${strategy}&category=performance&category=accessibility&category=best-practices&category=seo`;

    console.log(`\n  Testing ${url} (${strategy})...`);
    console.log('  Please wait, this may take 30-60 seconds...\n');

    try {
        const data = await httpsGet(apiUrl);

        if (data.error) {
            throw new Error(`API Error: ${data.error.message}`);
        }

        return data;
    } catch (error) {
        console.error(`  Error testing ${url}:`, error.message);
        throw error;
    }
}

function extractCoreWebVitals(data) {
    const lighthouse = data.lighthouseResult;
    const categories = lighthouse.categories;
    const audits = lighthouse.audits;

    const fcp = audits['first-contentful-paint'];
    const lcp = audits['largest-contentful-paint'];
    const tbt = audits['total-blocking-time'];
    const cls = audits['cumulative-layout-shift'];
    const si = audits['speed-index'];
    const inp = audits['interaction-to-next-paint'] || audits['experimental-interaction-to-next-paint'];

    // Extract opportunities
    const opportunities = Object.values(audits)
        .filter(audit => audit.details?.type === 'opportunity' && audit.details?.overallSavingsMs > 0)
        .sort((a, b) => (b.details?.overallSavingsMs || 0) - (a.details?.overallSavingsMs || 0))
        .map(opp => ({
            title: opp.title,
            description: opp.description,
            savings_ms: opp.details?.overallSavingsMs || 0,
            savings_bytes: opp.details?.overallSavingsBytes || 0
        }));

    // Extract diagnostics
    const diagnostics = Object.values(audits)
        .filter(audit => audit.details?.type === 'table' && audit.score !== null && audit.score < 0.9)
        .map(diag => ({
            title: diag.title,
            description: diag.description,
            score: diag.score
        }));

    return {
        url: lighthouse.finalUrl,
        fetchTime: lighthouse.fetchTime,
        userAgent: lighthouse.userAgent,
        scores: {
            performance: Math.round(categories.performance.score * 100),
            accessibility: Math.round(categories.accessibility.score * 100),
            bestPractices: Math.round(categories['best-practices'].score * 100),
            seo: Math.round(categories.seo.score * 100)
        },
        coreWebVitals: {
            FCP: {
                value: fcp?.numericValue || null,
                displayValue: fcp?.displayValue || 'N/A',
                score: fcp?.score || null
            },
            LCP: {
                value: lcp?.numericValue || null,
                displayValue: lcp?.displayValue || 'N/A',
                score: lcp?.score || null
            },
            CLS: {
                value: cls?.numericValue || null,
                displayValue: cls?.displayValue || 'N/A',
                score: cls?.score || null
            },
            TBT: {
                value: tbt?.numericValue || null,
                displayValue: tbt?.displayValue || 'N/A',
                score: tbt?.score || null
            },
            INP: {
                value: inp?.numericValue || null,
                displayValue: inp?.displayValue || 'N/A',
                score: inp?.score || null
            },
            SpeedIndex: {
                value: si?.numericValue || null,
                displayValue: si?.displayValue || 'N/A',
                score: si?.score || null
            }
        },
        opportunities: opportunities.slice(0, 10),
        diagnostics: diagnostics.slice(0, 10)
    };
}

function formatTime(ms) {
    if (ms === null || ms === undefined) return 'N/A';
    if (ms < 1000) return `${Math.round(ms)}ms`;
    return `${(ms / 1000).toFixed(2)}s`;
}

function getScoreEmoji(score) {
    if (score >= 90) return 'green';
    if (score >= 50) return 'yellow';
    return 'red';
}

function generateMarkdownReport(allResults) {
    const timestamp = new Date().toISOString();
    let markdown = `# Lighthouse Audit Report - Core Web Vitals

**Generated:** ${timestamp}
**Base URL:** ${BASE_URL}
**Locales Tested:** ${LOCALES.join(', ')}

---

## Executive Summary

This report documents Core Web Vitals (LCP, CLS, INP/TBT) measurements for all three language versions of the portfolio website in both mobile and desktop modes.

### Key Metrics Explained:

- **LCP (Largest Contentful Paint):** Measures loading performance. Good: < 2.5s, Needs Improvement: 2.5-4s, Poor: > 4s
- **CLS (Cumulative Layout Shift):** Measures visual stability. Good: < 0.1, Needs Improvement: 0.1-0.25, Poor: > 0.25
- **INP/TBT (Interaction to Next Paint / Total Blocking Time):** Measures interactivity. TBT Good: < 200ms, INP Good: < 200ms
- **FCP (First Contentful Paint):** Measures perceived load speed. Good: < 1.8s
- **Speed Index:** How quickly content is visually displayed. Good: < 3.4s

---

## Results Summary Table

### Mobile Results

| Locale | Performance | LCP | CLS | TBT | FCP | Accessibility | SEO |
|--------|-------------|-----|-----|-----|-----|---------------|-----|
`;

    // Add mobile results
    LOCALES.forEach(locale => {
        const result = allResults[`${locale}_mobile`];
        if (result) {
            const cwv = result.coreWebVitals;
            markdown += `| ${locale.toUpperCase()} | ${result.scores.performance}% | ${cwv.LCP.displayValue} | ${cwv.CLS.displayValue} | ${cwv.TBT.displayValue} | ${cwv.FCP.displayValue} | ${result.scores.accessibility}% | ${result.scores.seo}% |\n`;
        }
    });

    markdown += `
### Desktop Results

| Locale | Performance | LCP | CLS | TBT | FCP | Accessibility | SEO |
|--------|-------------|-----|-----|-----|-----|---------------|-----|
`;

    // Add desktop results
    LOCALES.forEach(locale => {
        const result = allResults[`${locale}_desktop`];
        if (result) {
            const cwv = result.coreWebVitals;
            markdown += `| ${locale.toUpperCase()} | ${result.scores.performance}% | ${cwv.LCP.displayValue} | ${cwv.CLS.displayValue} | ${cwv.TBT.displayValue} | ${cwv.FCP.displayValue} | ${result.scores.accessibility}% | ${result.scores.seo}% |\n`;
        }
    });

    markdown += `
---

## Detailed Results by Locale

`;

    // Detailed results for each locale
    LOCALES.forEach(locale => {
        markdown += `### ${locale.toUpperCase()} - ${locale === 'de' ? 'German' : locale === 'en' ? 'English' : 'Serbian'}

**URL:** ${BASE_URL}/${locale}

`;

        STRATEGIES.forEach(strategy => {
            const result = allResults[`${locale}_${strategy}`];
            if (result) {
                const cwv = result.coreWebVitals;
                markdown += `#### ${strategy.charAt(0).toUpperCase() + strategy.slice(1)}

**Scores:**
- Performance: ${result.scores.performance}%
- Accessibility: ${result.scores.accessibility}%
- Best Practices: ${result.scores.bestPractices}%
- SEO: ${result.scores.seo}%

**Core Web Vitals:**
| Metric | Value | Score |
|--------|-------|-------|
| First Contentful Paint (FCP) | ${cwv.FCP.displayValue} | ${cwv.FCP.score !== null ? Math.round(cwv.FCP.score * 100) + '%' : 'N/A'} |
| Largest Contentful Paint (LCP) | ${cwv.LCP.displayValue} | ${cwv.LCP.score !== null ? Math.round(cwv.LCP.score * 100) + '%' : 'N/A'} |
| Cumulative Layout Shift (CLS) | ${cwv.CLS.displayValue} | ${cwv.CLS.score !== null ? Math.round(cwv.CLS.score * 100) + '%' : 'N/A'} |
| Total Blocking Time (TBT) | ${cwv.TBT.displayValue} | ${cwv.TBT.score !== null ? Math.round(cwv.TBT.score * 100) + '%' : 'N/A'} |
| Speed Index | ${cwv.SpeedIndex.displayValue} | ${cwv.SpeedIndex.score !== null ? Math.round(cwv.SpeedIndex.score * 100) + '%' : 'N/A'} |

`;

                if (result.opportunities && result.opportunities.length > 0) {
                    markdown += `**Optimization Opportunities:**
`;
                    result.opportunities.slice(0, 5).forEach(opp => {
                        markdown += `- **${opp.title}**: Potential savings of ${formatTime(opp.savings_ms)}`;
                        if (opp.savings_bytes > 0) {
                            markdown += ` / ${(opp.savings_bytes / 1024).toFixed(1)} KB`;
                        }
                        markdown += `\n`;
                    });
                    markdown += '\n';
                }

                if (result.diagnostics && result.diagnostics.length > 0) {
                    markdown += `**Diagnostics (Items Needing Attention):**
`;
                    result.diagnostics.slice(0, 5).forEach(diag => {
                        markdown += `- ${diag.title} (Score: ${Math.round(diag.score * 100)}%)\n`;
                    });
                    markdown += '\n';
                }
            }
        });
    });

    markdown += `---

## Core Web Vitals Analysis

### LCP (Largest Contentful Paint) Summary

`;

    // LCP analysis
    const lcpValues = [];
    Object.entries(allResults).forEach(([key, result]) => {
        if (result && result.coreWebVitals.LCP.value) {
            lcpValues.push({
                test: key,
                value: result.coreWebVitals.LCP.value,
                displayValue: result.coreWebVitals.LCP.displayValue
            });
        }
    });

    if (lcpValues.length > 0) {
        const avgLCP = lcpValues.reduce((sum, item) => sum + item.value, 0) / lcpValues.length;
        const maxLCP = Math.max(...lcpValues.map(item => item.value));
        const minLCP = Math.min(...lcpValues.map(item => item.value));

        markdown += `- **Average LCP:** ${formatTime(avgLCP)}
- **Best LCP:** ${formatTime(minLCP)}
- **Worst LCP:** ${formatTime(maxLCP)}
- **Target:** < 2.5s for Good score

`;
    }

    markdown += `### CLS (Cumulative Layout Shift) Summary

`;

    // CLS analysis
    const clsValues = [];
    Object.entries(allResults).forEach(([key, result]) => {
        if (result && result.coreWebVitals.CLS.value !== null) {
            clsValues.push({
                test: key,
                value: result.coreWebVitals.CLS.value,
                displayValue: result.coreWebVitals.CLS.displayValue
            });
        }
    });

    if (clsValues.length > 0) {
        const avgCLS = clsValues.reduce((sum, item) => sum + item.value, 0) / clsValues.length;
        const maxCLS = Math.max(...clsValues.map(item => item.value));

        markdown += `- **Average CLS:** ${avgCLS.toFixed(3)}
- **Worst CLS:** ${maxCLS.toFixed(3)}
- **Target:** < 0.1 for Good score

`;
    }

    markdown += `### TBT (Total Blocking Time) Summary

`;

    // TBT analysis
    const tbtValues = [];
    Object.entries(allResults).forEach(([key, result]) => {
        if (result && result.coreWebVitals.TBT.value !== null) {
            tbtValues.push({
                test: key,
                value: result.coreWebVitals.TBT.value,
                displayValue: result.coreWebVitals.TBT.displayValue
            });
        }
    });

    if (tbtValues.length > 0) {
        const avgTBT = tbtValues.reduce((sum, item) => sum + item.value, 0) / tbtValues.length;
        const maxTBT = Math.max(...tbtValues.map(item => item.value));

        markdown += `- **Average TBT:** ${formatTime(avgTBT)}
- **Worst TBT:** ${formatTime(maxTBT)}
- **Target:** < 200ms for Good score

`;
    }

    markdown += `---

## Recommendations Summary

Based on the audit results, here are the key areas for improvement:

### High Priority (Performance Impact)

1. **Largest Contentful Paint (LCP):** Focus on optimizing the hero image and main content loading
2. **Total Blocking Time (TBT):** Reduce JavaScript execution time, consider code splitting
3. **First Contentful Paint (FCP):** Optimize critical rendering path

### Medium Priority (User Experience)

1. **Cumulative Layout Shift (CLS):** Ensure images have explicit dimensions, avoid layout shifts from fonts
2. **Speed Index:** Optimize above-the-fold content delivery

### Common Opportunities Across All Tests

`;

    // Aggregate opportunities
    const allOpportunities = {};
    Object.values(allResults).forEach(result => {
        if (result && result.opportunities) {
            result.opportunities.forEach(opp => {
                if (!allOpportunities[opp.title]) {
                    allOpportunities[opp.title] = {
                        count: 0,
                        totalSavings: 0,
                        title: opp.title
                    };
                }
                allOpportunities[opp.title].count++;
                allOpportunities[opp.title].totalSavings += opp.savings_ms;
            });
        }
    });

    const sortedOpportunities = Object.values(allOpportunities)
        .sort((a, b) => b.totalSavings - a.totalSavings)
        .slice(0, 10);

    sortedOpportunities.forEach((opp, index) => {
        markdown += `${index + 1}. **${opp.title}** - Appeared in ${opp.count} tests, avg. savings: ${formatTime(opp.totalSavings / opp.count)}\n`;
    });

    markdown += `

---

## Raw Data Files

Individual JSON files with complete audit data are saved in the \`lighthouse-reports\` directory:

`;

    Object.keys(allResults).forEach(key => {
        markdown += `- \`${key}.json\`\n`;
    });

    markdown += `
---

*Report generated by lighthouse-audit-all-locales.js*
`;

    return markdown;
}

async function main() {
    console.log('\n========================================');
    console.log(' Lighthouse Audit - All Locales');
    console.log('========================================\n');
    console.log(`Base URL: ${BASE_URL}`);
    console.log(`Locales: ${LOCALES.join(', ')}`);
    console.log(`Strategies: ${STRATEGIES.join(', ')}`);
    console.log(`Reports Directory: ${REPORTS_DIR}`);
    console.log('\n----------------------------------------\n');

    // Ensure reports directory exists
    if (!fs.existsSync(REPORTS_DIR)) {
        fs.mkdirSync(REPORTS_DIR, { recursive: true });
    }

    const allResults = {};
    const errors = [];

    // Run tests for each locale and strategy
    for (const locale of LOCALES) {
        const url = `${BASE_URL}/${locale}`;
        console.log(`\n>>> Testing ${locale.toUpperCase()} (${url})`);

        for (const strategy of STRATEGIES) {
            const key = `${locale}_${strategy}`;
            try {
                const data = await runPageSpeedTest(url, strategy);
                const results = extractCoreWebVitals(data);
                allResults[key] = results;

                // Save individual JSON file
                const jsonPath = path.join(REPORTS_DIR, `${key}.json`);
                fs.writeFileSync(jsonPath, JSON.stringify(results, null, 2));
                console.log(`  Saved: ${key}.json`);

                // Display quick summary
                console.log(`  Performance: ${results.scores.performance}% | LCP: ${results.coreWebVitals.LCP.displayValue} | CLS: ${results.coreWebVitals.CLS.displayValue}`);

            } catch (error) {
                console.error(`  FAILED: ${key} - ${error.message}`);
                errors.push({ key, error: error.message });
            }
        }
    }

    // Generate and save markdown report
    console.log('\n----------------------------------------');
    console.log('Generating comprehensive report...');

    const markdownReport = generateMarkdownReport(allResults);
    const reportPath = path.join(REPORTS_DIR, 'LIGHTHOUSE_REPORT.md');
    fs.writeFileSync(reportPath, markdownReport);
    console.log(`Report saved: ${reportPath}`);

    // Save combined JSON
    const combinedPath = path.join(REPORTS_DIR, 'all_results.json');
    fs.writeFileSync(combinedPath, JSON.stringify({
        timestamp: new Date().toISOString(),
        baseUrl: BASE_URL,
        locales: LOCALES,
        strategies: STRATEGIES,
        results: allResults,
        errors: errors
    }, null, 2));
    console.log(`Combined data saved: ${combinedPath}`);

    // Final summary
    console.log('\n========================================');
    console.log(' AUDIT COMPLETE');
    console.log('========================================\n');

    console.log('Results Summary:');
    console.log('----------------');

    LOCALES.forEach(locale => {
        console.log(`\n${locale.toUpperCase()}:`);
        STRATEGIES.forEach(strategy => {
            const result = allResults[`${locale}_${strategy}`];
            if (result) {
                console.log(`  ${strategy.padEnd(8)}: Performance ${result.scores.performance}% | LCP ${result.coreWebVitals.LCP.displayValue.padEnd(6)} | CLS ${result.coreWebVitals.CLS.displayValue}`);
            } else {
                console.log(`  ${strategy.padEnd(8)}: FAILED`);
            }
        });
    });

    if (errors.length > 0) {
        console.log(`\n${errors.length} test(s) failed. Check the logs above for details.`);
    }

    console.log('\n----------------------------------------');
    console.log(`Reports saved to: ${REPORTS_DIR}`);
    console.log('----------------------------------------\n');
}

main().catch(error => {
    console.error('Fatal error:', error);
    process.exit(1);
});
