// Package loadbalance 提供负载均衡算法的测试。
//
// 该文件测试负载均衡模块的各项功能，包括：
//   - 轮询算法
//   - 加权轮询算法
//   - 最少连接算法
//   - IP 哈希算法
//   - 一致性哈希算法
//
// 作者：xfy
package loadbalance

import (
	"net"
	"strings"
	"sync"
	"testing"
	"time"

	"github.com/valyala/fasthttp"
)

// createHealthyTarget 创建并返回一个指定 URL 和健康状态的 Target 实例。
//
// 该辅助函数简化测试中 Target 的创建过程，自动初始化 Healthy 状态。
//
// 参数：
//   - url: 目标 URL 地址
//   - healthy: 健康状态，true 表示健康，false 表示不健康
//
// 返回值：
//   - 初始化完成的 Target 指针
func createHealthyTarget(url string, healthy bool) *Target {
	t := &Target{URL: url, Stats: NewEWMAStats()}
	t.Healthy.Store(healthy)
	return t
}

// TestRoundRobin_Select 测试轮询负载均衡选择器。
func TestRoundRobin_Select(t *testing.T) {
	t.Parallel()
	t.Run("多目标轮询", func(_ *testing.T) {
		rr := NewRoundRobin()
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
			createHealthyTarget("http://backend3:8080", true),
		}

		// 验证轮询顺序
		got1 := rr.Select(targets)
		got2 := rr.Select(targets)
		got3 := rr.Select(targets)
		got4 := rr.Select(targets)

		if got1.URL != "http://backend1:8080" {
			t.Errorf("第一次选择 = %q, want %q", got1.URL, "http://backend1:8080")
		}
		if got2.URL != "http://backend2:8080" {
			t.Errorf("第二次选择 = %q, want %q", got2.URL, "http://backend2:8080")
		}
		if got3.URL != "http://backend3:8080" {
			t.Errorf("第三次选择 = %q, want %q", got3.URL, "http://backend3:8080")
		}
		if got4.URL != "http://backend1:8080" {
			t.Errorf("第四次选择 = %q, want %q", got4.URL, "http://backend1:8080")
		}
	})

	t.Run("单目标", func(_ *testing.T) {
		rr := NewRoundRobin()
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
		}

		got := rr.Select(targets)
		if got == nil {
			t.Fatal("Select() = nil, want non-nil")
		}
		if got.URL != "http://backend1:8080" {
			t.Errorf("Select() = %q, want %q", got.URL, "http://backend1:8080")
		}
	})

	t.Run("空目标", func(_ *testing.T) {
		rr := NewRoundRobin()
		got := rr.Select([]*Target{})
		if got != nil {
			t.Errorf("Select() = %v, want nil", got)
		}
	})

	t.Run("跳过不健康目标", func(_ *testing.T) {
		rr := NewRoundRobin()
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", false),
			createHealthyTarget("http://backend2:8080", true),
			createHealthyTarget("http://backend3:8080", false),
		}

		got := rr.Select(targets)
		if got == nil {
			t.Fatal("Select() = nil, want non-nil")
		}
		if got.URL != "http://backend2:8080" {
			t.Errorf("Select() = %q, want %q", got.URL, "http://backend2:8080")
		}
	})

	t.Run("所有目标都不健康", func(_ *testing.T) {
		rr := NewRoundRobin()
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", false),
			createHealthyTarget("http://backend2:8080", false),
		}

		got := rr.Select(targets)
		if got != nil {
			t.Errorf("Select() = %v, want nil", got)
		}
	})

	t.Run("并发安全", func(_ *testing.T) {
		rr := NewRoundRobin()
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
		}

		var wg sync.WaitGroup
		for range 100 {
			wg.Go(func() {
				_ = rr.Select(targets)
			})
		}
		wg.Wait()
	})
}

// TestWeightedRoundRobin_Select 测试加权轮询负载均衡选择器。
func TestWeightedRoundRobin_Select(t *testing.T) {
	t.Parallel()
	t.Run("权重分配", func(_ *testing.T) {
		wrr := NewWeightedRoundRobin()
		targets := []*Target{
			{URL: "http://backend1:8080", Weight: 1},
			{URL: "http://backend2:8080", Weight: 3},
		}
		targets[0].Healthy.Store(true)
		targets[1].Healthy.Store(true)

		// 统计选择次数
		counts := make(map[string]int)
		for range 400 {
			got := wrr.Select(targets)
			if got == nil {
				t.Fatal("Select() = nil, want non-nil")
			}
			counts[got.URL]++
		}

		// 权重1:3，期望比例大约为1:3
		// 允许一定误差
		ratio := float64(counts["http://backend2:8080"]) / float64(counts["http://backend1:8080"])
		if ratio < 2.0 || ratio > 4.0 {
			t.Errorf("权重比例 = %f, 期望接近 3.0", ratio)
		}
	})

	t.Run("权重为0", func(_ *testing.T) {
		wrr := NewWeightedRoundRobin()
		targets := []*Target{
			{URL: "http://backend1:8080", Weight: 0},
			{URL: "http://backend2:8080", Weight: 1},
		}
		targets[0].Healthy.Store(true)
		targets[1].Healthy.Store(true)

		// 权重为0的目标应该被当作权重为1处理
		counts := make(map[string]int)
		for range 100 {
			got := wrr.Select(targets)
			if got == nil {
				t.Fatal("Select() = nil, want non-nil")
			}
			counts[got.URL]++
		}

		// 两个目标都应该被选中
		if counts["http://backend1:8080"] == 0 {
			t.Error("权重为0的目标从未被选中")
		}
		if counts["http://backend2:8080"] == 0 {
			t.Error("权重为1的目标从未被选中")
		}
	})

	t.Run("空目标", func(_ *testing.T) {
		wrr := NewWeightedRoundRobin()
		got := wrr.Select([]*Target{})
		if got != nil {
			t.Errorf("Select() = %v, want nil", got)
		}
	})

	t.Run("所有目标权重为0或不健康", func(_ *testing.T) {
		wrr := NewWeightedRoundRobin()
		targets := []*Target{
			{URL: "http://backend1:8080", Weight: 0},
			{URL: "http://backend2:8080", Weight: 0},
		}
		targets[0].Healthy.Store(false)
		targets[1].Healthy.Store(false)

		got := wrr.Select(targets)
		if got != nil {
			t.Errorf("Select() = %v, want nil", got)
		}
	})

	t.Run("跳过不健康目标", func(_ *testing.T) {
		wrr := NewWeightedRoundRobin()
		targets := []*Target{
			{URL: "http://backend1:8080", Weight: 5},
			{URL: "http://backend2:8080", Weight: 1},
		}
		targets[0].Healthy.Store(false)
		targets[1].Healthy.Store(true)

		// 所有选择都应该落在健康目标上
		for range 50 {
			got := wrr.Select(targets)
			if got == nil {
				t.Fatal("Select() = nil, want non-nil")
			}
			if got.URL != "http://backend2:8080" {
				t.Errorf("Select() = %q, want %q", got.URL, "http://backend2:8080")
			}
		}
	})
}

// TestLeastConnections_Select 测试最少连接负载均衡选择器。
func TestLeastConnections_Select(t *testing.T) {
	t.Parallel()
	t.Run("选择最少连接", func(_ *testing.T) {
		lc := NewLeastConnections()
		target1 := &Target{URL: "http://backend1:8080", Connections: 10}
		target1.Healthy.Store(true)
		target2 := &Target{URL: "http://backend2:8080", Connections: 5}
		target2.Healthy.Store(true)
		target3 := &Target{URL: "http://backend3:8080", Connections: 15}
		target3.Healthy.Store(true)
		targets := []*Target{target1, target2, target3}

		got := lc.Select(targets)
		if got == nil {
			t.Fatal("Select() = nil, want non-nil")
		}
		if got.URL != "http://backend2:8080" {
			t.Errorf("Select() = %q, want %q", got.URL, "http://backend2:8080")
		}
	})

	t.Run("连接数相等时选择第一个", func(_ *testing.T) {
		lc := NewLeastConnections()
		targets := []*Target{
			{URL: "http://backend1:8080", Connections: 5},
			{URL: "http://backend2:8080", Connections: 5},
		}
		targets[0].Healthy.Store(true)
		targets[1].Healthy.Store(true)

		got := lc.Select(targets)
		if got == nil {
			t.Fatal("Select() = nil, want non-nil")
		}
		if got.URL != "http://backend1:8080" {
			t.Errorf("Select() = %q, want %q", got.URL, "http://backend1:8080")
		}
	})

	t.Run("空目标", func(_ *testing.T) {
		lc := NewLeastConnections()
		got := lc.Select([]*Target{})
		if got != nil {
			t.Errorf("Select() = %v, want nil", got)
		}
	})

	t.Run("跳过不健康目标", func(_ *testing.T) {
		lc := NewLeastConnections()
		targets := []*Target{
			{URL: "http://backend1:8080", Connections: 1},
			{URL: "http://backend2:8080", Connections: 10},
		}
		targets[0].Healthy.Store(false)
		targets[1].Healthy.Store(true)

		got := lc.Select(targets)
		if got == nil {
			t.Fatal("Select() = nil, want non-nil")
		}
		if got.URL != "http://backend2:8080" {
			t.Errorf("Select() = %q, want %q", got.URL, "http://backend2:8080")
		}
	})

	t.Run("所有目标都不健康", func(_ *testing.T) {
		lc := NewLeastConnections()
		targets := []*Target{
			{URL: "http://backend1:8080", Connections: 1},
			{URL: "http://backend2:8080", Connections: 2},
		}
		targets[0].Healthy.Store(false)
		targets[1].Healthy.Store(false)

		got := lc.Select(targets)
		if got != nil {
			t.Errorf("Select() = %v, want nil", got)
		}
	})
}

// TestIPHash_Select 测试IP哈希负载均衡选择器。
func TestIPHash_Select(t *testing.T) {
	t.Parallel()
	t.Run("相同IP返回相同目标", func(_ *testing.T) {
		ih := NewIPHash()
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
			createHealthyTarget("http://backend3:8080", true),
		}

		// 使用相同的IP地址多次选择
		clientIP := "192.168.1.100"
		var firstSelection *Target
		for range 10 {
			got := ih.SelectByIP(targets, clientIP)
			if got == nil {
				t.Fatal("SelectByIP() = nil, want non-nil")
			}
			if firstSelection == nil {
				firstSelection = got
			} else if got.URL != firstSelection.URL {
				t.Errorf("相同IP选择不同目标: 第一次=%q, 后续=%q", firstSelection.URL, got.URL)
			}
		}
	})

	t.Run("不同IP分配", func(_ *testing.T) {
		ih := NewIPHash()
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
		}

		// 使用不同的IP地址
		ips := []string{"192.168.1.1", "192.168.1.2", "10.0.0.1", "10.0.0.2"}
		selections := make(map[string]string)
		for _, ip := range ips {
			got := ih.SelectByIP(targets, ip)
			if got == nil {
				t.Fatal("SelectByIP() = nil, want non-nil")
			}
			selections[ip] = got.URL
		}

		// 验证每个IP都有分配（不验证具体分配到哪个）
		for _, ip := range ips {
			if selections[ip] == "" {
				t.Errorf("IP %s 没有分配到目标", ip)
			}
		}
	})

	t.Run("空目标", func(_ *testing.T) {
		ih := NewIPHash()
		got := ih.SelectByIP([]*Target{}, "192.168.1.1")
		if got != nil {
			t.Errorf("SelectByIP() = %v, want nil", got)
		}
	})

	t.Run("Select方法使用空IP", func(_ *testing.T) {
		ih := NewIPHash()
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
		}

		got := ih.Select(targets)
		if got == nil {
			t.Fatal("Select() = nil, want non-nil")
		}
		if got.URL != "http://backend1:8080" {
			t.Errorf("Select() = %q, want %q", got.URL, "http://backend1:8080")
		}
	})

	t.Run("跳过不健康目标", func(_ *testing.T) {
		ih := NewIPHash()
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", false),
			createHealthyTarget("http://backend2:8080", true),
		}

		got := ih.SelectByIP(targets, "192.168.1.1")
		if got == nil {
			t.Fatal("SelectByIP() = nil, want non-nil")
		}
		if got.URL != "http://backend2:8080" {
			t.Errorf("SelectByIP() = %q, want %q", got.URL, "http://backend2:8080")
		}
	})
}

// TestConnectionsAtomic 测试连接数的原子操作。
func TestConnectionsAtomic(t *testing.T) {
	t.Parallel()
	t.Run("IncrementConnections", func(_ *testing.T) {
		target := &Target{URL: "http://backend1:8080", Connections: 0}
		target.Healthy.Store(true)

		IncrementConnections(target)
		if target.Connections != 1 {
			t.Errorf("Connections = %d, want 1", target.Connections)
		}

		IncrementConnections(target)
		if target.Connections != 2 {
			t.Errorf("Connections = %d, want 2", target.Connections)
		}
	})

	t.Run("DecrementConnections", func(_ *testing.T) {
		target := &Target{URL: "http://backend1:8080", Connections: 5}
		target.Healthy.Store(true)

		DecrementConnections(target)
		if target.Connections != 4 {
			t.Errorf("Connections = %d, want 4", target.Connections)
		}

		DecrementConnections(target)
		if target.Connections != 3 {
			t.Errorf("Connections = %d, want 3", target.Connections)
		}
	})

	t.Run("并发IncrementConnections", func(_ *testing.T) {
		target := &Target{URL: "http://backend1:8080", Connections: 0}
		target.Healthy.Store(true)

		var wg sync.WaitGroup
		for range 1000 {
			wg.Go(func() {
				IncrementConnections(target)
			})
		}
		wg.Wait()

		if target.Connections != 1000 {
			t.Errorf("Connections = %d, want 1000", target.Connections)
		}
	})

	t.Run("并发DecrementConnections", func(_ *testing.T) {
		target := &Target{URL: "http://backend1:8080", Connections: 1000}
		target.Healthy.Store(true)

		var wg sync.WaitGroup
		for range 1000 {
			wg.Go(func() {
				DecrementConnections(target)
			})
		}
		wg.Wait()

		if target.Connections != 0 {
			t.Errorf("Connections = %d, want 0", target.Connections)
		}
	})

	t.Run("混合增减操作", func(_ *testing.T) {
		target := &Target{URL: "http://backend1:8080", Connections: 100}
		target.Healthy.Store(true)

		var wg sync.WaitGroup
		// 500个增加
		for range 500 {
			wg.Go(func() {
				IncrementConnections(target)
			})
		}
		// 300个减少
		for range 300 {
			wg.Go(func() {
				DecrementConnections(target)
			})
		}
		wg.Wait()

		// 100 + 500 - 300 = 300
		if target.Connections != 300 {
			t.Errorf("Connections = %d, want 300", target.Connections)
		}
	})

	t.Run("允许负值", func(_ *testing.T) {
		target := &Target{URL: "http://backend1:8080", Connections: 0}
		target.Healthy.Store(true)

		DecrementConnections(target)
		if target.Connections != -1 {
			t.Errorf("Connections = %d, want -1", target.Connections)
		}
	})
}

// TestHealthStatus 测试健康状态操作。
func TestHealthStatus(t *testing.T) {
	t.Parallel()
	t.Run("IsHealthy", func(_ *testing.T) {
		tests := []struct {
			target *Target
			name   string
			want   bool
		}{
			{
				name:   "健康目标",
				target: createHealthyTarget("http://backend1:8080", true),
				want:   true,
			},
			{
				name:   "不健康目标",
				target: createHealthyTarget("http://backend1:8080", false),
				want:   false,
			},
		}

		for _, tt := range tests {
			t.Run(tt.name, func(_ *testing.T) {
				got := tt.target.Healthy.Load()
				if got != tt.want {
					t.Errorf("Healthy.Load() = %v, want %v", got, tt.want)
				}
			})
		}
	})

	t.Run("SetHealthy", func(_ *testing.T) {
		target := &Target{URL: "http://backend1:8080"}
		target.Healthy.Store(true)

		// 设置为不健康
		target.Healthy.Store(false)
		if target.Healthy.Load() {
			t.Error("Store(false) 后期望 Load = false, 但 got true")
		}

		// 设置为健康
		target.Healthy.Store(true)
		if !target.Healthy.Load() {
			t.Error("Store(true) 后期望 Load = true, 但 got false")
		}
	})
}

// TestFilterHealthy 测试filterHealthy辅助函数。
func TestFilterHealthy(t *testing.T) {
	t.Parallel()
	t.Run("过滤健康目标", func(_ *testing.T) {
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", false),
			createHealthyTarget("http://backend3:8080", true),
			createHealthyTarget("http://backend4:8080", false),
		}

		fc := acquireFilterContext()
		got := filterInto(fc, targets)
		defer releaseFilterContext(fc)
		if len(got) != 2 {
			t.Errorf("len(filterInto) = %d, want 2", len(got))
		}

		for _, target := range got {
			if !target.Healthy.Load() {
				t.Errorf("filterInto returned unhealthy target: %q", target.URL)
			}
		}
	})

	t.Run("全部健康", func(_ *testing.T) {
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
		}

		fc := acquireFilterContext()
		got := filterInto(fc, targets)
		defer releaseFilterContext(fc)
		if len(got) != 2 {
			t.Errorf("len(filterInto) = %d, want 2", len(got))
		}
	})

	t.Run("全部不健康", func(_ *testing.T) {
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", false),
			createHealthyTarget("http://backend2:8080", false),
		}

		fc := acquireFilterContext()
		got := filterInto(fc, targets)
		defer releaseFilterContext(fc)
		if len(got) != 0 {
			t.Errorf("len(filterInto) = %d, want 0", len(got))
		}
	})

	t.Run("空切片", func(_ *testing.T) {
		fc := acquireFilterContext()
		got := filterInto(fc, []*Target{})
		defer releaseFilterContext(fc)
		if len(got) != 0 {
			t.Errorf("len(filterInto) = %d, want 0", len(got))
		}
	})

	t.Run("nil切片", func(_ *testing.T) {
		fc := acquireFilterContext()
		got := filterInto(fc, nil)
		defer releaseFilterContext(fc)
		if len(got) != 0 {
			t.Errorf("len(filterInto) = %d, want 0", len(got))
		}
	})
}

// TestBalancerInterface 测试各种负载均衡器都实现了Balancer接口。
func TestBalancerInterface(t *testing.T) {
	t.Parallel()
	tests := []struct {
		balancer Balancer
		name     string
	}{
		{
			name:     "RoundRobin",
			balancer: NewRoundRobin(),
		},
		{
			name:     "WeightedRoundRobin",
			balancer: NewWeightedRoundRobin(),
		},
		{
			name:     "LeastConnections",
			balancer: NewLeastConnections(),
		},
		{
			name:     "IPHash",
			balancer: NewIPHash(),
		},
	}

	targets := []*Target{
		createHealthyTarget("http://backend1:8080", true),
	}

	for _, tt := range tests {
		t.Run(tt.name, func(_ *testing.T) {
			got := tt.balancer.Select(targets)
			if got == nil {
				t.Fatal("Select() = nil, want non-nil")
			}
			if got.URL != "http://backend1:8080" {
				t.Errorf("Select() = %q, want %q", got.URL, "http://backend1:8080")
			}
		})
	}
}

// TestConsistentHash 测试一致性哈希负载均衡器。
func TestConsistentHash(t *testing.T) {
	t.Parallel()
	t.Run("创建默认配置", func(_ *testing.T) {
		ch := NewConsistentHash(0, "ip")
		if ch == nil {
			t.Fatal("NewConsistentHash() = nil")
		}
		if ch.GetVirtualNodes() != 150 {
			t.Errorf("GetVirtualNodes() = %d, want 150", ch.GetVirtualNodes())
		}
		if ch.GetHashKey() != "ip" {
			t.Errorf("GetHashKey() = %q, want %q", ch.GetHashKey(), "ip")
		}
	})

	t.Run("自定义虚拟节点数", func(_ *testing.T) {
		ch := NewConsistentHash(200, "uri")
		if ch.GetVirtualNodes() != 200 {
			t.Errorf("GetVirtualNodes() = %d, want 200", ch.GetVirtualNodes())
		}
	})

	t.Run("SelectByKey 空目标", func(_ *testing.T) {
		ch := NewConsistentHash(150, "ip")
		got := ch.SelectByKey([]*Target{}, "192.168.1.1")
		if got != nil {
			t.Errorf("SelectByKey() = %v, want nil", got)
		}
	})

	t.Run("SelectByKey 单目标", func(_ *testing.T) {
		ch := NewConsistentHash(150, "ip")
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
		}

		got := ch.SelectByKey(targets, "192.168.1.1")
		if got == nil {
			t.Fatal("SelectByKey() = nil")
		}
		if got.URL != "http://backend1:8080" {
			t.Errorf("SelectByKey() = %q, want %q", got.URL, "http://backend1:8080")
		}
	})

	t.Run("SelectByKey 多目标相同键", func(_ *testing.T) {
		ch := NewConsistentHash(150, "ip")
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
			createHealthyTarget("http://backend3:8080", true),
		}

		// 相同的键应该选择相同的目标
		key := "192.168.1.100"
		first := ch.SelectByKey(targets, key)
		for range 10 {
			got := ch.SelectByKey(targets, key)
			if got == nil {
				t.Fatal("SelectByKey() = nil")
			}
			if got.URL != first.URL {
				t.Errorf("相同键选择不同目标: first=%q, got=%q", first.URL, got.URL)
			}
		}
	})

	t.Run("GetStats", func(_ *testing.T) {
		ch := NewConsistentHash(100, "ip")
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
		}

		ch.Rebuild(targets)
		stats := ch.GetStats()

		if stats.VirtualNodes != 100 {
			t.Errorf("VirtualNodes = %d, want 100", stats.VirtualNodes)
		}
		if stats.CircleSize != 200 { // 2 targets * 100 nodes
			t.Errorf("CircleSize = %d, want 200", stats.CircleSize)
		}
	})

	t.Run("Rebuild 跳过不健康目标", func(_ *testing.T) {
		ch := NewConsistentHash(10, "ip")
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", false),
			createHealthyTarget("http://backend2:8080", true),
		}

		ch.Rebuild(targets)
		stats := ch.GetStats()

		if stats.CircleSize != 10 { // 只有1个健康目标 * 10 nodes
			t.Errorf("CircleSize = %d, want 10", stats.CircleSize)
		}
	})
}

// TestConsistentHashSelectExcludingByKey 测试一致性哈希排除选择功能。
func TestConsistentHashSelectExcludingByKey(t *testing.T) {
	t.Parallel()
	t.Run("空排除列表", func(_ *testing.T) {
		ch := NewConsistentHash(150, "ip")
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
			createHealthyTarget("http://backend3:8080", true),
		}
		ch.Rebuild(targets)

		key := "192.168.1.100"
		got := ch.SelectExcludingByKey(targets, []*Target{}, key)

		if got == nil {
			t.Fatal("SelectExcludingByKey() = nil, want non-nil")
		}

		// 验证正常选择行为
		got2 := ch.SelectExcludingByKey(targets, nil, key)
		if got2 == nil {
			t.Fatal("SelectExcludingByKey() with nil = nil, want non-nil")
		}
		if got.URL != got2.URL {
			t.Errorf("空排除和nil排除应该返回相同结果: empty=%q, nil=%q", got.URL, got2.URL)
		}
	})

	t.Run("部分排除", func(_ *testing.T) {
		ch := NewConsistentHash(150, "ip")
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
			createHealthyTarget("http://backend3:8080", true),
		}
		ch.Rebuild(targets)

		// 排除第一个目标
		excluded := []*Target{targets[0]}
		key := "192.168.1.100"

		// 多次选择，验证不会选中排除的目标
		for range 100 {
			got := ch.SelectExcludingByKey(targets, excluded, key)
			if got == nil {
				t.Fatal("SelectExcludingByKey() = nil, want non-nil")
			}
			if got.URL == targets[0].URL {
				t.Errorf("选中了被排除的目标: %q", got.URL)
			}
		}
	})

	t.Run("全部排除", func(_ *testing.T) {
		ch := NewConsistentHash(150, "ip")
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
		}
		ch.Rebuild(targets)

		// 排除所有目标
		excluded := []*Target{targets[0], targets[1]}
		key := "192.168.1.100"

		got := ch.SelectExcludingByKey(targets, excluded, key)
		if got != nil {
			t.Errorf("SelectExcludingByKey() = %q, want nil (all excluded)", got.URL)
		}
	})

	t.Run("排除包含nil目标", func(_ *testing.T) {
		ch := NewConsistentHash(150, "ip")
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
		}
		ch.Rebuild(targets)

		// 排除列表中包含nil
		excluded := []*Target{nil, targets[0]}
		key := "192.168.1.100"

		got := ch.SelectExcludingByKey(targets, excluded, key)
		if got == nil {
			t.Fatal("SelectExcludingByKey() = nil, want non-nil")
		}
		if got.URL == targets[0].URL {
			t.Errorf("选中了被排除的目标: %q", got.URL)
		}
	})

	t.Run("并发安全", func(_ *testing.T) {
		ch := NewConsistentHash(150, "ip")
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
			createHealthyTarget("http://backend3:8080", true),
		}
		ch.Rebuild(targets)

		excluded := []*Target{targets[0]}
		key := "192.168.1.100"

		var wg sync.WaitGroup
		for range 100 {
			wg.Go(func() {
				for range 100 {
					got := ch.SelectExcludingByKey(targets, excluded, key)
					if got != nil && got.URL == targets[0].URL {
						t.Errorf("并发时选中了被排除的目标: %q", got.URL)
					}
				}
			})
		}
		wg.Wait()
	})

	t.Run("相同键一致性", func(_ *testing.T) {
		ch := NewConsistentHash(150, "ip")
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
			createHealthyTarget("http://backend3:8080", true),
		}
		ch.Rebuild(targets)

		excluded := []*Target{targets[0]}
		key := "192.168.1.100"

		// 相同键应该始终返回相同的目标
		var firstSelection *Target
		for range 50 {
			got := ch.SelectExcludingByKey(targets, excluded, key)
			if got == nil {
				t.Fatal("SelectExcludingByKey() = nil, want non-nil")
			}
			if firstSelection == nil {
				firstSelection = got
			} else if got.URL != firstSelection.URL {
				t.Errorf("相同键选择不同目标: first=%q, got=%q", firstSelection.URL, got.URL)
			}
		}
	})
}

func TestIsValidAlgorithm(t *testing.T) {
	t.Parallel()
	tests := []struct {
		name      string
		algorithm string
		want      bool
	}{
		{"round_robin", "round_robin", true},
		{"weighted_round_robin", "weighted_round_robin", true},
		{"least_conn", "least_conn", true},
		{"ip_hash", "ip_hash", true},
		{"consistent_hash", "consistent_hash", true},
		{"random", "random", true},
		{"least_time", "least_time", true},
		{"sticky", "sticky", true},
		{"invalid", "invalid", false},
		{"empty", "", true}, // 空字符串有效（使用默认值）
		{"unknown", "unknown-algorithm", false},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(_ *testing.T) {
			got := IsValidAlgorithm(tt.algorithm)
			if got != tt.want {
				t.Errorf("IsValidAlgorithm(%q) = %v, want %v", tt.algorithm, got, tt.want)
			}
		})
	}
}

// TestRoundRobin_SelectExcluding 测试轮询排除选择功能。
func TestRoundRobin_SelectExcluding(t *testing.T) {
	t.Parallel()
	t.Run("空排除列表", func(_ *testing.T) {
		rr := NewRoundRobin()
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
		}

		got := rr.SelectExcluding(targets, nil)
		if got == nil {
			t.Fatal("SelectExcluding() = nil, want non-nil")
		}
	})

	t.Run("排除部分目标", func(_ *testing.T) {
		rr := NewRoundRobin()
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
			createHealthyTarget("http://backend3:8080", true),
		}
		excluded := []*Target{targets[0], targets[1]}

		got := rr.SelectExcluding(targets, excluded)
		if got == nil {
			t.Fatal("SelectExcluding() = nil, want non-nil")
		}
		if got.URL != "http://backend3:8080" {
			t.Errorf("SelectExcluding() = %q, want %q", got.URL, "http://backend3:8080")
		}
	})

	t.Run("排除所有目标", func(_ *testing.T) {
		rr := NewRoundRobin()
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
		}
		excluded := []*Target{targets[0], targets[1]}

		got := rr.SelectExcluding(targets, excluded)
		if got != nil {
			t.Errorf("SelectExcluding() = %v, want nil", got)
		}
	})

	t.Run("排除列表含nil", func(_ *testing.T) {
		rr := NewRoundRobin()
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
		}
		excluded := []*Target{nil, targets[0]}

		got := rr.SelectExcluding(targets, excluded)
		if got == nil {
			t.Fatal("SelectExcluding() = nil, want non-nil")
		}
		if got.URL == targets[0].URL {
			t.Errorf("选中了被排除的目标: %q", got.URL)
		}
	})

	t.Run("并发安全", func(_ *testing.T) {
		rr := NewRoundRobin()
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
			createHealthyTarget("http://backend3:8080", true),
		}
		excluded := []*Target{targets[0]}

		var wg sync.WaitGroup
		for range 100 {
			wg.Go(func() {
				got := rr.SelectExcluding(targets, excluded)
				if got != nil && got.URL == targets[0].URL {
					t.Errorf("选中了被排除的目标: %q", got.URL)
				}
			})
		}
		wg.Wait()
	})

	t.Run("排除不健康目标外再排除一个", func(_ *testing.T) {
		rr := NewRoundRobin()
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", false),
			createHealthyTarget("http://backend2:8080", true),
			createHealthyTarget("http://backend3:8080", true),
		}
		excluded := []*Target{targets[1]}

		got := rr.SelectExcluding(targets, excluded)
		if got == nil {
			t.Fatal("SelectExcluding() = nil, want non-nil")
		}
		if got.URL != "http://backend3:8080" {
			t.Errorf("SelectExcluding() = %q, want %q", got.URL, "http://backend3:8080")
		}
	})
}

// TestWeightedRoundRobin_SelectExcluding 测试加权轮询排除选择功能。
func TestWeightedRoundRobin_SelectExcluding(t *testing.T) {
	t.Parallel()
	t.Run("排除高权重目标", func(_ *testing.T) {
		wrr := NewWeightedRoundRobin()
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
		}
		targets[0].Weight = 1
		targets[1].Weight = 5
		excluded := []*Target{targets[1]}

		// 排除高权重目标后，只应选低权重目标
		for range 20 {
			got := wrr.SelectExcluding(targets, excluded)
			if got == nil {
				t.Fatal("SelectExcluding() = nil, want non-nil")
			}
			if got.URL != "http://backend1:8080" {
				t.Errorf("SelectExcluding() = %q, want %q", got.URL, "http://backend1:8080")
			}
		}
	})

	t.Run("排除所有健康目标", func(_ *testing.T) {
		wrr := NewWeightedRoundRobin()
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
		}
		excluded := []*Target{targets[0], targets[1]}

		got := wrr.SelectExcluding(targets, excluded)
		if got != nil {
			t.Errorf("SelectExcluding() = %v, want nil", got)
		}
	})

	t.Run("排除列表含nil", func(_ *testing.T) {
		wrr := NewWeightedRoundRobin()
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
		}
		targets[0].Weight = 1
		targets[1].Weight = 1
		excluded := []*Target{nil, targets[0]}

		got := wrr.SelectExcluding(targets, excluded)
		if got == nil {
			t.Fatal("SelectExcluding() = nil, want non-nil")
		}
		if got.URL == targets[0].URL {
			t.Errorf("选中了被排除的目标: %q", got.URL)
		}
	})
}

// TestLeastConnections_SelectExcluding 测试最少连接排除选择功能。
func TestLeastConnections_SelectExcluding(t *testing.T) {
	t.Parallel()
	t.Run("排除连接最少的目标", func(_ *testing.T) {
		lc := NewLeastConnections()
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
			createHealthyTarget("http://backend3:8080", true),
		}
		targets[0].Connections = 1
		targets[1].Connections = 10
		targets[2].Connections = 5
		excluded := []*Target{targets[0]}

		got := lc.SelectExcluding(targets, excluded)
		if got == nil {
			t.Fatal("SelectExcluding() = nil, want non-nil")
		}
		// 排除最少连接的后，应选连接数次少的
		if got.URL != "http://backend3:8080" {
			t.Errorf("SelectExcluding() = %q, want %q", got.URL, "http://backend3:8080")
		}
	})

	t.Run("排除列表含nil", func(_ *testing.T) {
		lc := NewLeastConnections()
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
		}
		targets[0].Connections = 5
		targets[1].Connections = 3
		excluded := []*Target{nil, targets[0]}

		got := lc.SelectExcluding(targets, excluded)
		if got == nil {
			t.Fatal("SelectExcluding() = nil, want non-nil")
		}
		if got.URL == targets[0].URL {
			t.Errorf("选中了被排除的目标: %q", got.URL)
		}
	})

	t.Run("全部排除", func(_ *testing.T) {
		lc := NewLeastConnections()
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
		}
		excluded := []*Target{targets[0], targets[1]}

		got := lc.SelectExcluding(targets, excluded)
		if got != nil {
			t.Errorf("SelectExcluding() = %v, want nil", got)
		}
	})
}

// TestIPHash_SelectExcluding 测试IP哈希排除选择功能。
func TestIPHash_SelectExcluding(t *testing.T) {
	t.Parallel()
	t.Run("排除命中目标", func(_ *testing.T) {
		ih := NewIPHash()
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
			createHealthyTarget("http://backend3:8080", true),
		}

		// 找到该IP会命中的目标
		clientIP := "192.168.1.100"
		first := ih.SelectByIP(targets, clientIP)
		if first == nil {
			t.Fatal("SelectByIP() = nil, want non-nil")
		}

		// 排除该目标
		excluded := []*Target{first}
		got := ih.SelectExcludingByIP(targets, excluded, clientIP)
		if got == nil {
			t.Fatal("SelectExcludingByIP() = nil, want non-nil")
		}
		if got.URL == first.URL {
			t.Errorf("SelectExcludingByIP() 选中了被排除的目标: %q", got.URL)
		}
	})

	t.Run("排除所有目标", func(_ *testing.T) {
		ih := NewIPHash()
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
		}
		excluded := []*Target{targets[0], targets[1]}

		got := ih.SelectExcludingByIP(targets, excluded, "10.0.0.1")
		if got != nil {
			t.Errorf("SelectExcludingByIP() = %v, want nil", got)
		}
	})

	t.Run("SelectExcluding使用空IP", func(_ *testing.T) {
		ih := NewIPHash()
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
		}
		excluded := []*Target{targets[0]}

		got := ih.SelectExcluding(targets, excluded)
		if got == nil {
			t.Fatal("SelectExcluding() = nil, want non-nil")
		}
	})

	t.Run("排除列表含nil", func(_ *testing.T) {
		ih := NewIPHash()
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
		}
		excluded := []*Target{nil, targets[0]}

		got := ih.SelectExcludingByIP(targets, excluded, "192.168.1.1")
		if got == nil {
			t.Fatal("SelectExcludingByIP() = nil, want non-nil")
		}
		if got.URL == targets[0].URL {
			t.Errorf("选中了被排除的目标: %q", got.URL)
		}
	})
}

// TestFilterHealthyAndExclude 测试filterHealthyAndExclude辅助函数。
func TestFilterHealthyAndExclude(t *testing.T) {
	t.Parallel()
	t.Run("基本过滤和排除", func(_ *testing.T) {
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", false),
			createHealthyTarget("http://backend3:8080", true),
		}
		excluded := []*Target{targets[0]}

		fc := acquireFilterContext()
		got := filterIntoExcluding(fc, targets, excluded)
		defer releaseFilterContext(fc)
		if len(got) != 1 {
			t.Fatalf("len = %d, want 1", len(got))
		}
		if got[0].URL != "http://backend3:8080" {
			t.Errorf("got = %q, want %q", got[0].URL, "http://backend3:8080")
		}
	})

	t.Run("空排除列表", func(_ *testing.T) {
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
		}

		fc := acquireFilterContext()
		got := filterIntoExcluding(fc, targets, nil)
		defer releaseFilterContext(fc)
		if len(got) != 2 {
			t.Fatalf("len = %d, want 2", len(got))
		}
	})

	t.Run("空目标列表", func(_ *testing.T) {
		fc := acquireFilterContext()
		got := filterIntoExcluding(fc, nil, []*Target{})
		defer releaseFilterContext(fc)
		if len(got) != 0 {
			t.Errorf("len = %d, want 0", len(got))
		}
	})

	t.Run("排除列表含nil", func(_ *testing.T) {
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
		}
		excluded := []*Target{nil}

		fc := acquireFilterContext()
		got := filterIntoExcluding(fc, targets, excluded)
		defer releaseFilterContext(fc)
		if len(got) != 1 {
			t.Fatalf("len = %d, want 1", len(got))
		}
	})
}

// TestTarget_Hostname 测试Target.Hostname方法。
func TestTarget_Hostname(t *testing.T) {
	t.Parallel()
	t.Run("从URL提取主机名", func(_ *testing.T) {
		target := NewTargetFromConfig("http://example.com:8080/api", 1, 0, 0, 0, false, false, "")
		got := target.Hostname()
		if got != "example.com" {
			t.Errorf("Hostname() = %q, want %q", got, "example.com")
		}
	})

	t.Run("无端口URL", func(_ *testing.T) {
		target := NewTargetFromConfig("http://example.com/api", 1, 0, 0, 0, false, false, "")
		got := target.Hostname()
		if got != "example.com" {
			t.Errorf("Hostname() = %q, want %q", got, "example.com")
		}
	})

	t.Run("无效URL主机名为空", func(_ *testing.T) {
		target := &Target{URL: "not-a-valid-url"}
		target.initHostname()
		got := target.Hostname()
		// url.Parse("not-a-valid-url") 解析为纯路径URL，Host为空
		if got != "" {
			t.Errorf("Hostname() = %q, want empty string", got)
		}
	})

	t.Run("缓存行为", func(_ *testing.T) {
		target := NewTargetFromConfig("http://example.com:8080", 1, 0, 0, 0, false, false, "")
		_ = target.Hostname()
		_ = target.Hostname() // 第二次应使用缓存
		got := target.Hostname()
		if got != "example.com" {
			t.Errorf("Hostname() = %q, want %q", got, "example.com")
		}
	})
}

// TestTarget_ResolvedIPs 测试Target.ResolvedIPs和SetResolvedIPs方法。
func TestTarget_ResolvedIPs(t *testing.T) {
	t.Parallel()
	t.Run("未设置时返回nil", func(_ *testing.T) {
		target := &Target{URL: "http://example.com"}
		got := target.ResolvedIPs()
		if got != nil {
			t.Errorf("ResolvedIPs() = %v, want nil", got)
		}
	})

	t.Run("设置后返回副本", func(_ *testing.T) {
		target := &Target{URL: "http://example.com"}
		ips := []string{"192.168.1.1", "192.168.1.2"}
		target.SetResolvedIPs(ips)

		got := target.ResolvedIPs()
		if len(got) != 2 {
			t.Fatalf("len = %d, want 2", len(got))
		}
		if got[0] != "192.168.1.1" || got[1] != "192.168.1.2" {
			t.Errorf("ResolvedIPs() = %v, want %v", got, ips)
		}

		// 修改原切片不影响内部存储
		ips[0] = "10.0.0.1"
		got2 := target.ResolvedIPs()
		if got2[0] != "192.168.1.1" {
			t.Errorf("ResolvedIPs() 受外部修改影响 = %q, want %q", got2[0], "192.168.1.1")
		}
	})

	t.Run("设置空列表", func(_ *testing.T) {
		target := &Target{URL: "http://example.com"}
		target.SetResolvedIPs([]string{})
		got := target.ResolvedIPs()
		if len(got) != 0 {
			t.Errorf("ResolvedIPs() = %v, want empty", got)
		}
	})
}

// TestTarget_NeedsResolve 测试Target.NeedsResolve方法。
func TestTarget_NeedsResolve(t *testing.T) {
	t.Parallel()
	t.Run("IP地址不需要解析", func(_ *testing.T) {
		target := NewTargetFromConfig("http://192.168.1.1:8080", 1, 0, 0, 0, false, false, "")
		if target.NeedsResolve(time.Minute) {
			t.Error("IP地址URL不需要解析")
		}
	})

	t.Run("首次解析需要", func(_ *testing.T) {
		target := NewTargetFromConfig("http://example.com:8080", 1, 0, 0, 0, false, false, "")
		if !target.NeedsResolve(time.Minute) {
			t.Error("首次解析应该需要")
		}
	})

	t.Run("TTL未过期不需要", func(_ *testing.T) {
		target := NewTargetFromConfig("http://example.com:8080", 1, 0, 0, 0, false, false, "")
		target.SetResolvedIPs([]string{"192.168.1.1"})
		// TTL为1小时，刚设置过，不应过期
		if target.NeedsResolve(time.Hour) {
			t.Error("TTL未过期不应该需要解析")
		}
	})

	t.Run("TTL过期需要", func(_ *testing.T) {
		target := NewTargetFromConfig("http://example.com:8080", 1, 0, 0, 0, false, false, "")
		target.SetResolvedIPs([]string{"192.168.1.1"})
		// 使用极短的TTL模拟过期
		if !target.NeedsResolve(time.Nanosecond) {
			t.Error("TTL过期应该需要解析")
		}
	})
}

// TestTarget_LastResolved 测试Target.LastResolved方法。
func TestTarget_LastResolved(t *testing.T) {
	t.Parallel()
	t.Run("未设置时返回零值", func(_ *testing.T) {
		target := &Target{URL: "http://example.com"}
		got := target.LastResolved()
		if !got.IsZero() {
			t.Errorf("LastResolved() = %v, want zero", got)
		}
	})

	t.Run("设置后返回时间", func(_ *testing.T) {
		target := &Target{URL: "http://example.com"}
		before := time.Now()
		target.SetResolvedIPs([]string{"192.168.1.1"})
		after := time.Now()

		got := target.LastResolved()
		if got.Before(before) || got.After(after) {
			t.Errorf("LastResolved() = %v, 应该在 %v 和 %v 之间", got, before, after)
		}
	})
}

// TestNewTargetFromConfig 测试NewTargetFromConfig函数。
func TestNewTargetFromConfig(t *testing.T) {
	t.Parallel()
	t.Run("创建健康目标", func(_ *testing.T) {
		target := NewTargetFromConfig("http://backend:8080", 5, 0, 0, 0, false, false, "")
		if target.URL != "http://backend:8080" {
			t.Errorf("URL = %q, want %q", target.URL, "http://backend:8080")
		}
		if target.Weight != 5 {
			t.Errorf("Weight = %d, want 5", target.Weight)
		}
		if !target.Healthy.Load() {
			t.Error("Healthy 应为 true")
		}
	})

	t.Run("主机名自动初始化", func(_ *testing.T) {
		target := NewTargetFromConfig("http://example.com:9090", 1, 0, 0, 0, false, false, "")
		got := target.Hostname()
		if got != "example.com" {
			t.Errorf("Hostname() = %q, want %q", got, "example.com")
		}
	})
}

// TestConsistentHash_PrecomputeHashes 测试预计算哈希功能。
func TestConsistentHash_PrecomputeHashes(t *testing.T) {
	t.Parallel()
	t.Run("预计算哈希值", func(_ *testing.T) {
		ch := NewConsistentHash(50, "ip")
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
		}

		ch.PrecomputeHashes(targets, 50)

		for _, target := range targets {
			if len(target.VirtualHashes) != 50 {
				t.Errorf("VirtualHashes len = %d, want 50", len(target.VirtualHashes))
			}
		}
	})

	t.Run("跳过已预计算的目标", func(_ *testing.T) {
		ch := NewConsistentHash(10, "ip")
		target := createHealthyTarget("http://backend1:8080", true)
		// 预计算一次
		ch.PrecomputeHashes([]*Target{target}, 10)
		firstHashes := make([]uint64, len(target.VirtualHashes))
		copy(firstHashes, target.VirtualHashes)

		// 再次预计算相同数量
		ch.PrecomputeHashes([]*Target{target}, 10)

		// 哈希值应保持不变
		for i, h := range target.VirtualHashes {
			if h != firstHashes[i] {
				t.Errorf("预计算改变了已有哈希值")
				break
			}
		}
	})

	t.Run("默认虚拟节点数", func(_ *testing.T) {
		ch := NewConsistentHash(0, "ip")
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
		}

		ch.PrecomputeHashes(targets, 0)

		if len(targets[0].VirtualHashes) != 150 {
			t.Errorf("VirtualHashes len = %d, want 150 (default)", len(targets[0].VirtualHashes))
		}
	})
}

// TestLeastConnections_ConcurrentSelection 测试最少连接并发选择。
func TestLeastConnections_ConcurrentSelection(t *testing.T) {
	t.Parallel()
	targets := []*Target{
		createHealthyTarget("http://backend1:8080", true),
		createHealthyTarget("http://backend2:8080", true),
		createHealthyTarget("http://backend3:8080", true),
	}
	lc := NewLeastConnections()

	var wg sync.WaitGroup
	for range 100 {
		wg.Go(func() {
			got := lc.Select(targets)
			if got == nil {
				t.Error("并发Select() = nil, want non-nil")
			}
		})
	}
	wg.Wait()
}

// TestWeightedRoundRobin_ConcurrentSelection 测试加权轮询并发选择。
func TestWeightedRoundRobin_ConcurrentSelection(t *testing.T) {
	t.Parallel()
	targets := []*Target{
		createHealthyTarget("http://backend1:8080", true),
		createHealthyTarget("http://backend2:8080", true),
	}
	targets[0].Weight = 3
	targets[1].Weight = 1
	wrr := NewWeightedRoundRobin()

	var wg sync.WaitGroup
	for range 100 {
		wg.Go(func() {
			got := wrr.Select(targets)
			if got == nil {
				t.Error("并发Select() = nil, want non-nil")
			}
		})
	}
	wg.Wait()
}

// TestIPHash_ConcurrentSelection 测试IP哈希并发选择。
func TestIPHash_ConcurrentSelection(t *testing.T) {
	t.Parallel()
	targets := []*Target{
		createHealthyTarget("http://backend1:8080", true),
		createHealthyTarget("http://backend2:8080", true),
	}
	ih := NewIPHash()

	var wg sync.WaitGroup
	for i := range 100 {
		wg.Add(1)
		go func(ip string) {
			defer wg.Done()
			got := ih.SelectByIP(targets, ip)
			if got == nil {
				t.Error("并发SelectByIP() = nil, want non-nil")
			}
		}(net.IP{192, 168, 1, byte(i)}.String())
	}
	wg.Wait()
}

// TestTarget_Hostname_IPURL 测试纯IP地址URL的主机名提取。
func TestTarget_Hostname_IPURL(t *testing.T) {
	t.Parallel()
	target := NewTargetFromConfig("http://10.0.0.1:8080", 1, 0, 0, 0, false, false, "")
	got := target.Hostname()
	if got != "10.0.0.1" {
		t.Errorf("Hostname() = %q, want %q", got, "10.0.0.1")
	}
}

// TestConsistentHash_SelectByKey_EmptyKey 测试空键选择行为。
func TestConsistentHash_SelectByKey_EmptyKey(t *testing.T) {
	t.Parallel()
	ch := NewConsistentHash(100, "ip")
	targets := []*Target{
		createHealthyTarget("http://backend1:8080", true),
	}

	// 空键也应该能选择（不会panic）
	got := ch.SelectByKey(targets, "")
	if got == nil {
		t.Fatal("SelectByKey(\"\") = nil, want non-nil")
	}
}

// TestConsistentHash_RebuildWithAllUnhealthy 测试所有目标不健康时重建。
func TestConsistentHash_RebuildWithAllUnhealthy(t *testing.T) {
	t.Parallel()
	ch := NewConsistentHash(10, "ip")
	targets := []*Target{
		createHealthyTarget("http://backend1:8080", false),
		createHealthyTarget("http://backend2:8080", false),
	}

	ch.Rebuild(targets)
	stats := ch.GetStats()

	if stats.CircleSize != 0 {
		t.Errorf("CircleSize = %d, want 0", stats.CircleSize)
	}
	if stats.SortedHashes != 0 {
		t.Errorf("SortedHashes = %d, want 0", stats.SortedHashes)
	}
}

// TestConsistentHash_GetStats 测试统计信息完整性。
func TestConsistentHash_GetStats(t *testing.T) {
	t.Parallel()
	ch := NewConsistentHash(50, "uri")
	targets := []*Target{
		createHealthyTarget("http://backend1:8080", true),
		createHealthyTarget("http://backend2:8080", true),
		createHealthyTarget("http://backend3:8080", true),
	}

	ch.Rebuild(targets)
	stats := ch.GetStats()

	if stats.VirtualNodes != 50 {
		t.Errorf("VirtualNodes = %d, want 50", stats.VirtualNodes)
	}
	if stats.CircleSize != 150 { // 3 targets * 50 nodes
		t.Errorf("CircleSize = %d, want 150", stats.CircleSize)
	}
	if stats.SortedHashes != 150 {
		t.Errorf("SortedHashes = %d, want 150", stats.SortedHashes)
	}
}

// TestConsistentHash_GetHashKey 测试哈希键配置获取。
func TestConsistentHash_GetHashKey(t *testing.T) {
	t.Parallel()
	tests := []struct {
		name    string
		hashKey string
		want    string
	}{
		{"ip", "ip", "ip"},
		{"uri", "uri", "uri"},
		{"header", "header:X-Forwarded-For", "header:X-Forwarded-For"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(_ *testing.T) {
			ch := NewConsistentHash(100, tt.hashKey)
			if ch.GetHashKey() != tt.want {
				t.Errorf("GetHashKey() = %q, want %q", ch.GetHashKey(), tt.want)
			}
		})
	}
}

// TestSelectExcluding_DynamicRebuild 测试SelectByKey触发的动态重建。
func TestSelectExcluding_DynamicRebuild(t *testing.T) {
	t.Parallel()
	ch := NewConsistentHash(10, "ip")
	targets := []*Target{
		createHealthyTarget("http://backend1:8080", true),
		createHealthyTarget("http://backend2:8080", true),
	}

	// 不手动Rebuild，SelectByKey应自动触发
	got := ch.SelectByKey(targets, "10.0.0.1")
	if got == nil {
		t.Fatal("SelectByKey() = nil after auto-rebuild, want non-nil")
	}
}

// TestWeightedRoundRobin_NegativeWeight 测试负权重行为。
func TestWeightedRoundRobin_NegativeWeight(t *testing.T) {
	t.Parallel()
	wrr := NewWeightedRoundRobin()
	targets := []*Target{
		createHealthyTarget("http://backend1:8080", true),
		createHealthyTarget("http://backend2:8080", true),
	}
	targets[0].Weight = -5
	targets[1].Weight = 3

	// 负权重要被当作1处理
	counts := make(map[string]int)
	for range 100 {
		got := wrr.Select(targets)
		if got == nil {
			t.Fatal("Select() = nil, want non-nil")
		}
		counts[got.URL]++
	}

	// 两个目标都应该被选中
	if counts["http://backend1:8080"] == 0 {
		t.Error("负权重目标从未被选中")
	}
	if counts["http://backend2:8080"] == 0 {
		t.Error("正权重目标从未被选中")
	}
}

// TestRoundRobin_NilTargets 测试nil切片输入。
func TestRoundRobin_NilTargets(t *testing.T) {
	t.Parallel()
	rr := NewRoundRobin()
	got := rr.Select(nil)
	if got != nil {
		t.Errorf("Select(nil) = %v, want nil", got)
	}
}

// TestLeastConnections_NilTargets 测试nil切片输入。
func TestLeastConnections_NilTargets(t *testing.T) {
	t.Parallel()
	lc := NewLeastConnections()
	got := lc.Select(nil)
	if got != nil {
		t.Errorf("Select(nil) = %v, want nil", got)
	}
}

func TestTargetIsAvailable(t *testing.T) {
	t.Parallel()
	t.Run("healthy target is available", func(t *testing.T) {
		target := NewTargetFromConfig("http://localhost:8080", 1, 0, 0, 0, false, false, "")
		if !target.IsAvailable() {
			t.Error("healthy target should be available")
		}
	})

	t.Run("down target is not available", func(t *testing.T) {
		target := NewTargetFromConfig("http://localhost:8080", 1, 0, 0, 0, false, true, "")
		if target.IsAvailable() {
			t.Error("down target should not be available")
		}
	})

	t.Run("unhealthy target is not available", func(t *testing.T) {
		target := NewTargetFromConfig("http://localhost:8080", 1, 0, 0, 0, false, false, "")
		target.Healthy.Store(false)
		if target.IsAvailable() {
			t.Error("unhealthy target should not be available")
		}
	})

	t.Run("max connections exceeded", func(t *testing.T) {
		target := NewTargetFromConfig("http://localhost:8080", 1, 2, 0, 0, false, false, "")
		IncrementConnections(target)
		IncrementConnections(target)
		if target.IsAvailable() {
			t.Error("target at max connections should not be available")
		}
	})

	t.Run("within max connections", func(t *testing.T) {
		target := NewTargetFromConfig("http://localhost:8080", 1, 2, 0, 0, false, false, "")
		IncrementConnections(target)
		if !target.IsAvailable() {
			t.Error("target under max connections should be available")
		}
	})
}

func TestTargetRecordFailure(t *testing.T) {
	t.Parallel()
	t.Run("record failure increments count", func(t *testing.T) {
		target := NewTargetFromConfig("http://localhost:8080", 1, 0, 3, 10*time.Second, false, false, "")
		count := target.RecordFailure()
		if count != 1 {
			t.Errorf("expected fail count 1, got %d", count)
		}
	})

	t.Run("target becomes unavailable after max fails", func(t *testing.T) {
		target := NewTargetFromConfig("http://localhost:8080", 1, 0, 2, 10*time.Second, false, false, "")
		target.RecordFailure()
		target.RecordFailure()
		if target.IsAvailable() {
			t.Error("target should be unavailable after reaching max fails")
		}
	})

	t.Run("default fail timeout is 10s", func(t *testing.T) {
		target := NewTargetFromConfig("http://localhost:8080", 1, 0, 1, 0, false, false, "")
		target.RecordFailure()
		if target.IsAvailable() {
			t.Error("target should be unavailable with default timeout")
		}
	})
}

func TestTargetRecordSuccess(t *testing.T) {
	t.Parallel()
	t.Run("record success resets fail count", func(t *testing.T) {
		target := NewTargetFromConfig("http://localhost:8080", 1, 0, 3, 10*time.Second, false, false, "")
		target.RecordFailure()
		target.RecordFailure()
		target.RecordSuccess()
		if target.failCount.Load() != 0 {
			t.Error("fail count should be reset after success")
		}
		if !target.IsAvailable() {
			t.Error("target should be available after success resets cooldown")
		}
	})
}

func TestFilterHealthyBackup(t *testing.T) {
	t.Parallel()
	t.Run("prefers non-backup targets", func(t *testing.T) {
		primary := NewTargetFromConfig("http://primary:8080", 1, 0, 0, 0, false, false, "")
		backup := NewTargetFromConfig("http://backup:8080", 1, 0, 0, 0, true, false, "")
		targets := []*Target{primary, backup}

		fc := acquireFilterContext()
		result := filterInto(fc, targets)
		defer releaseFilterContext(fc)
		if len(result) != 1 || result[0].URL != "http://primary:8080" {
			t.Error("should prefer non-backup target")
		}
	})

	t.Run("falls back to backup when primary unavailable", func(t *testing.T) {
		primary := NewTargetFromConfig("http://primary:8080", 1, 0, 0, 0, false, false, "")
		primary.Healthy.Store(false)
		backup := NewTargetFromConfig("http://backup:8080", 1, 0, 0, 0, true, false, "")
		targets := []*Target{primary, backup}

		fc := acquireFilterContext()
		result := filterInto(fc, targets)
		defer releaseFilterContext(fc)
		if len(result) != 1 || result[0].URL != "http://backup:8080" {
			t.Error("should fall back to backup target")
		}
	})
}

// TestConsistentHash_Select 测试一致性哈希 Select 方法（委托给 SelectByKey）。
func TestConsistentHash_Select(t *testing.T) {
	t.Parallel()
	t.Run("委托给SelectByKey", func(_ *testing.T) {
		ch := NewConsistentHash(100, "ip")
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
		}

		// Select 内部调用 SelectByKey(targets, "")
		got := ch.Select(targets)
		if got == nil {
			t.Fatal("Select() = nil, want non-nil")
		}
	})

	t.Run("空目标返回nil", func(_ *testing.T) {
		ch := NewConsistentHash(100, "ip")
		got := ch.Select([]*Target{})
		if got != nil {
			t.Errorf("Select() = %v, want nil", got)
		}
	})

	t.Run("单目标直接返回", func(_ *testing.T) {
		ch := NewConsistentHash(100, "ip")
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
		}

		got := ch.Select(targets)
		if got == nil {
			t.Fatal("Select() = nil, want non-nil")
		}
		if got.URL != "http://backend1:8080" {
			t.Errorf("Select() = %q, want %q", got.URL, "http://backend1:8080")
		}
	})

	t.Run("多目标一致性", func(_ *testing.T) {
		ch := NewConsistentHash(100, "ip")
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
			createHealthyTarget("http://backend3:8080", true),
		}

		// 多次调用应该返回相同结果（空键的一致性）
		first := ch.Select(targets)
		for range 10 {
			got := ch.Select(targets)
			if got == nil {
				t.Fatal("Select() = nil, want non-nil")
			}
			if got.URL != first.URL {
				t.Errorf("Select() 不一致: first=%q, got=%q", first.URL, got.URL)
			}
		}
	})
}

// TestConsistentHash_SelectExcluding 测试一致性哈希 SelectExcluding 方法。
func TestConsistentHash_SelectExcluding(t *testing.T) {
	t.Parallel()
	t.Run("委托给SelectExcludingByKey", func(_ *testing.T) {
		ch := NewConsistentHash(100, "ip")
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
			createHealthyTarget("http://backend2:8080", true),
		}
		ch.Rebuild(targets)

		excluded := []*Target{targets[0]}
		got := ch.SelectExcluding(targets, excluded)
		if got == nil {
			t.Fatal("SelectExcluding() = nil, want non-nil")
		}
		if got.URL == targets[0].URL {
			t.Errorf("选中了被排除的目标: %q", got.URL)
		}
	})

	t.Run("空排除列表", func(_ *testing.T) {
		ch := NewConsistentHash(100, "ip")
		targets := []*Target{
			createHealthyTarget("http://backend1:8080", true),
		}
		ch.Rebuild(targets)

		got := ch.SelectExcluding(targets, nil)
		if got == nil {
			t.Fatal("SelectExcluding() = nil, want non-nil")
		}
	})
}

// TestRandomBalancer 测试随机负载均衡器。
func TestRandomBalancer(t *testing.T) {
	t.Parallel()
	t.Run("selects from available targets", func(t *testing.T) {
		targets := []*Target{
			NewTargetFromConfig("http://a:8080", 1, 0, 0, 0, false, false, ""),
			NewTargetFromConfig("http://b:8080", 1, 0, 0, 0, false, false, ""),
		}
		b := NewRandom()
		selected := b.Select(targets)
		if selected == nil {
			t.Error("should select a target")
		}
	})

	t.Run("returns nil when no available targets", func(t *testing.T) {
		targets := []*Target{
			NewTargetFromConfig("http://a:8080", 1, 0, 0, 0, false, true, ""),
		}
		b := NewRandom()
		selected := b.Select(targets)
		if selected != nil {
			t.Error("should return nil for no available targets")
		}
	})

	t.Run("select excluding works", func(t *testing.T) {
		targets := []*Target{
			NewTargetFromConfig("http://a:8080", 1, 0, 0, 0, false, false, ""),
			NewTargetFromConfig("http://b:8080", 1, 0, 0, 0, false, false, ""),
		}
		b := NewRandom()
		selected := b.SelectExcluding(targets, targets[:1])
		if selected == nil || selected.URL == "http://a:8080" {
			t.Error("should exclude first target")
		}
	})

	t.Run("select excluding all targets returns nil", func(t *testing.T) {
		targets := []*Target{
			NewTargetFromConfig("http://a:8080", 1, 0, 0, 0, false, false, ""),
			NewTargetFromConfig("http://b:8080", 1, 0, 0, 0, false, false, ""),
		}
		b := NewRandom()
		selected := b.SelectExcluding(targets, targets)
		if selected != nil {
			t.Error("should return nil when all targets excluded")
		}
	})

	t.Run("select excluding empty list", func(t *testing.T) {
		targets := []*Target{
			NewTargetFromConfig("http://a:8080", 1, 0, 0, 0, false, false, ""),
		}
		b := NewRandom()
		selected := b.SelectExcluding(targets, nil)
		if selected == nil {
			t.Error("should select a target with empty exclusion")
		}
	})

	t.Run("select excluding with nil in excluded list", func(t *testing.T) {
		targets := []*Target{
			NewTargetFromConfig("http://a:8080", 1, 0, 0, 0, false, false, ""),
			NewTargetFromConfig("http://b:8080", 1, 0, 0, 0, false, false, ""),
		}
		b := NewRandom()
		selected := b.SelectExcluding(targets, []*Target{nil})
		if selected == nil {
			t.Error("should select a target even with nil in excluded list")
		}
	})

	t.Run("power of two choices prefers fewer connections", func(t *testing.T) {
		targets := []*Target{
			NewTargetFromConfig("http://a:8080", 1, 0, 0, 0, false, false, ""),
			NewTargetFromConfig("http://b:8080", 1, 0, 0, 0, false, false, ""),
		}
		targets[0].Connections = 100
		targets[1].Connections = 1
		b := NewRandom()

		// 多次选择，验证总是选择连接数少的目标
		for range 100 {
			selected := b.Select(targets)
			if selected == nil {
				t.Error("should select a target")
				continue
			}
			// Power of Two Choices 总是选择连接数少的
			if selected.URL != "http://b:8080" {
				t.Errorf("should prefer target with fewer connections, got %q", selected.URL)
			}
		}
	})

	t.Run("power of two choices with equal connections", func(t *testing.T) {
		targets := []*Target{
			NewTargetFromConfig("http://a:8080", 1, 0, 0, 0, false, false, ""),
			NewTargetFromConfig("http://b:8080", 1, 0, 0, 0, false, false, ""),
		}
		targets[0].Connections = 10
		targets[1].Connections = 10
		b := NewRandom()

		// 连接数相等时，两个目标都应该被选中
		counts := make(map[string]int)
		for range 100 {
			selected := b.Select(targets)
			if selected != nil {
				counts[selected.URL]++
			}
		}

		if counts["http://a:8080"] == 0 || counts["http://b:8080"] == 0 {
			t.Error("both targets should be selected when connections are equal")
		}
	})
}

// TestBalancerIntegration_LeastTime 验证 Least Time 算法 consistently 选择更快目标。
func TestBalancerIntegration_LeastTime(t *testing.T) {
	targets := []*Target{
		NewTargetFromConfig("http://slow:8080", 1, 0, 0, 0, false, false, ""),
		NewTargetFromConfig("http://fast:8080", 1, 0, 0, 0, false, false, ""),
	}

	lt := NewLeastTime("last_byte", time.Millisecond)

	// 模拟：slow 目标有 100ms avg，fast 有 10ms avg
	for i := 0; i < 10; i++ {
		targets[0].Stats.Record(50*time.Millisecond, 100*time.Millisecond)
		targets[1].Stats.Record(5*time.Millisecond, 10*time.Millisecond)
	}

	// 选择 100 次，应该 mostly 选 fast
	fastCount := 0
	for i := 0; i < 100; i++ {
		selected := lt.Select(targets)
		if selected.URL == "http://fast:8080" {
			fastCount++
		}
	}

	if fastCount < 80 {
		t.Errorf("fast target selected %d/100 times, expected >80", fastCount)
	}
}

// TestBalancerIntegration_StickyWithLeastTimeFallback 验证 Sticky 在目标不健康时 fallback。
func TestBalancerIntegration_StickyWithLeastTimeFallback(t *testing.T) {
	fallback := NewLeastTime("last_byte", time.Millisecond)
	config := StickyConfig{
		Enabled:  true,
		Name:     "test_route",
		Expires:  time.Hour,
		Path:     "/",
		HttpOnly: true,
	}

	sticky := NewStickySession(config, fallback)
	sticky.Start()
	defer sticky.Stop()

	targets := []*Target{
		NewTargetFromConfig("http://backend1:8080", 1, 0, 0, 0, false, false, ""),
		NewTargetFromConfig("http://backend2:8080", 1, 0, 0, 0, false, false, ""),
	}

	ctx := &fasthttp.RequestCtx{}

	// 首次请求
	selected1 := sticky.Select(ctx, targets)
	if selected1 == nil {
		t.Fatal("expected a target")
	}

	// 验证 cookie 已设置
	cookie := ctx.Response.Header.PeekCookie("test_route")
	if len(cookie) == 0 {
		t.Fatal("expected cookie")
	}

	// 使 selected1 不健康
	selected1.Healthy.Store(false)

	// 第二次请求带 cookie 应该 fallback
	ctx2 := &fasthttp.RequestCtx{}
	ctx2.Request.Header.SetCookie("test_route", string(extractCookieValue(cookie)))

	selected2 := sticky.Select(ctx2, targets)
	if selected2 == nil {
		t.Fatal("expected fallback target")
	}
	if selected2.URL == selected1.URL {
		t.Error("expected different target after fallback")
	}
}

// extractCookieValue 从 Set-Cookie header 中提取 cookie 值
func extractCookieValue(cookieHeader []byte) []byte {
	s := string(cookieHeader)
	// Format: "name=value; ..."
	parts := strings.SplitN(s, "=", 2)
	if len(parts) != 2 {
		return nil
	}
	valueParts := strings.SplitN(parts[1], ";", 2)
	return []byte(valueParts[0])
}
