package response

import (
	"io"
	"net/http/httptest"
	"testing"
	"time"

	"github.com/break/junhong_cmp_fiber/pkg/errors"
	"github.com/bytedance/sonic"
	"github.com/gofiber/fiber/v2"
)

// TestSuccess 测试成功响应（T034）
func TestSuccess(t *testing.T) {
	tests := []struct {
		name string
		data any
	}{
		{
			name: "success with string data",
			data: "test data",
		},
		{
			name: "success with map data",
			data: map[string]any{
				"id":   123,
				"name": "test",
			},
		},
		{
			name: "success with slice data",
			data: []string{"item1", "item2", "item3"},
		},
		{
			name: "success with struct data",
			data: struct {
				ID   int    `json:"id"`
				Name string `json:"name"`
			}{
				ID:   456,
				Name: "test struct",
			},
		},
		{
			name: "success with nil data",
			data: nil,
		},
		{
			name: "success with empty map",
			data: map[string]any{},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			app := fiber.New()
			app.Get("/test", func(c *fiber.Ctx) error {
				return Success(c, tt.data)
			})

			req := httptest.NewRequest("GET", "/test", nil)
			resp, err := app.Test(req)
			if err != nil {
				t.Fatalf("Failed to execute request: %v", err)
			}
			defer func() { _ = resp.Body.Close() }()

			// 验证 HTTP 状态码
			if resp.StatusCode != 200 {
				t.Errorf("Expected status code 200, got %d", resp.StatusCode)
			}

			// 验证响应头（Fiber 会自动添加 charset=utf-8）
			contentType := resp.Header.Get("Content-Type")
			if contentType != "application/json" && contentType != "application/json; charset=utf-8" {
				t.Errorf("Expected Content-Type application/json or application/json; charset=utf-8, got %s", contentType)
			}

			// 解析响应体
			body, err := io.ReadAll(resp.Body)
			if err != nil {
				t.Fatalf("Failed to read response body: %v", err)
			}

			var response Response
			if err := sonic.Unmarshal(body, &response); err != nil {
				t.Fatalf("Failed to unmarshal response: %v", err)
			}

			// 验证响应结构
			if response.Code != errors.CodeSuccess {
				t.Errorf("Expected code %d, got %d", errors.CodeSuccess, response.Code)
			}

			if response.Message != "success" {
				t.Errorf("Expected message 'success', got '%s'", response.Message)
			}

			// 验证时间戳格式 RFC3339
			if _, err := time.Parse(time.RFC3339, response.Timestamp); err != nil {
				t.Errorf("Timestamp is not in RFC3339 format: %s", response.Timestamp)
			}

			// 验证数据字段（如果不是 nil）
			if tt.data != nil {
				if response.Data == nil {
					t.Error("Expected data field to be non-nil")
				}
			}
		})
	}
}

// TestError 测试已被删除 - Error() 函数已在重构中移除
// 错误响应现在由全局 ErrorHandler 统一处理
// 相关测试已迁移到 pkg/errors/handler_test.go

// TestSuccessWithMessage 测试带自定义消息的成功响应（T034）
func TestSuccessWithMessage(t *testing.T) {
	tests := []struct {
		name    string
		data    any
		message string
	}{
		{
			name: "custom success message",
			data: map[string]any{
				"user_id": 123,
			},
			message: "User created successfully",
		},
		{
			name:    "empty custom message",
			data:    "test data",
			message: "",
		},
		{
			name: "chinese message",
			data: map[string]string{
				"status": "ok",
			},
			message: "操作成功",
		},
		{
			name:    "long message",
			data:    nil,
			message: "This is a very long success message that describes in detail what happened during the operation",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			app := fiber.New()
			app.Get("/test", func(c *fiber.Ctx) error {
				return SuccessWithMessage(c, tt.data, tt.message)
			})

			req := httptest.NewRequest("GET", "/test", nil)
			resp, err := app.Test(req)
			if err != nil {
				t.Fatalf("Failed to execute request: %v", err)
			}
			defer func() { _ = resp.Body.Close() }()

			// 验证 HTTP 状态码（默认 200）
			if resp.StatusCode != 200 {
				t.Errorf("Expected status code 200, got %d", resp.StatusCode)
			}

			// 解析响应体
			body, err := io.ReadAll(resp.Body)
			if err != nil {
				t.Fatalf("Failed to read response body: %v", err)
			}

			var response Response
			if err := sonic.Unmarshal(body, &response); err != nil {
				t.Fatalf("Failed to unmarshal response: %v", err)
			}

			// 验证响应结构
			if response.Code != errors.CodeSuccess {
				t.Errorf("Expected code %d, got %d", errors.CodeSuccess, response.Code)
			}

			if response.Message != tt.message {
				t.Errorf("Expected message '%s', got '%s'", tt.message, response.Message)
			}

			// 验证时间戳格式 RFC3339
			if _, err := time.Parse(time.RFC3339, response.Timestamp); err != nil {
				t.Errorf("Timestamp is not in RFC3339 format: %s", response.Timestamp)
			}
		})
	}
}

// TestResponseSerialization 测试响应序列化（T036）
func TestResponseSerialization(t *testing.T) {
	tests := []struct {
		name     string
		response Response
	}{
		{
			name: "complete response",
			response: Response{
				Code:      0,
				Data:      map[string]any{"key": "value"},
				Message:   "success",
				Timestamp: time.Now().Format(time.RFC3339),
			},
		},
		{
			name: "response with nil data",
			response: Response{
				Code:      1000,
				Data:      nil,
				Message:   "error",
				Timestamp: time.Now().Format(time.RFC3339),
			},
		},
		{
			name: "response with nested data",
			response: Response{
				Code: 0,
				Data: map[string]any{
					"user": map[string]any{
						"id":   123,
						"name": "test",
						"tags": []string{"tag1", "tag2"},
					},
				},
				Message:   "success",
				Timestamp: time.Now().Format(time.RFC3339),
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// 序列化
			data, err := sonic.Marshal(tt.response)
			if err != nil {
				t.Fatalf("Failed to marshal response: %v", err)
			}

			// 反序列化
			var deserialized Response
			if err := sonic.Unmarshal(data, &deserialized); err != nil {
				t.Fatalf("Failed to unmarshal response: %v", err)
			}

			// 验证字段
			if deserialized.Code != tt.response.Code {
				t.Errorf("Code mismatch: expected %d, got %d", tt.response.Code, deserialized.Code)
			}

			if deserialized.Message != tt.response.Message {
				t.Errorf("Message mismatch: expected '%s', got '%s'", tt.response.Message, deserialized.Message)
			}

			if deserialized.Timestamp != tt.response.Timestamp {
				t.Errorf("Timestamp mismatch: expected '%s', got '%s'", tt.response.Timestamp, deserialized.Timestamp)
			}
		})
	}
}

// TestResponseStructFields 测试响应结构字段（T036）
func TestResponseStructFields(t *testing.T) {
	response := Response{
		Code:      0,
		Data:      "test",
		Message:   "success",
		Timestamp: time.Now().Format(time.RFC3339),
	}

	data, err := sonic.Marshal(response)
	if err != nil {
		t.Fatalf("Failed to marshal response: %v", err)
	}

	// 解析为 map 以检查 JSON 键
	var jsonMap map[string]any
	if err := sonic.Unmarshal(data, &jsonMap); err != nil {
		t.Fatalf("Failed to unmarshal to map: %v", err)
	}

	// 验证所有必需字段都存在
	requiredFields := []string{"code", "data", "msg", "timestamp"}
	for _, field := range requiredFields {
		if _, exists := jsonMap[field]; !exists {
			t.Errorf("Required field '%s' is missing in JSON response", field)
		}
	}

	// 验证字段类型
	if _, ok := jsonMap["code"].(float64); !ok {
		t.Error("Field 'code' should be a number")
	}

	if _, ok := jsonMap["msg"].(string); !ok {
		t.Error("Field 'msg' should be a string")
	}

	if _, ok := jsonMap["timestamp"].(string); !ok {
		t.Error("Field 'timestamp' should be a string")
	}
}

// TestMultipleResponses 测试多个连续响应（T036）
func TestMultipleResponses(t *testing.T) {
	app := fiber.New()

	callCount := 0
	app.Get("/test", func(c *fiber.Ctx) error {
		callCount++
		// 只返回成功响应，因为 Error() 函数已被删除
		return Success(c, map[string]int{"count": callCount})
	})

	// 发送多个请求
	for i := 1; i <= 5; i++ {
		req := httptest.NewRequest("GET", "/test", nil)
		resp, err := app.Test(req)
		if err != nil {
			t.Fatalf("Request %d failed: %v", i, err)
		}

		body, _ := io.ReadAll(resp.Body)
		_ = resp.Body.Close()

		var response Response
		if err := sonic.Unmarshal(body, &response); err != nil {
			t.Fatalf("Request %d: failed to unmarshal response: %v", i, err)
		}

		// 验证每个响应都有时间戳
		if response.Timestamp == "" {
			t.Errorf("Request %d: timestamp should not be empty", i)
		}
	}
}

// TestTimestampFormat 测试时间戳格式（T036）
func TestTimestampFormat(t *testing.T) {
	app := fiber.New()
	app.Get("/test", func(c *fiber.Ctx) error {
		return Success(c, nil)
	})

	req := httptest.NewRequest("GET", "/test", nil)
	resp, err := app.Test(req)
	if err != nil {
		t.Fatalf("Failed to execute request: %v", err)
	}
	defer func() { _ = resp.Body.Close() }()

	body, _ := io.ReadAll(resp.Body)
	var response Response
	if err := sonic.Unmarshal(body, &response); err != nil {
		t.Fatalf("Failed to unmarshal response: %v", err)
	}

	// 验证是 RFC3339 格式
	parsedTime, err := time.Parse(time.RFC3339, response.Timestamp)
	if err != nil {
		t.Fatalf("Timestamp is not in RFC3339 format: %s, error: %v", response.Timestamp, err)
	}

	// 验证时间戳是最近的（应该在最近 1 秒内）
	now := time.Now()
	diff := now.Sub(parsedTime)
	if diff < 0 || diff > time.Second {
		t.Errorf("Timestamp seems incorrect: %s (diff from now: %v)", response.Timestamp, diff)
	}
}
