package errors

import (
	"testing"

	"github.com/gofiber/fiber/v2"
)

// TestGetHTTPStatus 测试错误码到 HTTP 状态码的映射
func TestGetHTTPStatus(t *testing.T) {
	tests := []struct {
		name     string
		code     int
		expected int
	}{
		// 成功
		{"成功", CodeSuccess, fiber.StatusOK},

		// 客户端错误 (1xxx -> 4xx)
		{"参数验证失败", CodeInvalidParam, fiber.StatusBadRequest},
		{"缺失认证令牌", CodeMissingToken, fiber.StatusUnauthorized},
		{"无效令牌", CodeInvalidToken, fiber.StatusUnauthorized},
		{"未授权访问", CodeUnauthorized, fiber.StatusUnauthorized},
		{"禁止访问", CodeForbidden, fiber.StatusForbidden},
		{"资源未找到", CodeNotFound, fiber.StatusNotFound},
		{"资源冲突", CodeConflict, fiber.StatusConflict},
		{"请求过多", CodeTooManyRequests, fiber.StatusTooManyRequests},
		{"请求体过大", CodeRequestTooLarge, fiber.StatusBadRequest},

		// 服务端错误 (2xxx -> 5xx)
		{"内部服务器错误", CodeInternalError, fiber.StatusInternalServerError},
		{"数据库错误", CodeDatabaseError, fiber.StatusInternalServerError},
		{"缓存服务错误", CodeRedisError, fiber.StatusInternalServerError},
		{"服务不可用", CodeServiceUnavailable, fiber.StatusServiceUnavailable},
		{"请求超时", CodeTimeout, fiber.StatusGatewayTimeout},
		{"任务队列错误", CodeTaskQueueError, fiber.StatusInternalServerError},

		// 未知错误码
		{"未知错误码", 9999, fiber.StatusInternalServerError},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := GetHTTPStatus(tt.code)
			if result != tt.expected {
				t.Errorf("GetHTTPStatus(%d) = %d, expected %d", tt.code, result, tt.expected)
			}
		})
	}
}

// TestGetMessage 测试错误码到错误消息的映射
func TestGetMessage(t *testing.T) {
	tests := []struct {
		name     string
		code     int
		expected string
	}{
		// 成功
		{"成功", CodeSuccess, "成功"},

		// 客户端错误
		{"参数验证失败", CodeInvalidParam, "参数验证失败"},
		{"缺失认证令牌", CodeMissingToken, "缺失认证令牌"},
		{"无效令牌", CodeInvalidToken, "无效或过期的令牌"},
		{"未授权访问", CodeUnauthorized, "未授权访问"},
		{"禁止访问", CodeForbidden, "禁止访问"},
		{"资源未找到", CodeNotFound, "资源未找到"},
		{"资源冲突", CodeConflict, "资源冲突"},
		{"请求过多", CodeTooManyRequests, "请求过多,请稍后重试"},
		{"请求体过大", CodeRequestTooLarge, "请求体过大"},

		// 服务端错误
		{"内部服务器错误", CodeInternalError, "内部服务器错误"},
		{"数据库错误", CodeDatabaseError, "数据库错误"},
		{"缓存服务错误", CodeRedisError, "缓存服务错误"},
		{"服务不可用", CodeServiceUnavailable, "服务暂时不可用"},
		{"请求超时", CodeTimeout, "请求超时"},
		{"任务队列错误", CodeTaskQueueError, "任务队列错误"},

		// 未知错误码
		{"未知错误码", 9999, "请求处理失败"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := GetMessage(tt.code, "zh-CN")
			if result != tt.expected {
				t.Errorf("GetMessage(%d, \"zh-CN\") = %q, expected %q", tt.code, result, tt.expected)
			}
		})
	}
}

// TestGetLogLevel 测试错误码到日志级别的映射
func TestGetLogLevel(t *testing.T) {
	tests := []struct {
		name     string
		code     int
		expected string
	}{
		// 成功 (不记录日志)
		{"成功", CodeSuccess, "info"},

		// 客户端错误 (Warn 级别)
		{"参数验证失败", CodeInvalidParam, "warn"},
		{"缺失认证令牌", CodeMissingToken, "warn"},
		{"无效令牌", CodeInvalidToken, "warn"},
		{"未授权访问", CodeUnauthorized, "warn"},
		{"禁止访问", CodeForbidden, "warn"},
		{"资源未找到", CodeNotFound, "warn"},
		{"资源冲突", CodeConflict, "warn"},
		{"请求过多", CodeTooManyRequests, "warn"},
		{"请求体过大", CodeRequestTooLarge, "warn"},

		// 服务端错误 (Error 级别)
		{"内部服务器错误", CodeInternalError, "error"},
		{"数据库错误", CodeDatabaseError, "error"},
		{"缓存服务错误", CodeRedisError, "error"},
		{"服务不可用", CodeServiceUnavailable, "error"},
		{"请求超时", CodeTimeout, "error"},
		{"任务队列错误", CodeTaskQueueError, "error"},

		// 未知错误码 (Error 级别)
		{"未知错误码", 9999, "error"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := GetLogLevel(tt.code)
			if result != tt.expected {
				t.Errorf("GetLogLevel(%d) = %q, expected %q", tt.code, result, tt.expected)
			}
		})
	}
}

func TestAllCodesHaveMessages(t *testing.T) {
	var missing []int
	for _, code := range allErrorCodes {
		if _, ok := errorMessages[code]; !ok {
			missing = append(missing, code)
		}
	}
	if len(missing) > 0 {
		t.Errorf("以下错误码缺少映射消息: %v", missing)
	}
}

func TestNoOrphanMessages(t *testing.T) {
	codeSet := make(map[int]bool)
	for _, code := range allErrorCodes {
		codeSet[code] = true
	}

	var orphan []int
	for code := range errorMessages {
		if !codeSet[code] {
			orphan = append(orphan, code)
		}
	}
	if len(orphan) > 0 {
		t.Errorf("以下错误码在 errorMessages 中存在但未在 allErrorCodes 中注册: %v", orphan)
	}
}

// BenchmarkGetHTTPStatus 基准测试 HTTP 状态码映射性能
func BenchmarkGetHTTPStatus(b *testing.B) {
	codes := []int{
		CodeSuccess,
		CodeInvalidParam,
		CodeMissingToken,
		CodeInternalError,
		CodeDatabaseError,
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		for _, code := range codes {
			GetHTTPStatus(code)
		}
	}
}

// BenchmarkGetMessage 基准测试错误消息获取性能
func BenchmarkGetMessage(b *testing.B) {
	codes := []int{
		CodeSuccess,
		CodeInvalidParam,
		CodeMissingToken,
		CodeInternalError,
		CodeDatabaseError,
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		for _, code := range codes {
			GetMessage(code, "zh-CN")
		}
	}
}

// BenchmarkGetLogLevel 基准测试日志级别映射性能
func BenchmarkGetLogLevel(b *testing.B) {
	codes := []int{
		CodeSuccess,
		CodeInvalidParam,
		CodeMissingToken,
		CodeInternalError,
		CodeDatabaseError,
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		for _, code := range codes {
			GetLogLevel(code)
		}
	}
}
