#!/usr/bin/env node

const http = require('http');
const https = require('https');
const fs = require('fs');
const path = require('path');

const API_BASE_URL = process.env.API_BASE_URL || 'http://localhost:8080';
const RESULTS_FILE = path.join(__dirname, '../performance-test-results.json');

class PerformanceTester {
    constructor(baseUrl) {
        this.baseUrl = baseUrl;
        this.results = [];
    }

    async testEndpoint(endpoint, method = 'GET', body = null) {
        const url = `${this.baseUrl}${endpoint}`;
        const startTime = Date.now();
        
        return new Promise((resolve, reject) => {
            const options = {
                method: method,
                headers: {
                    'Content-Type': 'application/json',
                }
            };

            if (body) {
                options.headers['Content-Length'] = Buffer.byteLength(JSON.stringify(body));
            }

            const protocol = url.startsWith('https') ? https : http;
            
            const req = protocol.request(url, options, (res) => {
                let data = '';
                
                res.on('data', (chunk) => {
                    data += chunk;
                });
                
                res.on('end', () => {
                    const endTime = Date.now();
                    const duration = endTime - startTime;
                    
                    resolve({
                        endpoint,
                        method,
                        statusCode: res.statusCode,
                        duration,
                        success: res.statusCode >= 200 && res.statusCode < 300,
                        dataSize: data.length
                    });
                });
            });

            req.on('error', (error) => {
                const endTime = Date.now();
                const duration = endTime - startTime;
                
                resolve({
                    endpoint,
                    method,
                    statusCode: 0,
                    duration,
                    success: false,
                    error: error.message
                });
            });

            if (body) {
                req.write(JSON.stringify(body));
            }
            
            req.end();
        });
    }

    async runLoadTest(endpoint, concurrentRequests = 10, totalRequests = 100) {
        console.log(`\n📊 开始负载测试: ${endpoint}`);
        console.log(`   并发数: ${concurrentRequests}`);
        console.log(`   总请求数: ${totalRequests}\n`);
        
        const results = [];
        const startTime = Date.now();
        
        for (let i = 0; i < totalRequests; i += concurrentRequests) {
            const batch = Math.min(concurrentRequests, totalRequests - i);
            const promises = [];
            
            for (let j = 0; j < batch; j++) {
                promises.push(this.testEndpoint(endpoint));
            }
            
            const batchResults = await Promise.all(promises);
            results.push(...batchResults);
            
            console.log(`   进度: ${Math.min(i + batch, totalRequests)}/${totalRequests} 请求已完成`);
        }
        
        const endTime = Date.now();
        const totalDuration = endTime - startTime;
        
        const successfulRequests = results.filter(r => r.success);
        const failedRequests = results.filter(r => !r.success);
        
        const durations = successfulRequests.map(r => r.duration);
        const avgDuration = durations.length > 0 ? durations.reduce((a, b) => a + b, 0) / durations.length : 0;
        const minDuration = durations.length > 0 ? Math.min(...durations) : 0;
        const maxDuration = durations.length > 0 ? Math.max(...durations) : 0;
        const p95Duration = this.calculatePercentile(durations, 95);
        const p99Duration = this.calculatePercentile(durations, 99);
        
        const throughput = (successfulRequests.length / totalDuration) * 1000;
        
        return {
            endpoint,
            concurrentRequests,
            totalRequests,
            successfulRequests: successfulRequests.length,
            failedRequests: failedRequests.length,
            successRate: (successfulRequests.length / totalRequests * 100).toFixed(2),
            totalDuration,
            avgDuration,
            minDuration,
            maxDuration,
            p95Duration,
            p99Duration,
            throughput: throughput.toFixed(2),
            results
        };
    }

    calculatePercentile(values, percentile) {
        if (values.length === 0) return 0;
        
        const sorted = [...values].sort((a, b) => a - b);
        const index = Math.ceil((percentile / 100) * sorted.length) - 1;
        return sorted[Math.max(0, index)];
    }

    async runPerformanceTests() {
        console.log('🚀 开始性能测试...\n');
        
        const endpoints = [
            { path: '/api/auth/login', method: 'POST', body: { username: 'admin', password: 'admin123' } },
            { path: '/api/users', method: 'GET' },
            { path: '/api/roles', method: 'GET' },
            { path: '/api/menus', method: 'GET' },
            { path: '/api/dicts', method: 'GET' },
        ];

        for (const endpoint of endpoints) {
            console.log(`\n📡 测试端点: ${endpoint.method} ${endpoint.path}`);
            
            const results = [];
            const iterations = 10;
            
            for (let i = 0; i < iterations; i++) {
                const result = await this.testEndpoint(endpoint.path, endpoint.method, endpoint.body);
                results.push(result);
                console.log(`   ${i + 1}/${iterations}: ${result.duration}ms - ${result.success ? '✅' : '❌'}`);
            }

            const durations = results.filter(r => r.success).map(r => r.duration);
            const avgDuration = durations.length > 0 ? durations.reduce((a, b) => a + b, 0) / durations.length : 0;
            const minDuration = durations.length > 0 ? Math.min(...durations) : 0;
            const maxDuration = durations.length > 0 ? Math.max(...durations) : 0;
            const successRate = (results.filter(r => r.success).length / results.length * 100).toFixed(2);

            this.results.push({
                endpoint: endpoint.path,
                method: endpoint.method,
                avgDuration,
                minDuration,
                maxDuration,
                successRate,
                status: this.evaluatePerformance(avgDuration)
            });
        }

        this.saveResults();
        this.printSummary();
    }

    evaluatePerformance(avgDuration) {
        if (avgDuration < 100) {
            return '🟢 优秀';
        } else if (avgDuration < 300) {
            return '🟡 良好';
        } else if (avgDuration < 500) {
            return '🟠 一般';
        } else {
            return '🔴 需要优化';
        }
    }

    saveResults() {
        const timestamp = new Date().toISOString();
        const data = {
            timestamp,
            performanceTests: this.results,
            loadTests: this.loadTestResults
        };

        const history = [];
        if (fs.existsSync(RESULTS_FILE)) {
            try {
                history.push(...JSON.parse(fs.readFileSync(RESULTS_FILE, 'utf8')));
            } catch (e) {
                console.warn('⚠️  无法解析历史结果文件');
            }
        }

        history.push(data);
        
        if (history.length > 20) {
            history.shift();
        }

        fs.writeFileSync(RESULTS_FILE, JSON.stringify(history, null, 2));
    }

    printSummary() {
        console.log('\n📊 性能测试摘要:');
        console.log('═══════════════════════════════════════');
        
        const table = this.results.map(r => ({
            端点: r.endpoint,
            方法: r.method,
            平均: `${r.avgDuration.toFixed(0)}ms`,
            最小: `${r.minDuration}ms`,
            最大: `${r.maxDuration}ms`,
            成功率: `${r.successRate}%`,
            状态: r.status
        }));

        console.table(table);

        if (this.loadTestResults) {
            console.log('\n📈 负载测试摘要:');
            console.log('═══════════════════════════════════════');
            
            const loadTable = this.loadTestResults.map(r => ({
                端点: r.endpoint,
                总请求: r.totalRequests,
                成功: r.successfulRequests,
                失败: r.failedRequests,
                成功率: `${r.successRate}%`,
                平均响应: `${r.avgDuration.toFixed(0)}ms`,
                P95: `${r.p95Duration.toFixed(0)}ms`,
                P99: `${r.p99Duration.toFixed(0)}ms`,
                吞吐量: `${r.throughput} req/s`
            }));

            console.table(loadTable);
        }

        console.log('\n💡 性能优化建议:');
        this.printRecommendations();
    }

    printRecommendations() {
        const slowEndpoints = this.results.filter(r => r.avgDuration > 300);
        if (slowEndpoints.length > 0) {
            console.log('   ⚠️  以下端点响应时间较长，建议优化:');
            slowEndpoints.forEach(r => {
                console.log(`      - ${r.endpoint}: ${r.avgDuration.toFixed(0)}ms`);
            });
        }

        const lowSuccessRate = this.results.filter(r => parseFloat(r.successRate) < 95);
        if (lowSuccessRate.length > 0) {
            console.log('   ⚠️  以下端点成功率较低，建议检查:');
            lowSuccessRate.forEach(r => {
                console.log(`      - ${r.endpoint}: ${r.successRate}%`);
            });
        }

        if (slowEndpoints.length === 0 && lowSuccessRate.length === 0) {
            console.log('   ✅ 所有端点性能良好，无需优化');
        }
    }

    async runLoadTests() {
        console.log('\n📊 开始负载测试...\n');
        
        const endpoints = ['/api/users', '/api/roles', '/api/menus'];
        this.loadTestResults = [];

        for (const endpoint of endpoints) {
            const result = await this.runLoadTest(endpoint, 10, 100);
            this.loadTestResults.push(result);
            
            console.log(`\n📈 ${endpoint} 负载测试结果:`);
            console.log(`   成功率: ${result.successRate}%`);
            console.log(`   平均响应时间: ${result.avgDuration.toFixed(0)}ms`);
            console.log(`   P95响应时间: ${result.p95Duration.toFixed(0)}ms`);
            console.log(`   P99响应时间: ${result.p99Duration.toFixed(0)}ms`);
            console.log(`   吞吐量: ${result.throughput} req/s`);
        }

        this.saveResults();
    }
}

async function main() {
    const tester = new PerformanceTester(API_BASE_URL);
    
    const command = process.argv[2];
    
    switch (command) {
        case 'performance':
            await tester.runPerformanceTests();
            break;
        case 'load':
            await tester.runLoadTests();
            break;
        case 'all':
            await tester.runPerformanceTests();
            await tester.runLoadTests();
            break;
        default:
            console.log('使用方法:');
            console.log('  node scripts/performance-test.js performance  - 运行性能测试');
            console.log('  node scripts/performance-test.js load         - 运行负载测试');
            console.log('  node scripts/performance-test.js all          - 运行所有测试');
            console.log('\n环境变量:');
            console.log('  API_BASE_URL - API基础URL (默认: http://localhost:8080)');
    }
}

if (require.main === module) {
    main();
}

module.exports = PerformanceTester;
