package com.rj.service;

import com.rj.config.MinIOConfig;
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.TestPropertySource;

import java.io.InputStream;
import java.util.List;

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

/**
 * MinIOService 集成测试类
 * 测试与实际MinIO服务器的集成
 * 
 * @author rj
 * @date 2025-10-02
 */
@SpringBootTest
@ActiveProfiles("test")
@TestPropertySource(properties = {
    "minio.endpoint=http://101.35.52.237:19005",
    "minio.access-key=minioadmin",
    "minio.secret-key=minioadmin",
    "minio.bucket-name=test-integration"
})
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@DisplayName("MinIOService 集成测试")
class MinIOServiceIntegrationTest {

    @Autowired
    private MinIOService minioService;

    @Autowired
    private MinIOConfig minioConfig;

    private static final String TEST_FILE_NAME = "integration-test-file.txt";
    private static final String TEST_CONTENT = "这是集成测试文件内容\nIntegration test file content";
    private static final String CUSTOM_BUCKET = "integration-custom-bucket";

    @BeforeAll
    static void beforeAll() {
        System.out.println("开始MinIOService集成测试...");
        System.out.println("请确保MinIO服务器正在运行: http://101.35.52.237:19005");
    }

    @AfterAll
    static void afterAll() {
        System.out.println("MinIOService集成测试完成！");
    }

    @Test
    @Order(1)
    @DisplayName("验证配置加载")
    void testConfigurationLoading() {
        assertNotNull(minioConfig);
        assertNotNull(minioConfig.getEndpoint());
        assertNotNull(minioConfig.getAccessKey());
        assertNotNull(minioConfig.getSecretKey());
        assertNotNull(minioConfig.getBucketName());
        
        System.out.println("MinIO配置信息:");
        System.out.println("Endpoint: " + minioConfig.getEndpoint());
        System.out.println("Bucket: " + minioConfig.getBucketName());
        System.out.println("✅ 配置加载成功");
    }

    @Test
    @Order(2)
    @DisplayName("创建测试存储桶")
    void testCreateBucket() {
        try {
            boolean result = minioService.createBucket(CUSTOM_BUCKET);
            assertTrue(result);
            System.out.println("✅ 创建存储桶成功: " + CUSTOM_BUCKET);
        } catch (Exception e) {
            System.out.println("⚠️ 创建存储桶失败（可能已存在）: " + e.getMessage());
            // 存储桶可能已存在，这不是错误
        }
    }

    @Test
    @Order(3)
    @DisplayName("获取所有存储桶")
    void testGetAllBuckets() {
        List<String> buckets = minioService.getAllBuckets();
        assertNotNull(buckets);
        System.out.println("✅ 获取存储桶列表成功，共 " + buckets.size() + " 个存储桶:");
        buckets.forEach(bucket -> System.out.println("  - " + bucket));
    }

    @Test
    @Order(4)
    @DisplayName("上传文件到默认存储桶")
    void testUploadFileToDefaultBucket() {
        MockMultipartFile file = new MockMultipartFile(
                "file",
                TEST_FILE_NAME,
                "text/plain",
                TEST_CONTENT.getBytes()
        );

        String fileUrl = minioService.uploadFile(file);
        assertNotNull(fileUrl);
        assertTrue(fileUrl.contains(TEST_FILE_NAME));
        
        System.out.println("✅ 文件上传成功:");
        System.out.println("  文件名: " + TEST_FILE_NAME);
        System.out.println("  访问URL: " + fileUrl);
    }

    @Test
    @Order(5)
    @DisplayName("上传文件到自定义存储桶")
    void testUploadFileToCustomBucket() {
        String customFileName = "custom-" + TEST_FILE_NAME;
        MockMultipartFile file = new MockMultipartFile(
                "file",
                customFileName,
                "text/plain",
                TEST_CONTENT.getBytes()
        );

        String fileUrl = minioService.uploadFile(file, CUSTOM_BUCKET);
     
        
        System.out.println("✅ 文件上传到自定义存储桶成功:");
        System.out.println("  存储桶: " + CUSTOM_BUCKET);
        System.out.println("  文件名: " + customFileName);
        System.out.println("  访问URL: " + fileUrl);
    }

    @Test
    @Order(6)
    @DisplayName("检查文件是否存在")
    void testFileExists() {
        boolean exists = minioService.fileExists(TEST_FILE_NAME);
        assertTrue(exists);
        System.out.println("✅ 文件存在性检查成功: " + TEST_FILE_NAME);

        boolean notExists = minioService.fileExists("non-existent-file.txt");
        assertFalse(notExists);
        System.out.println("✅ 不存在文件检查成功: non-existent-file.txt");
    }

    @Test
    @Order(7)
    @DisplayName("获取文件列表")
    void testListFiles() {
        List<String> files = minioService.listFiles();
        assertNotNull(files);
        assertTrue(files.contains(TEST_FILE_NAME));
        
        System.out.println("✅ 获取文件列表成功，共 " + files.size() + " 个文件:");
        files.forEach(file -> System.out.println("  - " + file));
    }

    @Test
    @Order(8)
    @DisplayName("获取文件详细信息")
    void testListFileDetails() {
        var fileDetails = minioService.listFileDetails();
        assertNotNull(fileDetails);
        assertFalse(fileDetails.isEmpty());
        
        System.out.println("✅ 获取文件详细信息成功:");
        fileDetails.forEach(fileInfo -> {
            System.out.println("  文件: " + fileInfo.getObjectName());
            System.out.println("    大小: " + fileInfo.getSize() + " 字节");
            System.out.println("    修改时间: " + fileInfo.getLastModified());
            System.out.println("    ETag: " + fileInfo.getEtag());
        });
    }

    @Test
    @Order(9)
    @DisplayName("下载文件")
    void testDownloadFile() {
        try (InputStream inputStream = minioService.downloadFile(TEST_FILE_NAME)) {
            assertNotNull(inputStream);
            
            // 读取文件内容
            byte[] content = inputStream.readAllBytes();
            String downloadedContent = new String(content);
            
            assertEquals(TEST_CONTENT, downloadedContent);
            System.out.println("✅ 文件下载成功:");
            System.out.println("  文件名: " + TEST_FILE_NAME);
            System.out.println("  内容长度: " + content.length + " 字节");
            System.out.println("  内容预览: " + downloadedContent.substring(0, Math.min(50, downloadedContent.length())) + "...");
            
        } catch (Exception e) {
            fail("文件下载失败: " + e.getMessage());
        }
    }

    @Test
    @Order(10)
    @DisplayName("获取预签名URL")
    void testGetPresignedUrl() {
        String presignedUrl = minioService.getPresignedUrl(TEST_FILE_NAME, 3600); // 1小时
        assertNotNull(presignedUrl);
        assertTrue(presignedUrl.startsWith("http"));
        assertTrue(presignedUrl.contains(TEST_FILE_NAME));
        
        System.out.println("✅ 获取预签名URL成功:");
        System.out.println("  文件名: " + TEST_FILE_NAME);
        System.out.println("  预签名URL: " + presignedUrl);
    }

    @Test
    @Order(11)
    @DisplayName("复制文件")
    void testCopyFile() {
        String targetFileName = "copied-" + TEST_FILE_NAME;
        
        boolean result = minioService.copyFile(TEST_FILE_NAME, targetFileName);
        assertTrue(result);
        
        // 验证复制的文件是否存在
        boolean exists = minioService.fileExists(targetFileName);
        assertTrue(exists);
        
        System.out.println("✅ 文件复制成功:");
        System.out.println("  源文件: " + TEST_FILE_NAME);
        System.out.println("  目标文件: " + targetFileName);
    }

    @Test
    @Order(12)
    @DisplayName("获取文件URL")
    void testGetFileUrl() {
        String fileUrl = minioService.getFileUrl("微信图片_20251005120205_56_49.jpg");
        assertNotNull(fileUrl);

        System.out.println("✅ 获取文件URL成功:");
        System.out.println("  文件名: " + TEST_FILE_NAME);
        System.out.println("  文件URL: " + fileUrl);
    }

    @Test
    @Order(13)
    @DisplayName("性能测试 - 批量上传")
    void testBatchUpload() {
        long startTime = System.currentTimeMillis();
        int fileCount = 5;
        
        for (int i = 0; i < fileCount; i++) {
            String fileName = "batch-test-" + i + ".txt";
            String content = "批量测试文件内容 " + i;
            
            MockMultipartFile file = new MockMultipartFile(
                    "file",
                    fileName,
                    "text/plain",
                    content.getBytes()
            );
            
            String fileUrl = minioService.uploadFile(file);
            assertNotNull(fileUrl);
        }
        
        long endTime = System.currentTimeMillis();
        long duration = endTime - startTime;
        
        System.out.println("✅ 批量上传性能测试完成:");
        System.out.println("  文件数量: " + fileCount);
        System.out.println("  总耗时: " + duration + " ms");
        System.out.println("  平均耗时: " + (duration / fileCount) + " ms/文件");
    }

    @Test
    @Order(14)
    @DisplayName("清理测试文件")
    void testCleanupTestFiles() {
        List<String> files = minioService.listFiles();
        int deletedCount = 0;
        
        for (String fileName : files) {
            if (fileName.startsWith("integration-test-") || 
                fileName.startsWith("copied-") || 
                fileName.startsWith("batch-test-")) {
                
                boolean deleted = minioService.deleteFile(fileName);
                if (deleted) {
                    deletedCount++;
                    System.out.println("  已删除: " + fileName);
                }
            }
        }
        
        System.out.println("✅ 清理测试文件完成，共删除 " + deletedCount + " 个文件");
    }

    @Test
    @Order(15)
    @DisplayName("错误处理测试")
    void testErrorHandling() {
        // 测试下载不存在的文件
        assertThrows(RuntimeException.class, () -> {
            minioService.downloadFile("non-existent-file.txt");
        });
        System.out.println("✅ 下载不存在文件的错误处理正常");
        
        // 测试检查不存在的文件
        boolean exists = minioService.fileExists("non-existent-file.txt");
        assertFalse(exists);
        System.out.println("✅ 检查不存在文件的处理正常");
    }

    @Test
    @Order(16)
    @DisplayName("连接稳定性测试")
    void testConnectionStability() {
        // 连续执行多次操作，测试连接稳定性
        for (int i = 0; i < 3; i++) {
            List<String> buckets = minioService.getAllBuckets();
            assertNotNull(buckets);
            
            List<String> files = minioService.listFiles();
            assertNotNull(files);
        }
        
        System.out.println("✅ 连接稳定性测试通过");
    }
}
