package repository

import (
	"net/http"
	"net/url"
	"testing"

	"github.com/Wei-Shaw/sub2api/internal/config"
)

// httpClientSink 用于防止编译器优化掉基准测试中的赋值操作
// 这是 Go 基准测试的常见模式，确保测试结果准确
var httpClientSink *http.Client

// BenchmarkHTTPUpstreamProxyClient 对比重复创建与复用代理客户端的开销
//
// 测试目的：
// - 验证连接池复用相比每次新建的性能提升
// - 量化内存分配差异
//
// 预期结果：
// - "复用" 子测试应显著快于 "新建"
// - "复用" 子测试应零内存分配
func BenchmarkHTTPUpstreamProxyClient(b *testing.B) {
	// 创建测试配置
	cfg := &config.Config{
		Gateway: config.GatewayConfig{ResponseHeaderTimeout: 300},
	}
	upstream := NewHTTPUpstream(cfg)
	svc, ok := upstream.(*httpUpstreamService)
	if !ok {
		b.Fatalf("类型断言失败，无法获取 httpUpstreamService")
	}

	proxyURL := "http://127.0.0.1:8080"
	b.ReportAllocs() // 报告内存分配统计

	// 子测试：每次新建客户端
	// 模拟未优化前的行为，每次请求都创建新的 http.Client
	b.Run("新建", func(b *testing.B) {
		parsedProxy, err := url.Parse(proxyURL)
		if err != nil {
			b.Fatalf("解析代理地址失败: %v", err)
		}
		settings := defaultPoolSettings(cfg)
		for i := 0; i < b.N; i++ {
			// 每次迭代都创建新客户端，包含 Transport 分配
			transport, err := buildUpstreamTransport(settings, parsedProxy)
			if err != nil {
				b.Fatalf("创建 Transport 失败: %v", err)
			}
			httpClientSink = &http.Client{
				Transport: transport,
			}
		}
	})

	// 子测试：复用已缓存的客户端
	// 模拟优化后的行为，从缓存获取客户端
	b.Run("复用", func(b *testing.B) {
		// 预热：确保客户端已缓存
		entry := svc.getOrCreateClient(proxyURL, 1, 1)
		client := entry.client
		b.ResetTimer() // 重置计时器，排除预热时间
		for i := 0; i < b.N; i++ {
			// 直接使用缓存的客户端，无内存分配
			httpClientSink = client
		}
	})
}
