package com.mosquito.project.dto;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Nested;

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

/**
 * ApiKeyResponse DTO测试
 */
@DisplayName("ApiKeyResponse DTO测试")
class ApiKeyResponseTest {

    private ObjectMapper objectMapper;

    @BeforeEach
    void setUp() {
        objectMapper = new ObjectMapper();
    }

    @Nested
    @DisplayName("构造函数测试")
    class ConstructorTests {

        @Test
        @DisplayName("全参数构造函数应该正确设置所有字段")
        void shouldSetAllFieldsCorrectly_WhenUsingAllArgsConstructor() {
            // Given
            String message = "测试消息";
            String data = "测试数据";
            String error = "测试错误";

            // When
            ApiKeyResponse response = new ApiKeyResponse(message, data, error);

            // Then
            assertEquals(message, response.getMessage());
            assertEquals(data, response.getData());
            assertEquals(error, response.getError());
        }

        @Test
        @DisplayName("无参构造函数应该创建空对象")
        void shouldCreateEmptyObject_WhenUsingNoArgsConstructor() {
            // When
            ApiKeyResponse response = new ApiKeyResponse();

            // Then
            assertNull(response.getMessage());
            assertNull(response.getData());
            assertNull(response.getError());
        }

        @Test
        @DisplayName("部分参数构造函数应该正确设置非null字段")
        void shouldSetFieldsCorrectly_WhenPartialParameters() {
            // Given
            String message = "成功消息";
            String data = "API密钥数据";

            // When
            ApiKeyResponse response = new ApiKeyResponse(message, data, null);

            // Then
            assertEquals(message, response.getMessage());
            assertEquals(data, response.getData());
            assertNull(response.getError());
        }
    }

    @Nested
    @DisplayName("静态工厂方法测试")
    class StaticFactoryMethodTests {

        @Test
        @DisplayName("success方法应该创建成功响应")
        void shouldCreateSuccessResponse_WhenUsingSuccessMethod() {
            // Given
            String data = "generated-api-key-123";

            // When
            ApiKeyResponse response = ApiKeyResponse.success(data);

            // Then
            assertEquals("操作成功", response.getMessage());
            assertEquals(data, response.getData());
            assertNull(response.getError());
        }

        @Test
        @DisplayName("error方法应该创建错误响应")
        void shouldCreateErrorResponse_WhenUsingErrorMethod() {
            // Given
            String error = "API密钥生成失败";

            // When
            ApiKeyResponse response = ApiKeyResponse.error(error);

            // Then
            assertEquals("操作失败", response.getMessage());
            assertNull(response.getData());
            assertEquals(error, response.getError());
        }

        @Test
        @DisplayName("success方法处理null数据应该正确")
        void shouldHandleNullData_WhenUsingSuccessMethod() {
            // When
            ApiKeyResponse response = ApiKeyResponse.success(null);

            // Then
            assertEquals("操作成功", response.getMessage());
            assertNull(response.getData());
            assertNull(response.getError());
        }

        @Test
        @DisplayName("error方法处理null错误应该正确")
        void shouldHandleNullError_WhenUsingErrorMethod() {
            // When
            ApiKeyResponse response = ApiKeyResponse.error(null);

            // Then
            assertEquals("操作失败", response.getMessage());
            assertNull(response.getData());
            assertNull(response.getError());
        }
    }

    @Nested
    @DisplayName("Getter和Setter测试")
    class GetterSetterTests {

        @Test
        @DisplayName("message字段的getter和setter应该正常工作")
        void shouldWorkCorrectly_MessageGetterSetter() {
            // Given
            ApiKeyResponse response = new ApiKeyResponse();
            String message = "测试消息";

            // When
            response.setMessage(message);

            // Then
            assertEquals(message, response.getMessage());
        }

        @Test
        @DisplayName("data字段的getter和setter应该正常工作")
        void shouldWorkCorrectly_DataGetterSetter() {
            // Given
            ApiKeyResponse response = new ApiKeyResponse();
            String data = "测试数据";

            // When
            response.setData(data);

            // Then
            assertEquals(data, response.getData());
        }

        @Test
        @DisplayName("error字段的getter和setter应该正常工作")
        void shouldWorkCorrectly_ErrorGetterSetter() {
            // Given
            ApiKeyResponse response = new ApiKeyResponse();
            String error = "测试错误";

            // When
            response.setError(error);

            // Then
            assertEquals(error, response.getError());
        }
    }

    @Nested
    @DisplayName("JSON序列化测试")
    class JsonSerializationTests {

        @Test
        @DisplayName("成功响应应该正确序列化为JSON")
        void shouldSerializeCorrectly_SuccessResponse() throws JsonProcessingException {
            // Given
            ApiKeyResponse response = ApiKeyResponse.success("api-key-123");

            // When
            String json = objectMapper.writeValueAsString(response);

            // Then
            assertNotNull(json);
            assertTrue(json.contains("\"message\":\"操作成功\""));
            assertTrue(json.contains("\"data\":\"api-key-123\""));
            assertFalse(json.contains("\"error\""));
        }

        @Test
        @DisplayName("错误响应应该正确序列化为JSON")
        void shouldSerializeCorrectly_ErrorResponse() throws JsonProcessingException {
            // Given
            ApiKeyResponse response = ApiKeyResponse.error("生成失败");

            // When
            String json = objectMapper.writeValueAsString(response);

            // Then
            assertNotNull(json);
            assertTrue(json.contains("\"message\":\"操作失败\""));
            assertTrue(json.contains("\"error\":\"生成失败\""));
            assertFalse(json.contains("\"data\""));
        }

        @Test
        @DisplayName("包含null字段应该正确序列化")
        void shouldSerializeCorrectly_WithNullFields() throws JsonProcessingException {
            // Given
            ApiKeyResponse response = new ApiKeyResponse("部分消息", "部分数据", null);

            // When
            String json = objectMapper.writeValueAsString(response);

            // Then
            assertNotNull(json);
            assertTrue(json.contains("\"message\":\"部分消息\""));
            assertTrue(json.contains("\"data\":\"部分数据\""));
            // null字段默认可能不包含或显示为null
        }
    }

    @Nested
    @DisplayName("JSON反序列化测试")
    class JsonDeserializationTests {

        @Test
        @DisplayName("完整JSON应该正确反序列化")
        void shouldDeserializeCorrectly_CompleteJson() throws JsonProcessingException {
            // Given
            String json = "{\"message\":\"测试消息\",\"data\":\"测试数据\",\"error\":\"测试错误\"}";

            // When
            ApiKeyResponse response = objectMapper.readValue(json, ApiKeyResponse.class);

            // Then
            assertEquals("测试消息", response.getMessage());
            assertEquals("测试数据", response.getData());
            assertEquals("测试错误", response.getError());
        }

        @Test
        @DisplayName("部分字段JSON应该正确反序列化")
        void shouldDeserializeCorrectly_PartialFieldsJson() throws JsonProcessingException {
            // Given
            String json = "{\"message\":\"成功消息\",\"data\":\"密钥数据\"}";

            // When
            ApiKeyResponse response = objectMapper.readValue(json, ApiKeyResponse.class);

            // Then
            assertEquals("成功消息", response.getMessage());
            assertEquals("密钥数据", response.getData());
            assertNull(response.getError());
        }

        @Test
        @DisplayName("空对象JSON应该正确反序列化")
        void shouldDeserializeCorrectly_EmptyObjectJson() throws JsonProcessingException {
            // Given
            String json = "{}";

            // When
            ApiKeyResponse response = objectMapper.readValue(json, ApiKeyResponse.class);

            // Then
            assertNull(response.getMessage());
            assertNull(response.getData());
            assertNull(response.getError());
        }
    }

    @Nested
    @DisplayName("边界条件测试")
    class BoundaryTests {

        @Test
        @DisplayName("包含特殊字符的内容应该正确处理")
        void shouldHandleSpecialCharacters() throws JsonProcessingException {
            // Given
            String specialChars = "包含中文、emoji🎉和特殊符号!@#$%^&*()";
            ApiKeyResponse response = new ApiKeyResponse(specialChars, specialChars, specialChars);

            // When
            String json = objectMapper.writeValueAsString(response);
            ApiKeyResponse deserialized = objectMapper.readValue(json, ApiKeyResponse.class);

            // Then
            assertEquals(specialChars, deserialized.getMessage());
            assertEquals(specialChars, deserialized.getData());
            assertEquals(specialChars, deserialized.getError());
        }

        @Test
        @DisplayName("超长字符串应该正确处理")
        void shouldHandleLongStrings() {
            // Given
            StringBuilder longString = new StringBuilder();
            for (int i = 0; i < 1000; i++) {
                longString.append("a");
            }
            String longContent = longString.toString();

            // When
            ApiKeyResponse response = new ApiKeyResponse(longContent, longContent, longContent);

            // Then
            assertEquals(longContent, response.getMessage());
            assertEquals(longContent, response.getData());
            assertEquals(longContent, response.getError());
        }

        @Test
        @DisplayName("JSON格式错误应该抛出异常")
        void shouldThrowException_WhenJsonIsMalformed() {
            // Given
            String malformedJson = "{\"message\":\"测试\",\"data\":\"数据\""; // 缺少闭合括号

            // When & Then
            assertThrows(JsonProcessingException.class, () -> {
                objectMapper.readValue(malformedJson, ApiKeyResponse.class);
            });
        }
    }
}
