package com.mosquito.project.performance;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Tag;

import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 超简化的性能测试
 * 专注于核心性能指标验证
 */
@DisplayName("性能测试")
@EnabledIfSystemProperty(named = "performance.test.enabled", matches = "true")
@Tag("performance")
class UltraSimplePerformanceTest {

    @Test
    @DisplayName("响应时间测试")
    void shouldMeasureResponseTime_BasicTest() throws InterruptedException {
        // Given
        long startTime = System.nanoTime();
        
        // When
        Thread.sleep(50);
        
        long endTime = System.nanoTime();
        long responseTimeMs = (endTime - startTime) / 1_000_000;
        
        // Then
        System.out.println("响应时间: " + responseTimeMs + "ms");
        assertTrue(responseTimeMs >= 40, "响应时间应该至少40ms");
        assertTrue(responseTimeMs <= 200, "响应时间不应该超过200ms");
    }

    @Test
    @DisplayName("并发测试")
    void shouldHandleConcurrency_ConcurrencyTest() throws InterruptedException {
        // Given
        int threadCount = 3;
        CountDownLatch latch = new CountDownLatch(threadCount);
        ExecutorService executor = Executors.newFixedThreadPool(threadCount);
        
        // When
        long startTime = System.currentTimeMillis();
        
        for (int i = 0; i < threadCount; i++) {
            final int threadId = i;
            executor.submit(() -> {
                try {
                    System.out.println("线程 " + threadId + " 开始");
                    Thread.sleep(100);
                    System.out.println("线程 " + threadId + " 完成");
                } catch (Exception e) {
                    System.err.println("线程 " + threadId + " 异常: " + e.getMessage());
                } finally {
                    latch.countDown();
                }
            });
        }
        
        latch.await(5, TimeUnit.SECONDS);
        long endTime = System.currentTimeMillis();
        
        // Then
        long totalTime = endTime - startTime;
        System.out.println("并发测试完成，总时间: " + totalTime + "ms");
        assertTrue(totalTime < 3000, "并发测试应该在5秒内完成");
    }

    @Test
    @DisplayName("内存测试")
    void shouldMonitorMemoryUsage_MemoryTest() {
        // Given
        Runtime runtime = Runtime.getRuntime();
        long initialMemory = runtime.totalMemory() - runtime.freeMemory();
        long initialMemoryMB = initialMemory / 1024 / 1024;
        
        // When
        byte[] memoryBlock = new byte[100000]; // 100KB
        
        // Then
        long peakMemory = runtime.totalMemory() - runtime.freeMemory();
        long peakMemoryMB = peakMemory / 1024 / 1024;
        long memoryUsedMB = (peakMemory - initialMemory) / 1024 / 1024;
        
        System.out.println("初始内存: " + initialMemoryMB + "MB");
        System.out.println("峰值内存: " + peakMemoryMB + "MB");
        System.out.println("使用内存: " + memoryUsedMB + "MB");
        
        assertTrue(memoryUsedMB >= 0, "内存使用不应为负数");
        assertTrue(memoryUsedMB < 200, "内存使用应该在200MB以内");
        
        // 清理
        memoryBlock = null;
        System.gc();
        
        long finalMemory = runtime.totalMemory() - runtime.freeMemory();
        long finalMemoryMB = finalMemory / 1024 / 1024;
        assertTrue(finalMemoryMB <= initialMemoryMB + 50, "内存应该基本恢复");
    }

    @Test
    @DisplayName("吞吐量测试")
    void shouldMeasureThroughput_ThroughputTest() throws InterruptedException {
        // Given
        int durationSeconds = 1;
        int targetOpsPerSecond = 50;
        
        long startTime = System.currentTimeMillis();
        
        AtomicInteger completedOperations = new AtomicInteger(0);
        
        while (System.currentTimeMillis() < startTime + durationSeconds * 1000) {
            completedOperations.incrementAndGet();
            Thread.sleep(20);
        }
        
        long endTime = System.currentTimeMillis();
        double actualOpsPerSecond = (double) completedOperations.get() / (endTime - startTime) * 1000;
        
        // Then
        System.out.println("计划操作数: " + (durationSeconds * targetOpsPerSecond));
        System.out.println("完成操作数: " + completedOperations.get());
        System.out.println("实际吞吐量: " + String.format("%.2f", actualOpsPerSecond) + " ops/s");
        
        assertTrue(actualOpsPerSecond >= targetOpsPerSecond * 0.9, "吞吐量应该达到目标的90%");
    }
}
