package node

import (
	"fmt"
	"sort"
	"strings"
	"testing"
)

// TestServerUserListCacheKeysForServer 验证按 server 枚举出的协议缓存 key 覆盖
// 所有客户端可能携带的 protocol（包括 hysteria2 兼容字段），形态为
// `server:user:{server_id}:{protocol}`。HIF-1: Del 路径必须用枚举而非 SCAN。
func TestServerUserListCacheKeysForServer(t *testing.T) {
	const serverId int64 = 42

	keys := ServerUserListCacheKeysForServer(serverId)
	if len(keys) != len(AllProtocols) {
		t.Fatalf("expected %d keys, got %d: %v", len(AllProtocols), len(keys), keys)
	}

	got := make([]string, len(keys))
	copy(got, keys)
	sort.Strings(got)

	want := make([]string, 0, len(AllProtocols))
	for _, p := range AllProtocols {
		want = append(want, fmt.Sprintf("%s%d:%s", ServerUserListCacheKey, serverId, p))
	}
	sort.Strings(want)

	for i := range got {
		if got[i] != want[i] {
			t.Errorf("key[%d] = %q, want %q", i, got[i], want[i])
		}
	}
}

// TestServerUserListCacheKeysForServer_NoLegacyFlatKey 验证清缓存路径不再使用
// 旧的扁平 key `server:user:{server_id}`（无 protocol 维度）——旧 key 一旦再出现，
// 与 P0-1 写入的带 protocol key 形态不一致，Del 会失效，回归 HIF-1 缺陷。
func TestServerUserListCacheKeysForServer_NoLegacyFlatKey(t *testing.T) {
	const serverId int64 = 7

	legacy := fmt.Sprintf("%s%d", ServerUserListCacheKey, serverId)
	for _, key := range ServerUserListCacheKeysForServer(serverId) {
		if key == legacy {
			t.Fatalf("Del path still emits legacy flat key %q without protocol", legacy)
		}
		if !strings.HasPrefix(key, legacy+":") {
			t.Errorf("key %q does not match `<flat>:<protocol>` shape", key)
		}
	}
}

// TestAllProtocolsContainsKnownProtocols 兜底保证 AllProtocols 至少覆盖关键协议；
// 缺失任一会让对应协议的用户列表缓存清不掉。
func TestAllProtocolsContainsKnownProtocols(t *testing.T) {
	required := []string{
		"shadowsocks",
		"vmess",
		"vless",
		"trojan",
		"tuic",
		"hysteria",
		"hysteria2",
	}
	set := make(map[string]struct{}, len(AllProtocols))
	for _, p := range AllProtocols {
		set[p] = struct{}{}
	}
	for _, r := range required {
		if _, ok := set[r]; !ok {
			t.Errorf("AllProtocols missing %q", r)
		}
	}
}
