package com.rj.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
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.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.*;

/**
 * 头衔上传接口测试
 * 测试 FaceDetectController 中的头衔上传功能
 * 
 * @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",
    "dashscope.api.key=${DASHSCOPE_API_KEY:test-key}"
})
@Slf4j
public class FaceDetectAvatarUploadTest {

    @Autowired
    private WebApplicationContext webApplicationContext;

    private MockMvc mockMvc;

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

    /**
     * 测试头衔上传接口 - 正常情况
     */
    @Test
    void testAvatarUpload_Success() throws Exception {
        log.info("=== 测试头衔上传接口 - 正常情况 ===");
        
        // 1. 创建测试图片文件
        String testContent = "这是一个测试图片文件内容";
        MockMultipartFile testFile = new MockMultipartFile(
            "file", 
            "test-avatar.jpg", 
            "image/jpeg", 
            testContent.getBytes(StandardCharsets.UTF_8)
        );

        // 2. 调用头衔上传接口
        MvcResult result = mockMvc.perform(multipart("/api/face-detect/avatar/upload")
                .file(testFile)
                .param("userId", "test-user-123")
                .param("expiresInSeconds", "3600"))
                .andExpect(status().isOk())
                .andExpect(content().contentType(MediaType.APPLICATION_JSON))
                .andReturn();

        String responseContent = result.getResponse().getContentAsString();
        log.info("头衔上传响应: {}", responseContent);

        // 3. 验证响应内容
        assertNotNull(responseContent);
        assertTrue(responseContent.contains("\"success\":true"));
        assertTrue(responseContent.contains("\"originalFileName\":\"test-avatar.jpg\""));
        assertTrue(responseContent.contains("\"fileUrl\""));
        assertTrue(responseContent.contains("\"shortUrl\""));
        assertTrue(responseContent.contains("\"faceDetection\""));
        assertTrue(responseContent.contains("\"userId\":\"test-user-123\""));
    }

    /**
     * 测试头衔上传接口 - 空文件
     */
    @Test
    void testAvatarUpload_EmptyFile() throws Exception {
        log.info("=== 测试头衔上传接口 - 空文件 ===");
        
        MockMultipartFile emptyFile = new MockMultipartFile(
            "file", 
            "empty.jpg", 
            "image/jpeg", 
            new byte[0]
        );

        MvcResult result = mockMvc.perform(multipart("/api/face-detect/avatar/upload")
                .file(emptyFile))
                .andExpect(status().isBadRequest())
                .andReturn();

        String responseContent = result.getResponse().getContentAsString();
        log.info("空文件上传响应: {}", responseContent);

        assertTrue(responseContent.contains("\"success\":false"));
        assertTrue(responseContent.contains("文件不能为空"));
    }

    /**
     * 测试头衔上传接口 - 非图片文件
     */
    @Test
    void testAvatarUpload_NonImageFile() throws Exception {
        log.info("=== 测试头衔上传接口 - 非图片文件 ===");
        
        MockMultipartFile nonImageFile = new MockMultipartFile(
            "file", 
            "test.txt", 
            "text/plain", 
            "这是一个文本文件".getBytes(StandardCharsets.UTF_8)
        );

        MvcResult result = mockMvc.perform(multipart("/api/face-detect/avatar/upload")
                .file(nonImageFile))
                .andExpect(status().isBadRequest())
                .andReturn();

        String responseContent = result.getResponse().getContentAsString();
        log.info("非图片文件上传响应: {}", responseContent);

        assertTrue(responseContent.contains("\"success\":false"));
        assertTrue(responseContent.contains("只支持图片文件格式"));
    }

    /**
     * 测试头衔上传接口 - 大文件
     */
    @Test
    void testAvatarUpload_LargeFile() throws Exception {
        log.info("=== 测试头衔上传接口 - 大文件 ===");
        
        // 创建一个51MB的文件（超过50MB限制）
        byte[] largeContent = new byte[51 * 1024 * 1024];
        MockMultipartFile largeFile = new MockMultipartFile(
            "file", 
            "large-image.jpg", 
            "image/jpeg", 
            largeContent
        );

        MvcResult result = mockMvc.perform(multipart("/api/face-detect/avatar/upload")
                .file(largeFile))
                .andExpect(status().isBadRequest())
                .andReturn();

        String responseContent = result.getResponse().getContentAsString();
        log.info("大文件上传响应: {}", responseContent);

        assertTrue(responseContent.contains("\"success\":false"));
        assertTrue(responseContent.contains("文件大小不能超过50MB"));
    }

    /**
     * 测试头衔上传接口 - 不同过期时间
     */
    @Test
    void testAvatarUpload_DifferentExpires() throws Exception {
        log.info("=== 测试头衔上传接口 - 不同过期时间 ===");
        
        String testContent = "测试图片内容";
        MockMultipartFile testFile = new MockMultipartFile(
            "file", 
            "test-expires.jpg", 
            "image/jpeg", 
            testContent.getBytes(StandardCharsets.UTF_8)
        );

        // 测试5分钟过期时间
        MvcResult result = mockMvc.perform(multipart("/api/face-detect/avatar/upload")
                .file(testFile)
                .param("expiresInSeconds", "300"))
                .andExpect(status().isOk())
                .andReturn();

        String responseContent = result.getResponse().getContentAsString();
        log.info("5分钟过期时间响应: {}", responseContent);

        assertTrue(responseContent.contains("\"success\":true"));
        assertTrue(responseContent.contains("\"shortUrlExpiresInSeconds\":300"));
    }

    /**
     * 测试头衔上传接口 - 带用户ID
     */
    @Test
    void testAvatarUpload_WithUserId() throws Exception {
        log.info("=== 测试头衔上传接口 - 带用户ID ===");
        
        String testContent = "测试图片内容";
        MockMultipartFile testFile = new MockMultipartFile(
            "file", 
            "test-user.jpg", 
            "image/jpeg", 
            testContent.getBytes(StandardCharsets.UTF_8)
        );

        MvcResult result = mockMvc.perform(multipart("/api/face-detect/avatar/upload")
                .file(testFile)
                .param("userId", "user-12345")
                .param("expiresInSeconds", "7200"))
                .andExpect(status().isOk())
                .andReturn();

        String responseContent = result.getResponse().getContentAsString();
        log.info("带用户ID上传响应: {}", responseContent);

        assertTrue(responseContent.contains("\"success\":true"));
        assertTrue(responseContent.contains("\"userId\":\"user-12345\""));
        assertTrue(responseContent.contains("\"shortUrlExpiresInSeconds\":7200"));
    }

    /**
     * 测试头衔上传接口 - 验证返回的数据结构
     */
    @Test
    void testAvatarUpload_ResponseStructure() throws Exception {
        log.info("=== 测试头衔上传接口 - 验证返回的数据结构 ===");
        
        String testContent = "测试图片内容";
        MockMultipartFile testFile = new MockMultipartFile(
            "file", 
            "structure-test.jpg", 
            "image/jpeg", 
            testContent.getBytes(StandardCharsets.UTF_8)
        );

        MvcResult result = mockMvc.perform(multipart("/api/face-detect/avatar/upload")
                .file(testFile)
                .param("userId", "structure-test-user"))
                .andExpect(status().isOk())
                .andReturn();

        String responseContent = result.getResponse().getContentAsString();
        log.info("数据结构测试响应: {}", responseContent);

        // 验证必要的字段存在
        assertTrue(responseContent.contains("\"success\""));
        assertTrue(responseContent.contains("\"message\""));
        assertTrue(responseContent.contains("\"originalFileName\""));
        assertTrue(responseContent.contains("\"fileSize\""));
        assertTrue(responseContent.contains("\"fileUrl\""));
        assertTrue(responseContent.contains("\"shortUrl\""));
        assertTrue(responseContent.contains("\"shortUrlExpiresAt\""));
        assertTrue(responseContent.contains("\"shortUrlExpiresInSeconds\""));
        assertTrue(responseContent.contains("\"userId\""));
        assertTrue(responseContent.contains("\"faceDetection\""));
    }
}
