#!/usr/bin/env node

/**
 * Node.js benchmark script for jdenticon-js using perf_hooks
 * Tests performance with JIT warm-up for fair comparison against Go implementation
 * Run with: node --expose-gc benchmark-js.js
 */

const fs = require('fs');
const path = require('path');
const { performance } = require('perf_hooks');

// Check if jdenticon-js is available
let jdenticon;
try {
    jdenticon = require('../jdenticon-js/dist/jdenticon-node.js');
} catch (err) {
    console.error('Error: jdenticon-js not found. Please ensure it\'s available in jdenticon-js/dist/');
    console.error('You may need to build the JS version first.');
    process.exit(1);
}

// --- Configuration ---
const ICON_SIZE = 64;
const WARMUP_RUNS = 3;

// Load test inputs
const inputsPath = path.join(__dirname, 'inputs.json');
if (!fs.existsSync(inputsPath)) {
    console.error('Error: inputs.json not found. Run generate-inputs.js first.');
    process.exit(1);
}

const inputs = JSON.parse(fs.readFileSync(inputsPath, 'utf8'));
const numInputs = inputs.length;

console.log('=== jdenticon-js Performance Benchmark ===');
console.log(`Inputs: ${numInputs} unique hash strings`);
console.log(`Icon size: ${ICON_SIZE}x${ICON_SIZE} pixels`);
console.log(`Format: SVG`);
console.log(`Node.js version: ${process.version}`);
console.log(`V8 version: ${process.versions.v8}`);
console.log('');

// --- Benchmark Function ---
function generateAllIcons() {
    for (let i = 0; i < numInputs; i++) {
        jdenticon.toSvg(inputs[i], ICON_SIZE);
    }
}

// --- Warm-up Phase ---
console.log(`Warming up JIT with ${WARMUP_RUNS} runs...`);
for (let i = 0; i < WARMUP_RUNS; i++) {
    console.log(`  Warm-up run ${i + 1}/${WARMUP_RUNS}`);
    generateAllIcons();
}

// Force garbage collection for clean baseline (if --expose-gc was used)
if (global.gc) {
    console.log('Forcing garbage collection...');
    global.gc();
} else {
    console.log('Note: Run with --expose-gc for more accurate memory measurements');
}

console.log('');

// --- Measurement Phase ---
console.log(`Running benchmark with ${numInputs} icons...`);

const memBefore = process.memoryUsage();
const startTime = performance.now();

generateAllIcons(); // The actual benchmark run

const endTime = performance.now();
const memAfter = process.memoryUsage();

// --- Calculate Metrics ---
const totalTimeMs = endTime - startTime;
const timePerIconMs = totalTimeMs / numInputs;
const timePerIconUs = timePerIconMs * 1000; // microseconds
const iconsPerSecond = 1000 / timePerIconMs;

// Memory metrics
const heapDelta = memAfter.heapUsed - memBefore.heapUsed;
const heapDeltaKB = heapDelta / 1024;
const heapDeltaPerIcon = heapDelta / numInputs;

// --- Results Report ---
console.log('');
console.log('=== jdenticon-js Results ===');
console.log(`Total time: ${totalTimeMs.toFixed(2)} ms`);
console.log(`Time per icon: ${timePerIconMs.toFixed(4)} ms (${timePerIconUs.toFixed(2)} μs)`);
console.log(`Throughput: ${iconsPerSecond.toFixed(2)} icons/sec`);
console.log('');
console.log('Memory Usage:');
console.log(`  Heap before: ${(memBefore.heapUsed / 1024).toFixed(2)} KB`);
console.log(`  Heap after: ${(memAfter.heapUsed / 1024).toFixed(2)} KB`);
console.log(`  Heap delta: ${heapDeltaKB.toFixed(2)} KB`);
console.log(`  Per icon: ${heapDeltaPerIcon.toFixed(2)} bytes`);
console.log('');
console.log('Additional Memory Info:');
console.log(`  RSS: ${(memAfter.rss / 1024 / 1024).toFixed(2)} MB`);
console.log(`  External: ${(memAfter.external / 1024).toFixed(2)} KB`);

// --- Save Results for Comparison ---
const results = {
    implementation: 'jdenticon-js',
    timestamp: new Date().toISOString(),
    nodeVersion: process.version,
    v8Version: process.versions.v8,
    config: {
        iconSize: ICON_SIZE,
        numInputs: numInputs,
        warmupRuns: WARMUP_RUNS
    },
    performance: {
        totalTimeMs: totalTimeMs,
        timePerIconMs: timePerIconMs,
        timePerIconUs: timePerIconUs,
        iconsPerSecond: iconsPerSecond
    },
    memory: {
        heapBeforeKB: memBefore.heapUsed / 1024,
        heapAfterKB: memAfter.heapUsed / 1024,
        heapDeltaKB: heapDeltaKB,
        heapDeltaPerIcon: heapDeltaPerIcon,
        rssKB: memAfter.rss / 1024,
        externalKB: memAfter.external / 1024
    }
};

const resultsPath = path.join(__dirname, 'results-js.json');
fs.writeFileSync(resultsPath, JSON.stringify(results, null, 2));
console.log(`Results saved to: ${resultsPath}`);

console.log('');
console.log('Run Go benchmark next: go test -bench=BenchmarkGenerate64pxIcon -benchmem ./...');