import { FullConfig, FullResult, Reporter, Suite, TestCase, TestResult } from '@playwright/test/reporter';
import * as fs from 'fs';
import * as path from 'path';

class CustomReporter implements Reporter {
  private results: Map<string, TestCase[]> = new Map();
  private suiteResults: Map<string, Suite> = new Map();
  private startTime: number = Date.now();
  private testResults: TestResult[] = [];

  onBegin(config: FullConfig) {
    console.log(`🚀 开始测试执行: ${config.projects.map(p => p.name).join(', ')}`);
    this.startTime = Date.now();
  }

  onTestBegin(test: TestCase, result: TestResult) {
    console.log(`📝 开始测试: ${test.title}`);
  }

  onTestEnd(test: TestCase, result: TestResult) {
    console.log(`✅ 测试完成: ${test.title} - ${result.status}`);
    this.testResults.push(result);
  }

  onEnd(result: FullResult) {
    const endTime = Date.now();
    const duration = endTime - this.startTime;

    console.log(`🎉 测试执行完成`);
    console.log(`⏱️  总耗时: ${this.formatDuration(duration)}`);

    const stats = this.calculateStats(result);
    this.generateConsoleReport(stats);
    this.generateHtmlReport(result, stats);
    this.generateJsonReport(result, stats);
  }

  private calculateStats(result: FullResult): TestStats {
    const suites = result.suites || [];
    const allTests = suites.flatMap(suite => 
      suite.specs.flatMap(spec => spec.tests)
    );

    const passed = allTests.filter(t => t.status === 'passed');
    const failed = allTests.filter(t => t.status === 'failed');
    const skipped = allTests.filter(t => t.status === 'skipped');
    const flaky = allTests.filter(t => t.status === 'passed' && t.retry >= 1);

    const totalDuration = allTests.reduce((sum, t) => sum + (t.duration || 0), 0);
    const avgDuration = totalDuration / allTests.length;

    const passRate = (passed.length / allTests.length) * 100;
    const failRate = (failed.length / allTests.length) * 100;
    const skipRate = (skipped.length / allTests.length) * 100;
    const flakyRate = (flaky.length / allTests.length) * 100;

    return {
      total: allTests.length,
      passed: passed.length,
      failed: failed.length,
      skipped: skipped.length,
      flaky: flaky.length,
      passRate,
      failRate,
      skipRate,
      flakyRate,
      totalDuration,
      avgDuration,
      slowestTests: allTests
        .filter(t => t.duration)
        .sort((a, b) => (b.duration || 0) - (a.duration || 0))
        .slice(0, 10),
      failedTests: failed,
    };
  }

  private generateConsoleReport(stats: TestStats) {
    console.log('');
    console.log('═══════════════════════════════════════════');
    console.log('📊 测试统计报告');
    console.log('═══════════════════════════════════════════');
    console.log('');
    console.log(`📈 总测试数: ${stats.total}`);
    console.log(`✅ 通过: ${stats.passed} (${stats.passRate.toFixed(2)}%)`);
    console.log(`❌ 失败: ${stats.failed} (${stats.failRate.toFixed(2)}%)`);
    console.log(`⏭️ 跳过: ${stats.skipped} (${stats.skipRate.toFixed(2)}%)`);
    console.log(`🔄 不稳定: ${stats.flaky} (${stats.flakyRate.toFixed(2)}%)`);
    console.log('');
    console.log(`⏱️  总耗时: ${this.formatDuration(stats.totalDuration)}`);
    console.log(`⏱️  平均耗时: ${this.formatDuration(stats.avgDuration)}`);
    console.log('');
    console.log('🐌 最慢的10个测试:');
    stats.slowestTests.forEach((test, index) => {
      console.log(`  ${index + 1}. ${test.title} - ${this.formatDuration(test.duration || 0)}`);
    });
    console.log('');

    if (stats.failedTests.length > 0) {
      console.log('❌ 失败的测试:');
      stats.failedTests.forEach((test, index) => {
        console.log(`  ${index + 1}. ${test.title}`);
        console.log(`     位置: ${test.location.file}:${test.location.line}`);
        console.log(`     错误: ${test.error?.message}`);
      });
      console.log('');
    }
  }

  private generateHtmlReport(result: FullResult, stats: TestStats) {
    const html = `
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>测试报告 - Novalon管理系统</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
            margin: 0;
            padding: 20px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        }
        .container {
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            border-radius: 10px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
            padding: 30px;
        }
        .header {
            text-align: center;
            margin-bottom: 30px;
            padding-bottom: 20px;
            border-bottom: 2px solid #e0e0e0;
        }
        .header h1 {
            margin: 0;
            color: #333;
            font-size: 28px;
        }
        .stats-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 20px;
            margin-bottom: 30px;
        }
        .stat-card {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 20px;
            border-radius: 10px;
            text-align: center;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
        }
        .stat-card h3 {
            margin: 0 0 10px 0;
            font-size: 14px;
            opacity: 0.9;
        }
        .stat-card .value {
            font-size: 32px;
            font-weight: bold;
            margin: 0;
        }
        .stat-card .label {
            font-size: 12px;
            opacity: 0.8;
            margin-top: 5px;
        }
        .stat-card.passed {
            background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);
        }
        .stat-card.failed {
            background: linear-gradient(135deg, #ef4444 0%, #f44336 100%);
        }
        .stat-card.flaky {
            background: linear-gradient(135deg, #f59e0b 0%, #f093fb 100%);
        }
        .section {
            margin-bottom: 30px;
        }
        .section h2 {
            color: #333;
            border-bottom: 2px solid #667eea;
            padding-bottom: 10px;
            margin-bottom: 20px;
        }
        .test-list {
            list-style: none;
            padding: 0;
        }
        .test-item {
            padding: 15px;
            margin-bottom: 10px;
            border-left: 4px solid #ddd;
            background: #f9f9f9;
            border-radius: 5px;
        }
        .test-item.passed {
            border-left-color: #38ef7d;
            background: #f0fff4;
        }
        .test-item.failed {
            border-left-color: #ef4444;
            background: #fff5f5;
        }
        .test-item.skipped {
            border-left-color: #f59e0b;
            background: #fef9c3;
        }
        .test-item.flaky {
            border-left-color: #f093fb;
            background: #fef3c7;
        }
        .test-item .test-name {
            font-weight: bold;
            margin-bottom: 5px;
            color: #333;
        }
        .test-item .test-duration {
            color: #666;
            font-size: 12px;
        }
        .test-item .test-error {
            color: #ef4444;
            font-size: 12px;
            margin-top: 5px;
            padding: 10px;
            background: #fee;
            border-radius: 3px;
        }
        .progress-bar {
            height: 20px;
            background: #e0e0e0;
            border-radius: 10px;
            overflow: hidden;
            margin: 20px 0;
        }
        .progress-bar-fill {
            height: 100%;
            background: linear-gradient(90deg, #11998e 0%, #38ef7d 100%);
            transition: width 0.5s ease;
        }
        .footer {
            text-align: center;
            margin-top: 30px;
            padding-top: 20px;
            border-top: 1px solid #e0e0e0;
            color: #666;
            font-size: 12px;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🧪 Novalon管理系统测试报告</h1>
            <p>生成时间: ${new Date().toLocaleString('zh-CN')}</p>
        </div>

        <div class="stats-grid">
            <div class="stat-card passed">
                <h3>通过测试</h3>
                <div class="value">${stats.passed}</div>
                <div class="label">${stats.passRate.toFixed(2)}%</div>
            </div>
            <div class="stat-card failed">
                <h3>失败测试</h3>
                <div class="value">${stats.failed}</div>
                <div class="label">${stats.failRate.toFixed(2)}%</div>
            </div>
            <div class="stat-card flaky">
                <h3>不稳定测试</h3>
                <div class="value">${stats.flaky}</div>
                <div class="label">${stats.flakyRate.toFixed(2)}%</div>
            </div>
            <div class="stat-card">
                <h3>总测试数</h3>
                <div class="value">${stats.total}</div>
                <div class="label">100%</div>
            </div>
        </div>

        <div class="progress-bar">
            <div class="progress-bar-fill" style="width: ${stats.passRate}%"></div>
        </div>

        <div class="section">
            <h2>📈 测试统计</h2>
            <ul class="test-list">
                <li class="test-item">
                    <div class="test-name">总耗时</div>
                    <div class="test-duration">${this.formatDuration(stats.totalDuration)}</div>
                </li>
                <li class="test-item">
                    <div class="test-name">平均耗时</div>
                    <div class="test-duration">${this.formatDuration(stats.avgDuration)}</div>
                </li>
                <li class="test-item">
                    <div class="test-name">跳过测试</div>
                    <div class="test-duration">${stats.skipped} (${stats.skipRate.toFixed(2)}%)</div>
                </li>
            </ul>
        </div>

        ${stats.failedTests.length > 0 ? `
        <div class="section">
            <h2>❌ 失败测试详情</h2>
            <ul class="test-list">
                ${stats.failedTests.map(test => `
                    <li class="test-item failed">
                        <div class="test-name">${test.title}</div>
                        <div class="test-duration">${this.formatDuration(test.duration || 0)}</div>
                        <div class="test-error">
                            <strong>错误:</strong> ${test.error?.message || '未知错误'}
                        </div>
                    </li>
                `).join('')}
            </ul>
        </div>
        ` : ''}

        <div class="section">
            <h2>🐌 最慢的10个测试</h2>
            <ul class="test-list">
                ${stats.slowestTests.map((test, index) => `
                    <li class="test-item ${test.status}">
                        <div class="test-name">${index + 1}. ${test.title}</div>
                        <div class="test-duration">${this.formatDuration(test.duration || 0)}</div>
                    </li>
                `).join('')}
            </ul>
        </div>

        <div class="footer">
            <p>🧪 Novalon管理系统 - 自动化测试报告</p>
            <p>生成时间: ${new Date().toLocaleString('zh-CN')}</p>
        </div>
    </div>
</body>
</html>
    `;

    const reportPath = path.join(process.cwd(), 'test-results', 'custom-report.html');
    fs.writeFileSync(reportPath, html, 'utf-8');
    console.log(`📄 HTML报告已生成: ${reportPath}`);
  }

  private generateJsonReport(result: FullResult, stats: TestStats) {
    const report = {
      summary: {
        timestamp: new Date().toISOString(),
        total: stats.total,
        passed: stats.passed,
        failed: stats.failed,
        skipped: stats.skipped,
        flaky: stats.flaky,
        passRate: stats.passRate,
        failRate: stats.failRate,
        skipRate: stats.skipRate,
        flakyRate: stats.flakyRate,
        totalDuration: stats.totalDuration,
        avgDuration: stats.avgDuration,
      },
      failedTests: stats.failedTests.map(test => ({
        title: test.title,
        location: test.location,
        error: test.error?.message,
        duration: test.duration,
      })),
      slowestTests: stats.slowestTests.map(test => ({
        title: test.title,
        duration: test.duration,
      })),
    };

    const reportPath = path.join(process.cwd(), 'test-results', 'custom-report.json');
    fs.writeFileSync(reportPath, JSON.stringify(report, null, 2), 'utf-8');
    console.log(`📄 JSON报告已生成: ${reportPath}`);
  }

  private formatDuration(ms: number): string {
    if (ms < 1000) {
      return `${ms}ms`;
    } else if (ms < 60000) {
      return `${(ms / 1000).toFixed(1)}s`;
    } else {
      return `${(ms / 60000).toFixed(1)}m`;
    }
  }
}

interface TestStats {
  total: number;
  passed: number;
  failed: number;
  skipped: number;
  flaky: number;
  passRate: number;
  failRate: number;
  skipRate: number;
  flakyRate: number;
  totalDuration: number;
  avgDuration: number;
  slowestTests: TestCase[];
}

export default CustomReporter;
