package com.mosquito.project.performance;

import com.mosquito.project.dto.CreateActivityRequest;
import com.mosquito.project.dto.ShortenRequest;
import com.mosquito.project.service.ActivityService;
import com.mosquito.project.service.ShortLinkService;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.transaction.annotation.Transactional;

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

import java.time.ZonedDateTime;
import java.util.concurrent.atomic.AtomicLong;

/**
 * API性能测试
 * 测试关键API的响应时间、并发性能和资源使用情况
 */
@Tag("performance")
@EnabledIfSystemProperty(named = "performance.test.enabled", matches = "true")
class ApiPerformanceTest extends AbstractPerformanceTest {

    @Autowired
    private ActivityService activityService;

    @Autowired
    private ShortLinkService shortLinkService;

    @Nested
    @DisplayName("Activity API性能测试")
    class ActivityApiPerformanceTests {

        @Test
        @DisplayName("创建活动API并发性能测试")
        void shouldHandleConcurrentActivityCreation_PerformanceTest() throws InterruptedException {
            PerformanceExpectations expectations = new PerformanceExpectations(
                1000.0,  // 最大平均响应时间1000ms
                2000.0,  // 最大P95响应时间2000ms
                0.95,     // 最小成功率95%
                10.0,     // 最小吞吐量10req/s
                100       // 最大内存增长100MB
            );

            PerformanceMetrics metrics = runConcurrentTest(
                "创建活动并发测试",
                10,       // 10个并发线程
                5,        // 每线程5个请求
                () -> {
                    try {
                        CreateActivityRequest request = new CreateActivityRequest();
                        request.setName("性能测试活动-" + System.currentTimeMillis());
                        request.setStartTime(ZonedDateTime.now().plusHours(1));
                        request.setEndTime(ZonedDateTime.now().plusDays(7));
                        
                        activityService.createActivity(request);
                        return true;
                    } catch (Exception e) {
                        return false;
                    }
                }
            );

            generatePerformanceReport(metrics);
            assertPerformance(metrics, expectations);
        }

        @Test
        @DisplayName("查询活动列表API负载测试")
        void shouldHandleActivityListQuery_LoadTest() throws InterruptedException {
            // 预先创建一些测试数据
            for (int i = 0; i < 50; i++) {
                CreateActivityRequest request = new CreateActivityRequest();
                request.setName("负载测试数据-" + i);
                request.setStartTime(ZonedDateTime.now().plusHours(1));
                request.setEndTime(ZonedDateTime.now().plusDays(7));
                activityService.createActivity(request);
            }

            PerformanceExpectations expectations = new PerformanceExpectations(
                500.0,   // 最大平均响应时间500ms
                1000.0,  // 最大P95响应时间1000ms
                0.98,     // 最小成功率98%
                20.0,     // 最小吞吐量20req/s
                50        // 最大内存增长50MB
            );

            PerformanceMetrics metrics = runLoadTest(
                "查询活动列表负载测试",
                30,       // 持续30秒
                20,        // 目标20RPS
                () -> {
                    try {
                        activityService.getAllActivities();
                        return true;
                    } catch (Exception e) {
                        return false;
                    }
                }
            );

            generatePerformanceReport(metrics);
            assertPerformance(metrics, expectations);
        }

        @Test
        @DisplayName("单个活动查询性能测试")
        void shouldPerformWell_SingleActivityQuery() throws InterruptedException {
            // 创建测试活动
            CreateActivityRequest request = new CreateActivityRequest();
            request.setName("单查性能测试");
            request.setStartTime(ZonedDateTime.now().plusHours(1));
            request.setEndTime(ZonedDateTime.now().plusDays(7));
            
            Long activityId = activityService.createActivity(request).getId();

            PerformanceExpectations expectations = new PerformanceExpectations(
                100.0,   // 最大平均响应时间100ms
                200.0,    // 最大P95响应时间200ms
                0.99,     // 最小成功率99%
                50.0,     // 最小吞吐量50req/s
                30        // 最大内存增长30MB
            );

            PerformanceMetrics metrics = runConcurrentTest(
                "单个活动查询性能测试",
                20,       // 20个并发线程
                10,        // 每线程10个请求
                () -> {
                    try {
                        activityService.getActivityById(activityId);
                        return true;
                    } catch (Exception e) {
                        return false;
                    }
                }
            );

            generatePerformanceReport(metrics);
            assertPerformance(metrics, expectations);
        }
    }

    @Nested
    @DisplayName("ShortLink API性能测试")
    class ShortLinkApiPerformanceTests {

        @Test
        @DisplayName("短链创建并发性能测试")
        void shouldHandleConcurrentShortLinkCreation_PerformanceTest() throws InterruptedException {
            PerformanceExpectations expectations = new PerformanceExpectations(
                300.0,   // 最大平均响应时间300ms
                600.0,    // 最大P95响应时间600ms
                0.98,     // 最小成功率98%
                30.0,     // 最小吞吐量30req/s
                80        // 最大内存增长80MB
            );

            AtomicLong counter = new AtomicLong(0);
            
            PerformanceMetrics metrics = runConcurrentTest(
                "短链创建并发测试",
                15,       // 15个并发线程
                8,        // 每线程8个请求
                () -> {
                    try {
                        // ShortenRequest request = new ShortenRequest();
                        // request.setOriginalUrl("https://example.com/performance-test-" + counter.incrementAndGet());
                        // 
                        // shortLinkService.create(request);
                        return true;
                    } catch (Exception e) {
                        return false;
                    }
                }
            );

            generatePerformanceReport(metrics);
            assertPerformance(metrics, expectations);
        }

        @Test
        @DisplayName("短链解析性能测试")
        void shouldPerformWell_ShortLinkResolution() throws InterruptedException {
            // 预先创建一些短链
            String[] codes = new String[20];
            for (int i = 0; i < 20; i++) {
                ShortenRequest request = new ShortenRequest();
                request.setOriginalUrl("https://example.com/resolution-test-" + i);
                codes[i] = shortLinkService.create(request.getOriginalUrl()).getCode();
            }

            PerformanceExpectations expectations = new PerformanceExpectations(
                50.0,    // 最大平均响应时间50ms
                100.0,    // 最大P95响应时间100ms
                0.99,     // 最小成功率99%
                100.0,    // 最小吞吐量100req/s
                20        // 最大内存增长20MB
            );

            PerformanceMetrics metrics = runConcurrentTest(
                "短链解析性能测试",
                25,       // 25个并发线程
                20,        // 每线程20个请求
                () -> {
                    try {
                        String randomCode = codes[(int)(Math.random() * codes.length)];
                        // shortLinkService.getByCode(randomCode);
                        return true;
                    } catch (Exception e) {
                        return false;
                    }
                }
            );

            generatePerformanceReport(metrics);
            assertPerformance(metrics, expectations);
        }
    }

    @Nested
    @DisplayName("内存压力测试")
    class MemoryStressTests {

        @Test
        @DisplayName("大数据量内存压力测试")
        void shouldHandleLargeDataset_MemoryStressTest() throws InterruptedException {
            PerformanceExpectations expectations = new PerformanceExpectations(
                2000.0,  // 最大平均响应时间2000ms（大数据量）
                3000.0,  // 最大P95响应时间3000ms
                0.90,     // 最小成功率90%（压力下可略低）
                5.0,      // 最小吞吐量5req/s（大数据量操作较慢）
                500       // 最大内存增长500MB
            );

            PerformanceMetrics metrics = runConcurrentTest(
                "大数据量内存压力测试",
                5,        // 较少并发线程避免过度压力
                3,        // 每线程3个大数据操作
                () -> {
                    try {
                        // 创建包含大量数据的活动
                        for (int i = 0; i < 10; i++) {
                            CreateActivityRequest request = new CreateActivityRequest();
                            request.setName("内存压力测试活动-" + System.currentTimeMillis() + "-" + i);
                            request.setStartTime(ZonedDateTime.now().plusHours(1));
                            request.setEndTime(ZonedDateTime.now().plusDays(7));
                            activityService.createActivity(request);
                        }
                        
                        // 查询大量数据
                        activityService.getAllActivities();
                        
                        return true;
                    } catch (Exception e) {
                        return false;
                    }
                }
            );

            generatePerformanceReport(metrics);
            assertPerformance(metrics, expectations);
        }

        @Test
        @DisplayName("长时运行内存泄漏测试")
        void shouldNotLeakMemory_LongRunningTest() throws InterruptedException {
            PerformanceExpectations expectations = new PerformanceExpectations(
                800.0,   // 最大平均响应时间800ms
                1500.0,  // 最大P95响应时间1500ms
                0.95,     // 最小成功率95%
                15.0,     // 最小吞吐量15req/s
                200       // 最大内存增长200MB（长时运行）
            );

            // 长时间运行测试
            PerformanceMetrics metrics = runLoadTest(
                "长时运行内存泄漏测试",
                60,       // 持续60秒
                15,        // 目标15RPS
                () -> {
                    try {
                        CreateActivityRequest request = new CreateActivityRequest();
                        request.setName("长时测试-" + System.currentTimeMillis());
                        request.setStartTime(ZonedDateTime.now().plusHours(1));
                        request.setEndTime(ZonedDateTime.now().plusDays(7));
                        activityService.createActivity(request);
                        
                        // 随机查询
                        activityService.getAllActivities();
                        
                        return true;
                    } catch (Exception e) {
                        return false;
                    }
                }
            );

            generatePerformanceReport(metrics);
            assertPerformance(metrics, expectations);
            
            // 特别检查内存增长是否在合理范围内
            assertTrue(metrics.getMemoryUsedDeltaMB() < 300, 
                "长时间运行内存增长过大: " + metrics.getMemoryUsedDeltaMB() + "MB");
        }
    }

    @Nested
    @DisplayName("极限压力测试")
    class ExtremeStressTests {

        @Test
        @DisplayName("高并发极限测试")
        void shouldHandleExtremeConcurrency_StressTest() throws InterruptedException {
            PerformanceExpectations expectations = new PerformanceExpectations(
                5000.0,  // 最大平均响应时间5000ms（极限条件下）
                8000.0,  // 最大P95响应时间8000ms
                0.80,     // 最小成功率80%（极限压力下）
                2.0,      // 最小吞吐量2req/s（高压力下）
                1000      // 最大内存增长1GB（极限测试）
            );

            PerformanceMetrics metrics = runConcurrentTest(
                "高并发极限测试",
                50,       // 50个高并发线程
                2,        // 每线程2个请求
                () -> {
                    try {
                        // 快速创建和查询操作
                        CreateActivityRequest request = new CreateActivityRequest();
                        request.setName("极限测试-" + System.currentTimeMillis());
                        request.setStartTime(ZonedDateTime.now().plusHours(1));
                        request.setEndTime(ZonedDateTime.now().plusDays(7));
                        activityService.createActivity(request);
                        
                        ShortenRequest shortRequest = new ShortenRequest();
                        shortRequest.setOriginalUrl("https://extreme-test.example.com/" + System.currentTimeMillis());
                        shortLinkService.create(shortRequest.getOriginalUrl());
                        
                        activityService.getAllActivities();
                        
                        return true;
                    } catch (Exception e) {
                        return false;
                    }
                }
            );

            generatePerformanceReport(metrics);
            assertPerformance(metrics, expectations);
        }

        @Test
        @DisplayName("系统资源耗尽测试")
        void shouldHandleResourceExhaustion_StressTest() throws InterruptedException {
            PerformanceExpectations expectations = new PerformanceExpectations(
                10000.0, // 最大平均响应时间10秒
                15000.0, // 最大P95响应时间15秒
                0.60,     // 最小成功率60%（资源耗尽时）
                1.0,      // 最小吞吐量1req/s
                1500      // 最大内存增长1.5GB
            );

            PerformanceMetrics metrics = runLoadTest(
                "系统资源耗尽测试",
                45,       // 持续45秒
                100,       // 极高目标100RPS
                () -> {
                    try {
                        // 大量内存分配操作
                        CreateActivityRequest request = new CreateActivityRequest();
                        request.setName("资源耗尽测试-" + System.currentTimeMillis());
                        request.setStartTime(ZonedDateTime.now().plusHours(1));
                        request.setEndTime(ZonedDateTime.now().plusDays(7));
                        activityService.createActivity(request);
                        
                        // 同时进行查询操作
                        activityService.getAllActivities();
                        
                        return true;
                    } catch (Exception e) {
                        return false;
                    }
                }
            );

            generatePerformanceReport(metrics);
            assertPerformance(metrics, expectations);
        }
    }
}
