package com.rj.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.rj.service.MinIOService;
import com.rj.utils.MinIOUrlGenerator;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureWebMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;

import static org.junit.jupiter.api.Assertions.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

/**
 * MinIO 临时URL接口测试
 * 测试 generateTempUrlWithExpires 接口的功能
 * 
 * @author rj
 * @date 2025-01-02
 */
@SpringBootTest
@AutoConfigureWebMvc
@TestPropertySource(properties = {
    "minio.endpoint=http://101.35.52.237:19005",
    "minio.access-key=minioadmin",
    "minio.secret-key=minioadmin",
    "minio.bucket-name=car"
})
@Slf4j
public class MinIOControllerTempUrlTest {

    @Autowired
    private WebApplicationContext webApplicationContext;

    @Autowired
    private MinIOService minioService;

    @Autowired
    private MinIOUrlGenerator urlGenerator;

    private MockMvc mockMvc;
    private ObjectMapper objectMapper = new ObjectMapper();

    @org.junit.jupiter.api.BeforeEach
    void setUp() {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }

    /**
     * 测试生成临时URL接口 - 正常情况
     */
    @Test
    void testGenerateTempUrlWithExpires_Success() throws Exception {
        // 1. 先上传一个测试文件

        MinIOUrlGenerator.UrlInfo urlInfo = urlGenerator.generateTempUrl("微信图片_20251005120205_56_49.jpg");

        log.info("临时url：  "+urlInfo.toString());

    }

    /**
     * 测试生成临时URL接口 - 文件不存在
     */
    @Test
    void testGenerateTempUrlWithExpires_FileNotFound() throws Exception {
        String nonExistentFile = "non-existent-file-" + System.currentTimeMillis() + ".txt";
        int expiresInSeconds = 300;

        MvcResult result = mockMvc.perform(get("/minio/temp-url/{fileName}/{expiresInSeconds}", 
                nonExistentFile, expiresInSeconds))
                .andExpect(status().isOk()) // 接口返回200，但success为false
                .andExpect(content().contentType(MediaType.APPLICATION_JSON))
                .andReturn();

        String responseContent = result.getResponse().getContentAsString();
        System.out.println("文件不存在时的响应: " + responseContent);

        // 验证响应内容
        assertNotNull(responseContent);
        assertTrue(responseContent.contains("\"success\":false"));
    }

    /**
     * 测试生成临时URL接口 - 过期时间超出范围
     */
    @Test
    void testGenerateTempUrlWithExpires_InvalidExpires() throws Exception {
        // 先上传一个测试文件
        String testFileName = "test-invalid-expires-" + System.currentTimeMillis() + ".txt";
        String testContent = "测试文件";
        
        MockMultipartFile testFile = new MockMultipartFile(
            "file", 
            testFileName, 
            "text/plain", 
            testContent.getBytes(StandardCharsets.UTF_8)
        );

        // 上传文件
        mockMvc.perform(multipart("/minio/upload")
                .file(testFile))
                .andExpect(status().isOk());

        // 测试过期时间过短（小于60秒）
        MvcResult result1 = mockMvc.perform(get("/minio/temp-url/{fileName}/{expiresInSeconds}", 
                testFileName, 30)) // 30秒，小于最小值60秒
                .andExpect(status().isBadRequest())
                .andReturn();

        System.out.println("过期时间过短的响应: " + result1.getResponse().getContentAsString());

        // 测试过期时间过长（超过7天）
        MvcResult result2 = mockMvc.perform(get("/minio/temp-url/{fileName}/{expiresInSeconds}", 
                testFileName, 604801)) // 超过7天
                .andExpect(status().isBadRequest())
                .andReturn();

        System.out.println("过期时间过长的响应: " + result2.getResponse().getContentAsString());

        // 清理测试文件
        minioService.deleteFile(testFileName);
    }

    /**
     * 测试边界值 - 最小和最大过期时间
     */
    @Test
    void testGenerateTempUrlWithExpires_BoundaryValues() throws Exception {
        // 先上传一个测试文件
        String testFileName = "test-boundary-" + System.currentTimeMillis() + ".txt";
        String testContent = "边界值测试文件";
        
        MockMultipartFile testFile = new MockMultipartFile(
            "file", 
            testFileName, 
            "text/plain", 
            testContent.getBytes(StandardCharsets.UTF_8)
        );

        // 上传文件
        mockMvc.perform(multipart("/minio/upload")
                .file(testFile))
                .andExpect(status().isOk());

        // 测试最小过期时间（60秒）
        MvcResult result1 = mockMvc.perform(get("/minio/temp-url/{fileName}/{expiresInSeconds}", 
                testFileName, 60))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.success").value(true))
                .andReturn();

        System.out.println("最小过期时间测试: " + result1.getResponse().getContentAsString());

        // 测试最大过期时间（7天）
        MvcResult result2 = mockMvc.perform(get("/minio/temp-url/{fileName}/{expiresInSeconds}", 
                testFileName, 604800))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.success").value(true))
                .andReturn();

        System.out.println("最大过期时间测试: " + result2.getResponse().getContentAsString());

        // 清理测试文件
        minioService.deleteFile(testFileName);
    }

    /**
     * 从响应中提取临时URL
     */
    private String extractTempUrlFromResponse(String responseContent) {
        try {
            // 简单的JSON解析来提取tempUrl
            int startIndex = responseContent.indexOf("\"tempUrl\":\"");
            if (startIndex != -1) {
                startIndex += 11; // 跳过 "tempUrl":"
                int endIndex = responseContent.indexOf("\"", startIndex);
                if (endIndex != -1) {
                    return responseContent.substring(startIndex, endIndex);
                }
            }
        } catch (Exception e) {
            System.err.println("提取临时URL失败: " + e.getMessage());
        }
        return null;
    }

    /**
     * 测试临时URL的可访问性
     */
    private void testTempUrlAccessibility(String tempUrl) {
        try {
            System.out.println("测试临时URL可访问性: " + tempUrl);
            
            URL url = new URL(tempUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(10000); // 10秒超时
            connection.setReadTimeout(10000);
            
            int responseCode = connection.getResponseCode();
            System.out.println("临时URL响应码: " + responseCode);
            
            if (responseCode == 200) {
                System.out.println("✅ 临时URL可以正常访问");
                
                // 读取响应内容验证
                InputStream inputStream = connection.getInputStream();
                byte[] buffer = new byte[1024];
                int bytesRead = inputStream.read(buffer);
                if (bytesRead > 0) {
                    String content = new String(buffer, 0, bytesRead, StandardCharsets.UTF_8);
                    System.out.println("文件内容预览: " + content.substring(0, Math.min(100, content.length())));
                }
                inputStream.close();
            } else {
                System.out.println("❌ 临时URL无法访问，响应码: " + responseCode);
            }
            
            connection.disconnect();
            
        } catch (Exception e) {
            System.err.println("测试临时URL访问失败: " + e.getMessage());
        }
    }
}
