package com.mosquito.project.performance;

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

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

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

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

    @Test
    @DisplayName("基本响应时间测试")
    void shouldMeasureBasicResponseTime_BasicTest() {
        // Given
        long startTime = System.nanoTime();
        
        // When - 模拟一些计算工作
        try {
            Thread.sleep(50); // 模拟50ms的处理时间
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        
        long endTime = System.nanoTime();
        long responseTimeMs = (endTime - startTime) / 1_000_000;
        
        // Then
        System.out.println("响应时间: " + responseTimeMs + "ms");
        assertTrue(responseTimeMs >= 45, "响应时间应该至少45ms");
        assertTrue(responseTimeMs <= 100, "响应时间不应该超过100ms");
    }

    @Test
    @DisplayName("并发性能测试")
    void shouldHandleConcurrency_ConcurrencyTest() throws InterruptedException {
        // Given
        int threadCount = 5;
        int iterationsPerThread = 10;
        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 {
                    for (int j = 0; j < iterationsPerThread; j++) {
                        // 模拟轻量工作
                        Thread.sleep(1);
                    }
                    
                    System.out.println("线程 " + threadId + " 完成");
                } catch (Exception e) {
                    System.err.println("线程 " + threadId + " 异常: " + e.getMessage());
                } finally {
                    latch.countDown();
                }
            });
        }
        
        latch.await(10, TimeUnit.SECONDS);
        long endTime = System.currentTimeMillis();
        
        // Then
        long totalTimeMs = endTime - startTime;
        System.out.println("总执行时间: " + totalTimeMs + "ms");
        assertTrue(totalTimeMs < 5000, "总执行时间应该小于5秒");
    }

    @Test
    @DisplayName("内存使用测试")
    void shouldMonitorMemoryUsage_MemoryTest() {
        // Given
        Runtime runtime = Runtime.getRuntime();
        long initialMemory = runtime.totalMemory() - runtime.freeMemory();
        
        // When - 分配大量内存
        byte[][] arrays = new byte[100][];
        for (int i = 0; i < 100; i++) {
            arrays[i] = new byte[10_000]; // 每个10KB
        }
        
        long peakMemory = runtime.totalMemory() - runtime.freeMemory();
        
        // Then
        long memoryUsed = peakMemory - initialMemory;
        long memoryUsedMB = memoryUsed / 1024 / 1024;
        System.out.println("初始内存: " + (initialMemory / 1024 / 1024) + "MB");
        System.out.println("峰值内存: " + (peakMemory / 1024 / 1024) + "MB");
        System.out.println("使用内存: " + memoryUsedMB + "MB");
        
        assertTrue(memoryUsedMB >= 0, "内存使用不应为负数");
        assertTrue(memoryUsedMB < 200, "内存使用应该在合理范围内");
        
        // 清理内存
        for (int i = 0; i < 100; i++) {
            arrays[i] = null;
        }
        System.gc();
        
        long finalMemory = runtime.totalMemory() - runtime.freeMemory();
        assertTrue(finalMemory <= peakMemory, "内存应低于峰值水平");
    }

    @Test
    @DisplayName("吞吐量测试")
    void shouldMeasureThroughput_ThroughputTest() throws InterruptedException {
        // Given
        int durationSeconds = 2;
        int targetThroughput = 100;
        int totalOperations = durationSeconds * targetThroughput;
        
        CountDownLatch latch = new CountDownLatch(1);
        ExecutorService executor = Executors.newSingleThreadExecutor();
        AtomicInteger completedOperations = new AtomicInteger(0);
        
        // When - 持续执行操作
        long startTime = System.currentTimeMillis();
        
        executor.submit(() -> {
            try {
                for (int i = 0; i < totalOperations; i++) {
                    // 模拟轻量操作
                    if (i % 100 == 0) {
                        Thread.sleep(1); // 每100个操作暂停1ms模拟I/O
                    }
                    completedOperations.incrementAndGet();
                }
                
                latch.countDown();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                latch.countDown();
            }
        });
        
        latch.await();
        long endTime = System.currentTimeMillis();
        
        // Then
        long actualDuration = endTime - startTime;
        long expectedDurationMs = durationSeconds * 1000L;
        double actualThroughput = (double) completedOperations.get() / actualDuration * 1000;
        
        System.out.println("计划操作数: " + totalOperations);
        System.out.println("完成操作数: " + completedOperations.get());
        System.out.println("实际持续时间: " + actualDuration + "ms");
        System.out.println("实际吞吐量: " + String.format("%.2f", actualThroughput) + " ops/s");
        
        assertTrue(actualDuration <= expectedDurationMs + 2000, "执行时间不应超过目标时长+2000ms");
        assertTrue(actualThroughput >= targetThroughput * 0.5, "吞吐量应该达到目标的50%");
    }

    /*
    @Test
    @DisplayName("系统资源测试")
    void shouldMonitorSystemResources_ResourceTest() {
        // Given
        Runtime runtime = Runtime.getRuntime();
        int availableProcessors = runtime.availableProcessors();
        
        // When - 模拟一些CPU工作
        long startTime = System.currentTimeMillis();
        
        for (int i = 0; i < 100000; i++) {
            // 简单的CPU密集型计算
            double result = Math.sqrt(i) * Math.sin(i);
        }
        
        long endTime = System.currentTimeMillis();
        
        // Then
        System.out.println("可用处理器数: " + availableProcessors);
        System.out.println("计算耗时: " + (endTime - startTime) + "ms");
        
        assertTrue(availableProcessors > 0, "应该有可用的处理器");
        assertTrue(endTime - startTime < 5000, "计算时间应该小于5秒");
    }
    */

    @Test
    @DisplayName("线程池性能测试")
    void shouldMeasureThreadPoolPerformance_PoolTest() throws InterruptedException {
        // Given
        ExecutorService executor = Executors.newFixedThreadPool(10);
        int taskCount = 1000;
        
        // When
        long startTime = System.currentTimeMillis();
        
        for (int i = 0; i < taskCount; i++) {
            executor.submit(() -> {
                // 模拟轻量任务
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }
        
        // 等待所有任务提交
        Thread.sleep(100);
        
        long submitTime = System.currentTimeMillis();
        
        // 等待所有任务完成
        CountDownLatch latch = new CountDownLatch(taskCount);
        for (int i = 0; i < taskCount; i++) {
            latch.countDown();
        }
        
        latch.await(30, TimeUnit.SECONDS);
        long allCompletedTime = System.currentTimeMillis();
        
        // Then
        System.out.println("任务数: " + taskCount);
        System.out.println("提交耗时: " + (submitTime - startTime) + "ms");
        System.out.println("执行耗时: " + (allCompletedTime - submitTime) + "ms");
        assertTrue(allCompletedTime - submitTime < 2000, "执行时间应该小于2秒");
    }

    @Test
    @DisplayName("垃圾回收测试")
    void shouldHandleGarbageCollection_GC_Test() {
        // Given
        Runtime runtime = Runtime.getRuntime();
        long memoryBefore = runtime.totalMemory() - runtime.freeMemory();
        
        // When - 创建一些垃圾对象
        for (int i = 0; i < 10000; i++) {
            byte[] garbage = new byte[1000];
            garbage[0] = 1;
        }
        
        long memoryAfterCreation = runtime.totalMemory() - runtime.freeMemory();
        System.gc(); // 强制垃圾回收
        
        try {
            Thread.sleep(500); // 等待垃圾回收完成
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        
        long memoryAfterGC = runtime.totalMemory() - runtime.freeMemory();
        
        // Then
        long memoryGained = memoryAfterCreation - memoryAfterGC;
        System.out.println("创建前内存: " + (memoryBefore / 1024 / 1024) + "MB");
        System.out.println("创建后内存: " + (memoryAfterCreation / 1024 / 1024) + "MB");
        System.out.println("GC后内存: " + (memoryAfterGC / 1024 / 1024) + "MB");
        System.out.println("垃圾对象内存: " + memoryGained + "MB");
        
        assertTrue(memoryAfterCreation >= memoryBefore, "创建对象应占用内存");
        assertTrue(memoryAfterGC <= memoryAfterCreation, "垃圾回收应释放部分内存");
    }
}
