package service

import (
	"fmt"
	"net"
	"runtime"
	"sync"
	"sync/atomic"
	"testing"
	"time"

	toki "git.toki-labs.com/toki/proto-socket/go"
	"google.golang.org/protobuf/proto"
	edgeevents "iop/apps/edge/internal/events"
	edgenode "iop/apps/edge/internal/node"
	"iop/packages/go/config"
	iop "iop/proto/gen/iop"
)

func TestListNodeSnapshotsUsesEdgeQueueState(t *testing.T) {
	reg := edgenode.NewRegistry()
	reg.Register(&edgenode.NodeEntry{NodeID: "node-q-1", Alias: "node-q-1"})

	store := edgenode.NewNodeStore()
	rec := &edgenode.NodeRecord{
		ID: "node-q-1",
		Adapters: config.AdaptersConf{
			OllamaInstances: []config.OllamaInstanceConf{
				{
					Name:     "ollama-inst",
					Enabled:  true,
					Capacity: 3,
				},
			},
		},
	}
	store.Add(rec)

	bus := edgeevents.NewBus()
	svc := New(reg, bus)
	svc.SetNodeStore(store)

	svc.queue.mu.Lock()
	svc.queue.groups["test-group"] = &modelQueueGroup{
		key:      "test-group",
		adapter:  "ollama-inst",
		inflight: map[string]int{"node-q-1": 2},
		queue: []*queueItem{
			{
				candidates: []candidateNode{
					{entry: reg.All()[0], capacity: 3},
				},
			},
		},
	}
	svc.queue.mu.Unlock()

	snaps := svc.ListNodeSnapshots()
	if len(snaps) != 1 {
		t.Fatalf("expected 1 node snapshot, got %d", len(snaps))
	}
	snap := snaps[0]
	if len(snap.ProviderSnapshots) != 1 {
		t.Fatalf("expected 1 provider snapshot, got %d", len(snap.ProviderSnapshots))
	}
	p := snap.ProviderSnapshots[0]
	if p.Adapter != "ollama-inst" {
		t.Errorf("expected adapter ollama-inst, got %s", p.Adapter)
	}
	if p.Capacity != 3 {
		t.Errorf("expected capacity 3, got %d", p.Capacity)
	}
	if p.InFlight != 2 {
		t.Errorf("expected inflight 2, got %d", p.InFlight)
	}
	if p.Queued != 1 {
		t.Errorf("expected queued 1, got %d", p.Queued)
	}
}

func TestListNodeSnapshotsTypeRouteSingleNamedInstance(t *testing.T) {
	reg := edgenode.NewRegistry()
	reg.Register(&edgenode.NodeEntry{NodeID: "node-q-2", Alias: "node-q-2"})

	store := edgenode.NewNodeStore()
	rec := &edgenode.NodeRecord{
		ID: "node-q-2",
		Adapters: config.AdaptersConf{
			OllamaInstances: []config.OllamaInstanceConf{
				{
					Name:     "ollama-local",
					Enabled:  true,
					Capacity: 5,
				},
			},
		},
	}
	store.Add(rec)

	bus := edgeevents.NewBus()
	svc := New(reg, bus)
	svc.SetNodeStore(store)

	svc.queue.mu.Lock()
	svc.queue.groups["test-group"] = &modelQueueGroup{
		key:      "test-group",
		adapter:  "ollama",
		inflight: map[string]int{"node-q-2": 3},
		queue: []*queueItem{
			{
				candidates: []candidateNode{
					{entry: reg.All()[0], capacity: 5},
				},
			},
		},
	}
	svc.queue.mu.Unlock()

	snaps := svc.ListNodeSnapshots()
	if len(snaps) != 1 {
		t.Fatalf("expected 1 node snapshot, got %d", len(snaps))
	}
	snap := snaps[0]
	if len(snap.ProviderSnapshots) != 1 {
		t.Fatalf("expected 1 provider snapshot, got %d", len(snap.ProviderSnapshots))
	}
	p := snap.ProviderSnapshots[0]
	if p.Adapter != "ollama-local" {
		t.Errorf("expected adapter ollama-local, got %s", p.Adapter)
	}
	if p.Capacity != 5 {
		t.Errorf("expected capacity 5, got %d", p.Capacity)
	}
	if p.InFlight != 3 {
		t.Errorf("expected inflight 3, got %d", p.InFlight)
	}
	if p.Queued != 1 {
		t.Errorf("expected queued 1, got %d", p.Queued)
	}
}

func TestListNodeSnapshotsProviderEmptyAdapterFallbackToProviderID(t *testing.T) {
	reg := edgenode.NewRegistry()
	reg.Register(&edgenode.NodeEntry{NodeID: "node-e-1", Alias: "node-e-1"})

	store := edgenode.NewNodeStore()
	rec := &edgenode.NodeRecord{
		ID:       "node-e-1",
		Adapters: config.AdaptersConf{},
		Providers: []config.NodeProviderConf{
			{
				ID:       "standalone-provider",
				Type:     "ollama",
				Category: config.CategoryLocalInference,
				Adapter:  "",
				Models:   []string{"test-model"},
				Capacity: 2,
			},
		},
		Runtime: config.RuntimeConf{Concurrency: 2},
	}
	store.Add(rec)

	bus := edgeevents.NewBus()
	svc := New(reg, bus)
	svc.SetNodeStore(store)

	svc.queue.mu.Lock()
	key := providerResourceKey{nodeID: "node-e-1", providerID: "standalone-provider"}
	res := svc.queue.resources[key]
	if res == nil {
		res = &providerResourceState{
			nodeID:     "node-e-1",
			providerID: "standalone-provider",
			capacity:   2,
			enabled:    true,
		}
		svc.queue.resources[key] = res
	}
	res.inFlight = 1

	svc.queue.groups["test-group"] = &modelQueueGroup{
		key:     "test-group",
		adapter: "standalone-provider",
		queue: []*queueItem{
			{
				candidates: []candidateNode{
					{entry: reg.All()[0], capacity: 2, providerID: "standalone-provider"},
				},
			},
		},
	}
	svc.queue.mu.Unlock()

	snaps := svc.ListNodeSnapshots()
	if len(snaps) != 1 {
		t.Fatalf("expected 1 node snapshot, got %d", len(snaps))
	}
	snap := snaps[0]

	found := false
	for i, ps := range snap.ProviderSnapshots {
		if ps.Id == "standalone-provider" {
			found = true
			if ps.InFlight != 1 {
				t.Errorf("expected InFlight=1 for standalone-provider (adapter empty), got %d", ps.InFlight)
			}
			if ps.Queued != 1 {
				t.Errorf("expected Queued=1 for standalone-provider (adapter empty), got %d", ps.Queued)
			}
			if ps.Capacity != 2 {
				t.Errorf("expected Capacity=2 for standalone-provider, got %d", ps.Capacity)
			}
			expectedLoadRatio := float32(1) / float32(2)
			if ps.LoadRatio != expectedLoadRatio {
				t.Errorf("expected LoadRatio=%.2f for standalone-provider, got %.2f", expectedLoadRatio, ps.LoadRatio)
			}
			t.Logf("provider snapshot[%d]: id=%s, adapter=%s, InFlight=%d, Queued=%d, Capacity=%d, LoadRatio=%.2f",
				i, ps.Id, ps.Adapter, ps.InFlight, ps.Queued, ps.Capacity, ps.LoadRatio)
			break
		}
	}
	if !found {
		t.Fatalf("expected provider snapshot with id=standalone-provider, got %d provider snapshots", len(snap.ProviderSnapshots))
	}
}

func TestListNodeSnapshotsProviderCatalogSupersedesAdapterSnapshots(t *testing.T) {
	reg := edgenode.NewRegistry()
	reg.Register(&edgenode.NodeEntry{NodeID: "node-cs-1", Alias: "node-cs-1"})

	store := edgenode.NewNodeStore()
	rec := &edgenode.NodeRecord{
		ID: "node-cs-1",
		Adapters: config.AdaptersConf{
			Ollama: config.OllamaConf{Enabled: true, BaseURL: "http://127.0.0.1:11434"},
			OpenAICompatInstances: []config.OpenAICompatInstanceConf{
				{Name: "vllm-gpu", Enabled: true},
			},
		},
		Providers: []config.NodeProviderConf{
			{ID: "prov-cat-1", Adapter: "vllm-gpu", Models: []string{"model-x"}, Health: "available", Capacity: 4},
			{ID: "prov-cat-2", Adapter: "vllm-gpu", Models: []string{"model-y"}, Health: "available", Capacity: 2},
		},
		Runtime: config.RuntimeConf{Concurrency: 1},
	}
	store.Add(rec)

	bus := edgeevents.NewBus()
	svc := New(reg, bus)
	svc.SetNodeStore(store)

	snaps := svc.ListNodeSnapshots()
	if len(snaps) != 1 {
		t.Fatalf("expected 1 node snapshot, got %d", len(snaps))
	}
	snap := snaps[0]

	if len(snap.ProviderSnapshots) != 2 {
		t.Fatalf("expected 2 catalog snapshots, got %d: %+v",
			len(snap.ProviderSnapshots), snap.ProviderSnapshots)
	}
	ids := map[string]bool{}
	for _, p := range snap.ProviderSnapshots {
		if p.Id == "" {
			t.Errorf("unexpected adapter-only snapshot (empty Id): %+v", p)
		}
		ids[p.Id] = true
	}
	if !ids["prov-cat-1"] || !ids["prov-cat-2"] {
		t.Errorf("expected catalog IDs prov-cat-1 and prov-cat-2, got: %v", ids)
	}
}

func TestListNodeSnapshotsCatalogProviderZeroCapacityDoesNotUseRuntimeFallback(t *testing.T) {
	reg := edgenode.NewRegistry()
	reg.Register(&edgenode.NodeEntry{NodeID: "node-zero-cap", Alias: "node-zero-cap"})

	store := edgenode.NewNodeStore()
	rec := &edgenode.NodeRecord{
		ID: "node-zero-cap",
		Adapters: config.AdaptersConf{
			OpenAICompatInstances: []config.OpenAICompatInstanceConf{
				{Name: "vllm-gpu", Enabled: true, Capacity: 7},
			},
		},
		Providers: []config.NodeProviderConf{
			{ID: "prov-zero", Adapter: "vllm-gpu", Models: []string{"model-zero"}, Health: "available", Capacity: 0},
		},
		Runtime: config.RuntimeConf{Concurrency: 7},
	}
	store.Add(rec)

	bus := edgeevents.NewBus()
	svc := New(reg, bus)
	svc.SetNodeStore(store)

	snaps := svc.ListNodeSnapshots()
	if len(snaps) != 1 {
		t.Fatalf("expected 1 node snapshot, got %d", len(snaps))
	}
	if len(snaps[0].ProviderSnapshots) != 1 {
		t.Fatalf("expected 1 provider snapshot, got %d", len(snaps[0].ProviderSnapshots))
	}
	p := snaps[0].ProviderSnapshots[0]
	if p.Id != "prov-zero" {
		t.Fatalf("expected provider id prov-zero, got %q", p.Id)
	}
	if p.Capacity != 0 {
		t.Fatalf("provider catalog capacity must not fall back to runtime concurrency: got %d", p.Capacity)
	}
	if p.LoadRatio != 0 {
		t.Fatalf("expected zero load ratio for zero capacity provider, got %.2f", p.LoadRatio)
	}
}

func TestStaticProviderCatalogSnapshotsZeroCapacityDoesNotUseRuntimeFallback(t *testing.T) {
	rec := &edgenode.NodeRecord{
		ID: "node-static-zero-cap",
		Providers: []config.NodeProviderConf{
			{ID: "prov-zero", Adapter: "vllm-gpu", Models: []string{"model-zero"}, Health: "available", Capacity: 0},
		},
		Runtime: config.RuntimeConf{Concurrency: 7},
	}

	snaps := staticProviderCatalogSnapshots(rec, true)
	if len(snaps) != 1 {
		t.Fatalf("expected 1 provider snapshot, got %d", len(snaps))
	}
	if snaps[0].Capacity != 0 {
		t.Fatalf("static provider catalog capacity must not fall back to runtime concurrency: got %d", snaps[0].Capacity)
	}
}

func TestListNodeSnapshotsAdapterFallbackWhenNoProviders(t *testing.T) {
	reg := edgenode.NewRegistry()
	reg.Register(&edgenode.NodeEntry{NodeID: "node-legacy-snap", Alias: "node-legacy-snap"})

	store := edgenode.NewNodeStore()
	rec := &edgenode.NodeRecord{
		ID: "node-legacy-snap",
		Adapters: config.AdaptersConf{
			Ollama: config.OllamaConf{Enabled: true, BaseURL: "http://127.0.0.1:11434"},
			OllamaInstances: []config.OllamaInstanceConf{
				{Name: "ollama-local", Enabled: true, Capacity: 3},
			},
		},
		Runtime: config.RuntimeConf{Concurrency: 2},
	}
	store.Add(rec)

	bus := edgeevents.NewBus()
	svc := New(reg, bus)
	svc.SetNodeStore(store)

	snaps := svc.ListNodeSnapshots()
	if len(snaps) != 1 {
		t.Fatalf("expected 1 node snapshot, got %d", len(snaps))
	}
	snap := snaps[0]

	if len(snap.ProviderSnapshots) != 1 {
		t.Fatalf("expected 1 ollama-local adapter snapshot, got %d: %+v",
			len(snap.ProviderSnapshots), snap.ProviderSnapshots)
	}
	adapters := map[string]bool{}
	for _, p := range snap.ProviderSnapshots {
		adapters[p.Adapter] = true
	}
	if !adapters["ollama-local"] {
		t.Errorf("expected ollama-local adapter snapshot, got: %v", adapters)
	}
}

func TestListNodeSnapshotsProviderIdDiffersFromAdapterKey(t *testing.T) {
	reg := edgenode.NewRegistry()
	reg.Register(&edgenode.NodeEntry{NodeID: "node-p-1", Alias: "node-p-1"})

	store := edgenode.NewNodeStore()
	rec := &edgenode.NodeRecord{
		ID: "node-p-1",
		Adapters: config.AdaptersConf{
			OllamaInstances: []config.OllamaInstanceConf{
				{Name: "vllm-gpu", Enabled: true, Capacity: 4},
			},
		},
		Providers: []config.NodeProviderConf{
			{
				ID:       "provider-vllm-primary",
				Type:     "vllm",
				Category: config.CategoryAPI,
				Adapter:  "vllm-gpu",
				Models:   []string{"nvidia/Qwen3.6-35B"},
				Capacity: 4,
			},
		},
		Runtime: config.RuntimeConf{Concurrency: 2},
	}
	store.Add(rec)

	bus := edgeevents.NewBus()
	svc := New(reg, bus)
	svc.SetNodeStore(store)

	svc.queue.mu.Lock()
	key := providerResourceKey{nodeID: "node-p-1", providerID: "provider-vllm-primary"}
	res := svc.queue.resources[key]
	if res == nil {
		res = &providerResourceState{
			nodeID:     "node-p-1",
			providerID: "provider-vllm-primary",
			capacity:   4,
			enabled:    true,
		}
		svc.queue.resources[key] = res
	}
	res.inFlight = 2

	svc.queue.groups["test-group"] = &modelQueueGroup{
		key:     "test-group",
		adapter: "vllm-gpu",
		queue: []*queueItem{
			{
				candidates: []candidateNode{
					{entry: reg.All()[0], capacity: 4, providerID: "provider-vllm-primary"},
				},
			},
		},
	}
	svc.queue.mu.Unlock()

	snaps := svc.ListNodeSnapshots()
	if len(snaps) != 1 {
		t.Fatalf("expected 1 node snapshot, got %d", len(snaps))
	}
	snap := snaps[0]

	var p *config.NodeProviderConf
	for i := range snap.ProviderSnapshots {
		ps := snap.ProviderSnapshots[i]
		if ps.Id == "provider-vllm-primary" {
			p = &config.NodeProviderConf{
				Capacity: int(ps.Capacity),
			}
			if ps.InFlight != 2 {
				t.Errorf("expected InFlight=2 for provider-vllm-primary, got %d", ps.InFlight)
			}
			if ps.Queued != 1 {
				t.Errorf("expected Queued=1 for provider-vllm-primary, got %d", ps.Queued)
			}
			if ps.Adapter != "vllm-gpu" {
				t.Errorf("expected Adapter=vllm-gpu for provider-vllm-primary, got %s", ps.Adapter)
			}
			break
		}
	}
	if p == nil {
		t.Fatalf("expected provider snapshot with id=provider-vllm-primary, got %d provider snapshots", len(snap.ProviderSnapshots))
	}
}

func TestListNodeSnapshotsLongContextFields(t *testing.T) {
	reg := edgenode.NewRegistry()
	reg.Register(&edgenode.NodeEntry{NodeID: "node-long-1", Alias: "node-long-1"})

	store := edgenode.NewNodeStore()
	rec := &edgenode.NodeRecord{
		ID: "node-long-1",
		Providers: []config.NodeProviderConf{
			{
				ID:                  "long-provider",
				Type:                "vllm",
				Category:            config.CategoryAPI,
				Adapter:             "vllm-gpu",
				Models:              []string{"long-model"},
				Capacity:            4,
				LongContextCapacity: 2,
			},
		},
		Runtime: config.RuntimeConf{Concurrency: 2},
	}
	store.Add(rec)

	bus := edgeevents.NewBus()
	svc := New(reg, bus)
	svc.SetNodeStore(store)

	svc.queue.mu.Lock()
	key := providerResourceKey{nodeID: "node-long-1", providerID: "long-provider"}
	res := svc.queue.resources[key]
	if res == nil {
		res = &providerResourceState{
			nodeID:       "node-long-1",
			providerID:   "long-provider",
			capacity:     4,
			longCapacity: 2,
			enabled:      true,
		}
		svc.queue.resources[key] = res
	}
	res.inFlight = 1
	res.longInFlight = 1

	svc.queue.groups["test-group"] = &modelQueueGroup{
		key:     "test-group",
		adapter: "vllm-gpu",
		queue: []*queueItem{
			{
				candidates: []candidateNode{
					{entry: reg.All()[0], capacity: 4, providerID: "long-provider"},
				},
				long: true,
			},
		},
	}
	svc.queue.mu.Unlock()

	snaps := svc.ListNodeSnapshots()
	if len(snaps) != 1 {
		t.Fatalf("expected 1 node snapshot, got %d", len(snaps))
	}
	snap := snaps[0]
	if len(snap.ProviderSnapshots) != 1 {
		t.Fatalf("expected 1 provider snapshot, got %d", len(snap.ProviderSnapshots))
	}
	p := snap.ProviderSnapshots[0]
	if p.Id != "long-provider" {
		t.Errorf("expected long-provider, got %s", p.Id)
	}
	if p.LongContextCapacity != 2 {
		t.Errorf("expected LongContextCapacity 2, got %d", p.LongContextCapacity)
	}
	if p.LongInFlight != 1 {
		t.Errorf("expected LongInFlight 1, got %d", p.LongInFlight)
	}
	if p.LongQueued != 1 {
		t.Errorf("expected LongQueued 1, got %d", p.LongQueued)
	}
}

func TestProviderSnapshotQueuedCountsCandidatePressureAcrossModelGroups(t *testing.T) {
	reg := edgenode.NewRegistry()
	entry := &edgenode.NodeEntry{NodeID: "node-pressure", Alias: "node-pressure"}
	reg.Register(entry)

	store := edgenode.NewNodeStore()
	rec := &edgenode.NodeRecord{
		ID: "node-pressure",
		Providers: []config.NodeProviderConf{
			{
				ID:                  "provider-shared",
				Type:                "vllm",
				Category:            config.CategoryAPI,
				Models:              []string{"model-a", "model-b"},
				Health:              "available",
				Capacity:            1,
				LongContextCapacity: 1,
			},
			{
				ID:                  "provider-fallback",
				Type:                "vllm",
				Category:            config.CategoryAPI,
				Models:              []string{"model-a"},
				Health:              "available",
				Capacity:            1,
				LongContextCapacity: 1,
			},
		},
	}
	store.Add(rec)

	svc := New(reg, edgeevents.NewBus())
	svc.SetNodeStore(store)

	svc.queue.mu.Lock()
	svc.queue.groups["model-a"] = &modelQueueGroup{
		key: "model-a",
		queue: []*queueItem{
			{
				candidates: []candidateNode{
					{entry: entry, providerID: "provider-shared"},
					{entry: entry, providerID: "provider-fallback"},
				},
			},
		},
	}
	svc.queue.groups["model-b"] = &modelQueueGroup{
		key: "model-b",
		queue: []*queueItem{
			{
				candidates: []candidateNode{
					{entry: entry, providerID: "provider-shared"},
				},
				long: true,
			},
		},
	}
	svc.queue.mu.Unlock()

	snaps := svc.ListNodeSnapshots()
	if len(snaps) != 1 {
		t.Fatalf("expected 1 node snapshot, got %d", len(snaps))
	}
	if len(snaps[0].ProviderSnapshots) != 2 {
		t.Fatalf("expected 2 provider snapshots, got %d", len(snaps[0].ProviderSnapshots))
	}

	byID := make(map[string]*iop.ProviderSnapshot, len(snaps[0].ProviderSnapshots))
	for _, snapshot := range snaps[0].ProviderSnapshots {
		byID[snapshot.GetId()] = snapshot
	}

	shared := byID["provider-shared"]
	if shared == nil {
		t.Fatal("provider-shared snapshot not found")
	}
	if shared.GetQueued() != 2 || shared.GetLongQueued() != 1 {
		t.Fatalf("shared candidate pressure mismatch: queued=%d long_queued=%d", shared.GetQueued(), shared.GetLongQueued())
	}

	fallback := byID["provider-fallback"]
	if fallback == nil {
		t.Fatal("provider-fallback snapshot not found")
	}
	if fallback.GetQueued() != 1 || fallback.GetLongQueued() != 0 {
		t.Fatalf("fallback candidate pressure mismatch: queued=%d long_queued=%d", fallback.GetQueued(), fallback.GetLongQueued())
	}

	if total := shared.GetQueued() + fallback.GetQueued(); total != 3 {
		t.Fatalf("provider candidate pressure should be non-additive across 2 Edge pending requests: got total=%d", total)
	}
}

func TestProviderSnapshotReadsResourceState(t *testing.T) {
	reg := edgenode.NewRegistry()
	reg.Register(&edgenode.NodeEntry{NodeID: "node-snap-test", Alias: "node-snap-test"})

	store := edgenode.NewNodeStore()
	rec := &edgenode.NodeRecord{
		ID:      "node-snap-test",
		Runtime: config.RuntimeConf{Concurrency: 5},
		Providers: []config.NodeProviderConf{
			{
				ID:                  "snap-prov",
				Adapter:             "vllm",
				Capacity:            3,
				LongContextCapacity: 2,
				Enabled:             nil,
			},
		},
	}
	store.Add(rec)

	bus := edgeevents.NewBus()
	svc := New(reg, bus)
	svc.SetNodeStore(store)

	svc.queue.mu.Lock()
	key := providerResourceKey{nodeID: "node-snap-test", providerID: "snap-prov"}
	res := svc.queue.resources[key]
	if res == nil {
		svc.queue.mu.Unlock()
		t.Fatal("resource state not found after SetNodeStore")
	}
	res.inFlight = 2
	res.longInFlight = 1
	svc.queue.mu.Unlock()

	snaps := svc.ListNodeSnapshots()
	if len(snaps) != 1 {
		t.Fatalf("expected 1 node snapshot, got %d", len(snaps))
	}
	snap := snaps[0]
	if len(snap.ProviderSnapshots) != 1 {
		t.Fatalf("expected 1 provider snapshot, got %d", len(snap.ProviderSnapshots))
	}
	p := snap.ProviderSnapshots[0]
	if p.InFlight != 2 {
		t.Errorf("expected InFlight 2, got %d", p.InFlight)
	}
	if p.LongInFlight != 1 {
		t.Errorf("expected LongInFlight 1, got %d", p.LongInFlight)
	}
}

func TestProviderSnapshotIgnoresLegacyFallbackState(t *testing.T) {
	reg := edgenode.NewRegistry()
	reg.Register(&edgenode.NodeEntry{NodeID: "node-fallback-test", Alias: "node-fallback-test"})

	store := edgenode.NewNodeStore()
	rec := &edgenode.NodeRecord{
		ID:      "node-fallback-test",
		Runtime: config.RuntimeConf{Concurrency: 5},
		Providers: []config.NodeProviderConf{
			{
				ID:                  "fallback-prov",
				Adapter:             "vllm",
				Capacity:            3,
				LongContextCapacity: 2,
				Enabled:             nil,
			},
		},
	}
	store.Add(rec)

	bus := edgeevents.NewBus()
	svc := New(reg, bus)
	svc.SetNodeStore(store)

	trackTestLease(svc.queue, "test-group", "run-legacy", "node-fallback-test", "fallback-prov", true)

	svc.queue.mu.Lock()
	svc.queue.groups["test-group"] = &modelQueueGroup{
		key:          "test-group",
		adapter:      "vllm",
		inflight:     map[string]int{"node-fallback-test:fallback-prov": 1},
		longInflight: map[string]int{"node-fallback-test:fallback-prov": 1},
	}
	key := providerResourceKey{nodeID: "node-fallback-test", providerID: "fallback-prov"}
	res := svc.queue.resources[key]
	if res == nil {
		svc.queue.mu.Unlock()
		t.Fatal("resource state not found")
	}
	res.inFlight = 0
	res.longInFlight = 0
	svc.queue.mu.Unlock()

	snaps := svc.ListNodeSnapshots()
	if len(snaps) != 1 {
		t.Fatalf("expected 1 node snapshot")
	}
	p := snaps[0].ProviderSnapshots[0]
	if p.InFlight != 0 {
		t.Errorf("expected InFlight 0, got %d", p.InFlight)
	}
	if p.LongInFlight != 0 {
		t.Errorf("expected LongInFlight 0, got %d", p.LongInFlight)
	}
}

// findProviderSnapshotOnNode finds a provider snapshot by nodeID and providerID
// from the production ListNodeSnapshots output. It is used by lifecycle tests
// that assert provider state through the actual snapshot surface rather than
// reading internal queue/resource maps directly.
func findProviderSnapshotOnNode(snaps []NodeSnapshot, nodeID, providerID string) *iop.ProviderSnapshot {
	for _, snap := range snaps {
		if snap.NodeID == nodeID {
			for _, ps := range snap.ProviderSnapshots {
				if ps.Id == providerID {
					return ps
				}
			}
		}
	}
	return nil
}

// assertProviderSnapshotState asserts individual provider snapshot fields
// read from production ListNodeSnapshots. All four counters are independent so
// that mixed-field regressions (e.g., inFlight set but queued not cleared) are
// caught. The production surface is the only assertion channel: the internal
// queue/resource maps are implementation details.
func assertProviderSnapshotState(t *testing.T, snaps []NodeSnapshot, nodeID, providerID, label string,
	inFlight, queued, longInFlight, longQueued int32) {
	t.Helper()
	ps := findProviderSnapshotOnNode(snaps, nodeID, providerID)
	if ps == nil {
		t.Fatalf("%s: provider %s snapshot not found on %s in ListNodeSnapshots", label, providerID, nodeID)
	}
	if ps.GetId() != providerID {
		t.Errorf("%s %s id mismatch: want %s, got %s", label, providerID, providerID, ps.GetId())
	}
	if ps.GetInFlight() != inFlight {
		t.Errorf("%s %s inFlight: want %d, got %d", label, providerID, inFlight, ps.GetInFlight())
	}
	if ps.GetQueued() != queued {
		t.Errorf("%s %s queued: want %d, got %d", label, providerID, queued, ps.GetQueued())
	}
	if ps.GetLongInFlight() != longInFlight {
		t.Errorf("%s %s longInFlight: want %d, got %d", label, providerID, longInFlight, ps.GetLongInFlight())
	}
	if ps.GetLongQueued() != longQueued {
		t.Errorf("%s %s longQueued: want %d, got %d", label, providerID, longQueued, ps.GetLongQueued())
	}
}

// snapshotTuple describes the exact provider snapshot tuple (status, configured
// capacity, in-flight, queued, long-context in-flight, long-context queued).
// Used by the pure validateSnapshotTuple so every concurrent reader compares
// the same canonical field set without touching *testing.T.
type snapshotTuple struct {
	status       string
	capacity     int32
	inFlight     int32
	queued       int32
	longInFlight int32
	longQueued   int32
}

// validateSnapshotTuple compares a snapshotTuple against an expected tuple and
// returns nil on exact match or an error listing the first mismatched field.
// Pure function: does not touch *testing.T so storm readers can collect
// failures through a bounded channel without blocking on t.Fatal.
func validateSnapshotTuple(got, want snapshotTuple) error {
	if got.status != want.status {
		return fmt.Errorf("status: want %q, got %q", want.status, got.status)
	}
	if got.capacity != want.capacity {
		return fmt.Errorf("capacity: want %d, got %d", want.capacity, got.capacity)
	}
	if got.inFlight != want.inFlight {
		return fmt.Errorf("inFlight: want %d, got %d", want.inFlight, got.inFlight)
	}
	if got.queued != want.queued {
		return fmt.Errorf("queued: want %d, got %d", want.queued, got.queued)
	}
	if got.longInFlight != want.longInFlight {
		return fmt.Errorf("longInFlight: want %d, got %d", want.longInFlight, got.longInFlight)
	}
	if got.longQueued != want.longQueued {
		return fmt.Errorf("longQueued: want %d, got %d", want.longQueued, got.longQueued)
	}
	return nil
}

// snapshotFailure carries one reader's first validation error for bounded
// delivery through a snapReaders-sized channel during the concurrent storm.
// The main goroutine owns all t.Fatal/Error calls.
type snapshotFailure struct {
	reader int
	err    error
}

// exactProviderTuples builds a provider-ID → snapshotTuple map from a node's
// snapshot, rejecting missing or duplicate providers with an error. Used by the
// concurrent storm reader so each expected provider is proven present and only
// once before any tuple comparison.
func exactProviderTuples(snaps []NodeSnapshot, nodeID string, expectedIDs ...string) (map[string]snapshotTuple, error) {
	var nodeSnap *NodeSnapshot
	for i := range snaps {
		if snaps[i].NodeID == nodeID {
			nodeSnap = &snaps[i]
			break
		}
	}
	if nodeSnap == nil {
		return nil, fmt.Errorf("node %s not found in ListNodeSnapshots", nodeID)
	}
	seen := make(map[string]snapshotTuple, len(expectedIDs))
	for _, ps := range nodeSnap.ProviderSnapshots {
		pid := ps.GetId()
		if pid == "" {
			continue
		}
		t := snapshotTuple{
			status:       ps.GetStatus(),
			capacity:     ps.GetCapacity(),
			inFlight:     ps.GetInFlight(),
			queued:       ps.GetQueued(),
			longInFlight: ps.GetLongInFlight(),
			longQueued:   ps.GetLongQueued(),
		}
		if _, dup := seen[pid]; dup {
			return nil, fmt.Errorf("duplicate provider %s on %s", pid, nodeID)
		}
		seen[pid] = t
	}
	for _, wantID := range expectedIDs {
		if _, ok := seen[wantID]; !ok {
			return nil, fmt.Errorf("expected provider %s missing on %s", wantID, nodeID)
		}
	}
	return seen, nil
}

// reportFirstSnapshotFailure sends err through errCh as a reader's first
// validation failure. Non-blocking: if the channel is full, the reader exits
// silently so a stuck channel never deadlocks the storm.
func reportFirstSnapshotFailure(errCh chan<- snapshotFailure, readerID int, err error) {
	select {
	case errCh <- snapshotFailure{reader: readerID, err: err}:
	default:
	}
}

// TestProviderSnapshotLiveCandidatePressureFollowsRefreshAcrossModelGroups
// verifies that a provider snapshot reflects live candidate pressure from actual
// SubmitRun waiter dispatches across model groups, covering both the normal and
// long-context lifecycle (enqueue, dispatch, terminal zero). The holder and
// waiter go through real admission → pump → terminal lifecycle, not direct
// queue injection.
func TestProviderSnapshotLiveCandidatePressureFollowsRefreshAcrossModelGroups(t *testing.T) {
	for _, tc := range []struct {
		name         string
		contextClass string
		wantLong     int
	}{
		{name: "normal"},
		{name: "long", contextClass: contextClassLong, wantLong: 1},
	} {
		t.Run(tc.name, func(t *testing.T) {
			parserMap := toki.ParserMap{
				toki.TypeNameOf(&iop.RunRequest{}): func(b []byte) (proto.Message, error) {
					m := &iop.RunRequest{}
					return m, proto.Unmarshal(b, m)
				},
			}

			edgeConn, nodeConn := net.Pipe()
			defer edgeConn.Close()
			defer nodeConn.Close()
			edgeClient := toki.NewTcpClient(edgeConn, 0, 0, parserMap)
			_ = toki.NewTcpClient(nodeConn, 0, 0, parserMap)

			const nodeID = "node-lifecycle"
			reg := edgenode.NewRegistry()
			reg.Register(&edgenode.NodeEntry{NodeID: nodeID, Client: edgeClient})
			bus := edgeevents.NewBus()
			svc := New(reg, bus)

			catalog := []config.ModelCatalogEntry{
				{
					ID:        "model-a",
					Providers: map[string]string{"prov-shared": "served-a"},
				},
				{
					ID:        "model-b",
					Providers: map[string]string{"prov-fallback": "served-b"},
				},
				{
					ID: "model-wait",
					Providers: map[string]string{
						"prov-shared":   "served-shared",
						"prov-fallback": "served-fallback",
					},
				},
			}

			makeStore := func(longCap int) *edgenode.NodeStore {
				store := edgenode.NewNodeStore()
				store.Add(&edgenode.NodeRecord{
					ID: nodeID,
					Adapters: config.AdaptersConf{
						VllmInstances: []config.VllmInstanceConf{
							{Name: "vllm-gpu", Enabled: true},
						},
					},
					Providers: []config.NodeProviderConf{
						{
							ID: "prov-shared", Type: "vllm", Category: config.CategoryAPI,
							Adapter: "vllm-gpu", Models: []string{"served-a", "served-shared"},
							Health: "available", Capacity: 1, LongContextCapacity: longCap,
						},
						{
							ID: "prov-fallback", Type: "vllm", Category: config.CategoryAPI,
							Adapter: "vllm-gpu", Models: []string{"served-b", "served-fallback"},
							Health: "available", Capacity: 1, LongContextCapacity: longCap,
						},
					},
				})
				return store
			}

			svc.SetRuntimeConfig(makeStore(tc.wantLong), catalog, groupPolicy{})

			// 1. Holder A for model-a → dispatched to prov-shared immediately.
			holderA, err := svc.SubmitRun(t.Context(), SubmitRunRequest{
				ModelGroupKey: "model-a", ProviderPool: true, Background: true,
				ContextClass: tc.contextClass,
			})
			if err != nil || holderA == nil {
				t.Fatalf("holder A submit: %v", err)
			}
			hA := holderA.Dispatch()
			if got := hA.ProviderID; got != "prov-shared" {
				t.Fatalf("holder A expected prov-shared, got %s", got)
			}

			// 2. Holder B for model-b → dispatched to prov-fallback immediately.
			holderB, err := svc.SubmitRun(t.Context(), SubmitRunRequest{
				ModelGroupKey: "model-b", ProviderPool: true, Background: true,
				ContextClass: tc.contextClass,
			})
			if err != nil || holderB == nil {
				t.Fatalf("holder B submit: %v", err)
			}
			hB := holderB.Dispatch()
			if got := hB.ProviderID; got != "prov-fallback" {
				t.Fatalf("holder B expected prov-fallback, got %s", got)
			}

			// Snapshot while both holders are in-flight and no waiter: queued must be 0.
			snaps := svc.ListNodeSnapshots()
			assertProviderSnapshotState(t, snaps, nodeID, "prov-shared", "step1-holders",
				1, 0, int32(tc.wantLong), 0)
			assertProviderSnapshotState(t, snaps, nodeID, "prov-fallback", "step1-holders",
				1, 0, int32(tc.wantLong), 0)

			// 3. Waiter for model-wait → queues because both providers are full.
			type submitResult struct {
				run RunResult
				err error
			}
			resultCh := make(chan submitResult, 1)
			go func() {
				run, err := svc.SubmitRun(t.Context(), SubmitRunRequest{
					ModelGroupKey: "model-wait", ProviderPool: true, Background: true,
					ContextClass: tc.contextClass,
				})
				resultCh <- submitResult{run: run, err: err}
			}()

			// Poll until the waiter is enqueued.
			deadline := time.After(2 * time.Second)
			waiterQueued := false
			for {
				svc.queue.mu.Lock()
				group := svc.queue.groups["model-wait"]
				count := 0
				if group != nil {
					count = len(group.queue)
				}
				svc.queue.mu.Unlock()
				if count == 1 {
					waiterQueued = true
					break
				}
				select {
				case <-deadline:
					t.Fatal("waiter was not enqueued within timeout")
				default:
					runtime.Gosched()
				}
			}
			if !waiterQueued {
				t.Fatal("waiter not enqueued")
			}

			// Snapshot while waiter is queued: each provider has in_flight=1
			// from its holder AND queued=1 from the waiter's candidate.
			snaps = svc.ListNodeSnapshots()
			assertProviderSnapshotState(t, snaps, nodeID, "prov-shared", "step2-queued",
				1, 1, int32(tc.wantLong), int32(tc.wantLong))
			assertProviderSnapshotState(t, snaps, nodeID, "prov-fallback", "step2-queued",
				1, 1, int32(tc.wantLong), int32(tc.wantLong))

			// 4. Release holder B (fallback) → waiter dispatches to fallback.
			svc.HandleRunLifecycleEvent(&iop.RunEvent{RunId: hB.RunID, Type: "complete"})

			var waiterRes submitResult
			select {
			case waiterRes = <-resultCh:
			case <-time.After(2 * time.Second):
				t.Fatal("waiter did not dispatch after fallback release")
			}
			if waiterRes.err != nil {
				t.Fatalf("waiter submit error: %v", waiterRes.err)
			}
			if waiterRes.run == nil {
				t.Fatal("waiter expected non-nil result")
			}
			defer waiterRes.run.Close()
			wDispatch := waiterRes.run.Dispatch()
			if got := wDispatch.ProviderID; got != "prov-fallback" {
				t.Fatalf("waiter expected dispatch to prov-fallback, got %s", got)
			}

			// Snapshot after dispatch.
			snaps = svc.ListNodeSnapshots()
			assertProviderSnapshotState(t, snaps, nodeID, "prov-shared", "step3-dispatched",
				1, 0, int32(tc.wantLong), 0)
			assertProviderSnapshotState(t, snaps, nodeID, "prov-fallback", "step3-dispatched",
				1, 0, int32(tc.wantLong), 0)

			// 5. Terminal for holder A (shared).
			svc.HandleRunLifecycleEvent(&iop.RunEvent{RunId: hA.RunID, Type: "complete"})
			snaps = svc.ListNodeSnapshots()
			assertProviderSnapshotState(t, snaps, nodeID, "prov-shared", "step4-shared-terminal",
				0, 0, 0, 0)
			assertProviderSnapshotState(t, snaps, nodeID, "prov-fallback", "step4-shared-terminal",
				1, 0, int32(tc.wantLong), 0)

			// 6. Terminal for waiter → full drain.
			svc.HandleRunLifecycleEvent(&iop.RunEvent{RunId: wDispatch.RunID, Type: "complete"})
			snaps = svc.ListNodeSnapshots()
			assertProviderSnapshotState(t, snaps, nodeID, "prov-shared", "step5-all-terminal",
				0, 0, 0, 0)
			assertProviderSnapshotState(t, snaps, nodeID, "prov-fallback", "step5-all-terminal",
				0, 0, 0, 0)

			// Final counters and lease must be fully zero.
			aInFlight, aLong := providerResourceCounts(svc.queue, nodeID, "prov-shared")
			bInFlight, bLong := providerResourceCounts(svc.queue, nodeID, "prov-fallback")
			if aInFlight != 0 || aLong != 0 {
				t.Fatalf("expected prov-shared drained to 0, got inFlight=%d longInFlight=%d", aInFlight, aLong)
			}
			if bInFlight != 0 || bLong != 0 {
				t.Fatalf("expected prov-fallback drained to 0, got inFlight=%d longInFlight=%d", bInFlight, bLong)
			}
			if lc := leaseCount(svc.queue); lc != 0 {
				t.Fatalf("expected leaseCount=0 after all terminals, got %d", lc)
			}
		})
	}
}

// TestProviderSnapshotConcurrentRefreshPressureUsesLiveCandidates drives
// concurrent runtime refresh and snapshot reads against a queued waiter.
// Every snapshot tuple is asserted to be a fully-consistent old-or-new state:
// enabled providers must have (status=available, configured capacity, in-flight
// from current lease, queued from live candidates); disabled providers must have
// every effective counter and capacity zero. Each reader records at most one
// invalid-tuple failure so the storm cannot block on the bounded channel.
func TestProviderSnapshotConcurrentRefreshPressureUsesLiveCandidates(t *testing.T) {
	parserMap := toki.ParserMap{
		toki.TypeNameOf(&iop.RunRequest{}): func(b []byte) (proto.Message, error) {
			m := &iop.RunRequest{}
			return m, proto.Unmarshal(b, m)
		},
	}

	edgeConn, nodeConn := net.Pipe()
	defer edgeConn.Close()
	defer nodeConn.Close()
	edgeClient := toki.NewTcpClient(edgeConn, 0, 0, parserMap)
	_ = toki.NewTcpClient(nodeConn, 0, 0, parserMap)

	const nodeID = "node-concurrent"
	reg := edgenode.NewRegistry()
	reg.Register(&edgenode.NodeEntry{NodeID: nodeID, Client: edgeClient})
	bus := edgeevents.NewBus()
	svc := New(reg, bus)

	catalog := []config.ModelCatalogEntry{
		{
			ID:        "model-a",
			Providers: map[string]string{"prov-shared": "served-a"},
		},
		{
			ID:        "model-b",
			Providers: map[string]string{"prov-fallback": "served-b"},
		},
		{
			ID: "model-conc",
			Providers: map[string]string{
				"prov-shared":   "served-shared",
				"prov-fallback": "served-fallback",
			},
		},
	}

	makeStore := func(fallbackEnabled bool) *edgenode.NodeStore {
		enabledFlag := fallbackEnabled
		store := edgenode.NewNodeStore()
		store.Add(&edgenode.NodeRecord{
			ID: nodeID,
			Adapters: config.AdaptersConf{
				VllmInstances: []config.VllmInstanceConf{
					{Name: "vllm-gpu", Enabled: true},
				},
			},
			Providers: []config.NodeProviderConf{
				{
					ID: "prov-shared", Type: "vllm", Category: config.CategoryAPI,
					Adapter: "vllm-gpu", Models: []string{"served-a", "served-shared"},
					Health: "available", Capacity: 1,
				},
				{
					ID: "prov-fallback", Type: "vllm", Category: config.CategoryAPI,
					Adapter: "vllm-gpu", Models: []string{"served-b", "served-fallback"},
					Health: "available", Capacity: 1, Enabled: &enabledFlag,
				},
			},
		})
		return store
	}

	enabledStore := makeStore(true)
	concDisabledStore := makeStore(false)

	svc.SetRuntimeConfig(enabledStore, catalog, groupPolicy{})

	holderA, err := svc.SubmitRun(t.Context(), SubmitRunRequest{
		ModelGroupKey: "model-a", ProviderPool: true, Background: true,
	})
	if err != nil || holderA == nil {
		t.Fatalf("holder A submit: %v", err)
	}
	defer holderA.Close()

	holderB, err := svc.SubmitRun(t.Context(), SubmitRunRequest{
		ModelGroupKey: "model-b", ProviderPool: true, Background: true,
	})
	if err != nil || holderB == nil {
		t.Fatalf("holder B submit: %v", err)
	}
	defer holderB.Close()

	type submitResult struct {
		run RunResult
		err error
	}
	resultCh := make(chan submitResult, 1)
	go func() {
		run, err := svc.SubmitRun(t.Context(), SubmitRunRequest{
			ModelGroupKey: "model-conc", ProviderPool: true, Background: true,
		})
		resultCh <- submitResult{run: run, err: err}
	}()

	waitForQueueLen(t, svc.queue, "model-conc", 1)

	// Snapshot while queued with both enabled — using production ListNodeSnapshots
	// so the assertion exercises the actual snapshot surface.
	snaps := svc.ListNodeSnapshots()
	assertProviderSnapshotState(t, snaps, nodeID, "prov-shared", "conc-pre-storm",
		1, 1, 0, 0)
	assertProviderSnapshotState(t, snaps, nodeID, "prov-fallback", "conc-pre-storm",
		1, 1, 0, 0)

	// Expected tuples for exact concurrent storm validation.
	// prov-shared is always enabled: capacity=1, inFlight=1 (holder A), queued=1 (waiter candidate).
	expectedShared := snapshotTuple{
		status: "available", capacity: 1, inFlight: 1, queued: 1,
		longInFlight: 0, longQueued: 0,
	}
	// prov-fallback alternates: enabled (same tuple as shared) or disabled (all zeros).
	expectedFallbackEnabled := snapshotTuple{
		status: "available", capacity: 1, inFlight: 1, queued: 1,
		longInFlight: 0, longQueued: 0,
	}
	expectedFallbackDisabled := snapshotTuple{
		status: "disabled", capacity: 0, inFlight: 0, queued: 0,
		longInFlight: 0, longQueued: 0,
	}

	// --- Concurrent storm ---
	// Bounded failure channel sized to reader count: each reader delivers at
	// most one first-error, so the channel never fills and the storm cannot
	// deadlock on send. Main goroutine owns all t.Fatal/Error.
	const snapReaders = 4
	errCh := make(chan snapshotFailure, snapReaders)

	start := make(chan struct{})
	stop := make(chan struct{})
	var wg sync.WaitGroup

	wg.Add(1)
	go func() {
		defer wg.Done()
		<-start
		for {
			select {
			case <-stop:
				return
			default:
				svc.SetRuntimeConfig(enabledStore, catalog, groupPolicy{})
				svc.SetRuntimeConfig(concDisabledStore, catalog, groupPolicy{})
			}
		}
	}()

	var (
		fallbackSeenAvailable atomic.Bool
		fallbackSeenDisabled  atomic.Bool
	)

	for r := 0; r < snapReaders; r++ {
		wg.Add(1)
		go func(readerID int) {
			defer wg.Done()
			<-start
			for {
				select {
				case <-stop:
					return
				default:
				}
				snaps := svc.ListNodeSnapshots()
				if len(snaps) == 0 {
					runtime.Gosched()
					continue
				}

				byID, err := exactProviderTuples(snaps, nodeID, "prov-shared", "prov-fallback")
				if err != nil {
					reportFirstSnapshotFailure(errCh, readerID, err)
					return
				}
				if err := validateSnapshotTuple(byID["prov-shared"], expectedShared); err != nil {
					reportFirstSnapshotFailure(errCh, readerID, err)
					return
				}
				switch fb := byID["prov-fallback"]; {
				case validateSnapshotTuple(fb, expectedFallbackEnabled) == nil:
					fallbackSeenAvailable.Store(true)
				case validateSnapshotTuple(fb, expectedFallbackDisabled) == nil:
					fallbackSeenDisabled.Store(true)
				default:
					reportFirstSnapshotFailure(errCh, readerID, fmt.Errorf(
						"fallback tuple mismatch: got status=%q capacity=%d inflight=%d queued=%d",
						fb.status, fb.capacity, fb.inFlight, fb.queued))
					return
				}
			}
		}(r)
	}

	close(start)
	time.Sleep(300 * time.Millisecond)
	close(stop)
	wg.Wait()
	close(errCh)

	// Main goroutine owns all t.Fatal/Error: each reader delivered at most one
	// first-error through the bounded channel, so this loop never blocks.
	for f := range errCh {
		t.Errorf("reader %d: %v", f.reader, f.err)
	}

	// Fallback must have been observed in both enabled and disabled states during
	// the storm — a torn-tuple regression that silently passed every fallback read
	// as one state would leave one of the flags unset.
	if !fallbackSeenAvailable.Load() {
		t.Fatal("concurrent storm never sampled fallback in available state")
	}
	if !fallbackSeenDisabled.Load() {
		t.Fatal("concurrent storm never sampled fallback in disabled state")
	}

	// --- Post-storm ---
	svc.SetRuntimeConfig(enabledStore, catalog, groupPolicy{})
	snaps = svc.ListNodeSnapshots()
	assertProviderSnapshotState(t, snaps, nodeID, "prov-shared", "conc-post-storm",
		1, 1, 0, 0)
	assertProviderSnapshotState(t, snaps, nodeID, "prov-fallback", "conc-post-storm",
		1, 1, 0, 0)

	// --- Dispatch the waiter via holder release ---
	svc.HandleRunLifecycleEvent(&iop.RunEvent{RunId: holderB.Dispatch().RunID, Type: "complete"})

	var waiterRes submitResult
	select {
	case waiterRes = <-resultCh:
	case <-time.After(2 * time.Second):
		t.Fatal("waiter did not dispatch after holder release")
	}
	if waiterRes.err != nil {
		t.Fatalf("waiter submit error: %v", waiterRes.err)
	}
	if waiterRes.run == nil {
		t.Fatal("waiter expected non-nil result")
	}
	defer waiterRes.run.Close()
	wDispatch := waiterRes.run.Dispatch()
	if got := wDispatch.ProviderID; got != "prov-fallback" {
		t.Fatalf("waiter expected dispatch to prov-fallback, got %s", got)
	}

	snaps = svc.ListNodeSnapshots()
	assertProviderSnapshotState(t, snaps, nodeID, "prov-shared", "conc-after-dispatch",
		1, 0, 0, 0)
	assertProviderSnapshotState(t, snaps, nodeID, "prov-fallback", "conc-after-dispatch",
		1, 0, 0, 0)

	svc.HandleRunLifecycleEvent(&iop.RunEvent{RunId: holderA.Dispatch().RunID, Type: "complete"})
	svc.HandleRunLifecycleEvent(&iop.RunEvent{RunId: wDispatch.RunID, Type: "complete"})

	aInFlight, aLong := providerResourceCounts(svc.queue, nodeID, "prov-shared")
	bInFlight, bLong := providerResourceCounts(svc.queue, nodeID, "prov-fallback")
	if aInFlight != 0 || aLong != 0 {
		t.Fatalf("expected prov-shared drained to 0, got inFlight=%d longInFlight=%d", aInFlight, aLong)
	}
	if bInFlight != 0 || bLong != 0 {
		t.Fatalf("expected prov-fallback drained to 0, got inFlight=%d longInFlight=%d", bInFlight, bLong)
	}
	if lc := leaseCount(svc.queue); lc != 0 {
		t.Fatalf("expected leaseCount=0 after all terminals, got %d", lc)
	}
}

// TestProviderSnapshotResolverErrorDoesNotUseStaleCandidate verifies that when
// a queued item's live resolver returns an error or an empty slice, the
// production ListNodeSnapshots surface does not fall back to the enqueue-time
// candidate list. The resolver path is exercised by setting resolveCandidates
// on an actual queued item, then asserting the snapshot reports zero candidate
// pressure (queued=0, longQueued=0) for the provider the item targets.
//
// This regression test exists because a previous loop removed it: with a
// regular expression test list, a zero-match run exits successfully, so the
// missing test was silently passing. Both error and empty cases are covered
// here so the resolver contract (no stale enqueue-time snapshot fallback) is
// enforced.
func TestProviderSnapshotResolverErrorDoesNotUseStaleCandidate(t *testing.T) {
	const nodeID = "node-resolver-stale"
	reg := edgenode.NewRegistry()
	reg.Register(&edgenode.NodeEntry{NodeID: nodeID, Alias: nodeID})

	store := edgenode.NewNodeStore()
	store.Add(&edgenode.NodeRecord{
		ID: nodeID,
		Adapters: config.AdaptersConf{
			VllmInstances: []config.VllmInstanceConf{
				{Name: "vllm-gpu", Enabled: true},
			},
		},
		Providers: []config.NodeProviderConf{
			{
				ID:       "prov-shared",
				Type:     "vllm",
				Category: config.CategoryAPI,
				Adapter:  "vllm-gpu",
				Models:   []string{"served-a"},
				Health:   "available",
				Capacity: 1,
			},
		},
	})

	bus := edgeevents.NewBus()
	svc := New(reg, bus)
	svc.SetNodeStore(store)

	// Pre-fill provider resource state to simulate an in-flight holder already
	// consuming the slot. The queued waiter's pressure must not show up in the
	// snapshot if its resolver is broken.
	svc.queue.mu.Lock()
	key := providerResourceKey{nodeID: nodeID, providerID: "prov-shared"}
	res := svc.queue.resources[key]
	if res == nil {
		res = &providerResourceState{
			nodeID:     nodeID,
			providerID: "prov-shared",
			capacity:   1,
			enabled:    true,
		}
		svc.queue.resources[key] = res
	}
	res.inFlight = 1

	entry := reg.All()[0]
	svc.queue.groups["model-a"] = &modelQueueGroup{
		key: "model-a",
		queue: []*queueItem{
			{
				candidates: []candidateNode{
					{entry: entry, providerID: "prov-shared", capacity: 1},
				},
				waitCh: make(chan admitResult, 1),
			},
		},
	}
	svc.queue.mu.Unlock()

	assertZeroPressure := func(t *testing.T, label string) {
		t.Helper()
		snaps := svc.ListNodeSnapshots()
		ps := findProviderSnapshotOnNode(snaps, nodeID, "prov-shared")
		if ps == nil {
			t.Fatalf("%s: provider snapshot not found in ListNodeSnapshots", label)
		}
		if got := ps.GetQueued(); got != 0 {
			t.Errorf("%s: expected queued=0, got %d", label, got)
		}
		if got := ps.GetLongQueued(); got != 0 {
			t.Errorf("%s: expected longQueued=0, got %d", label, got)
		}
	}

	// Case 1: resolver returns error.
	t.Run("resolverError", func(t *testing.T) {
		svc.queue.mu.Lock()
		wg := svc.queue.groups["model-a"]
		if len(wg.queue) == 1 {
			wg.queue[0].resolveCandidates = func() ([]candidateNode, error) {
				return nil, fmt.Errorf("resolver error")
			}
		}
		svc.queue.mu.Unlock()
		assertZeroPressure(t, "resolverError")
	})

	// Case 2: resolver returns empty slice.
	t.Run("resolverEmpty", func(t *testing.T) {
		svc.queue.mu.Lock()
		wg := svc.queue.groups["model-a"]
		if len(wg.queue) == 1 {
			wg.queue[0].resolveCandidates = func() ([]candidateNode, error) {
				return []candidateNode{}, nil
			}
		}
		svc.queue.mu.Unlock()
		assertZeroPressure(t, "resolverEmpty")
	})

	// Case 3: resolver works normally — pressure should be reported.
	t.Run("resolverOkHasPressure", func(t *testing.T) {
		svc.queue.mu.Lock()
		wg := svc.queue.groups["model-a"]
		if len(wg.queue) == 1 {
			wg.queue[0].resolveCandidates = func() ([]candidateNode, error) {
				return []candidateNode{{entry: entry, providerID: "prov-shared", capacity: 1}}, nil
			}
		}
		svc.queue.mu.Unlock()
		snaps := svc.ListNodeSnapshots()
		ps := findProviderSnapshotOnNode(snaps, nodeID, "prov-shared")
		if ps == nil {
			t.Fatal("resolverOk: provider snapshot not found")
		}
		if got := ps.GetQueued(); got != 1 {
			t.Errorf("resolverOk: expected queued=1, got %d", got)
		}
	})
}

// TestProviderSnapshotRuntimeRefreshIsOldOrNew forces a queue-held writer to
// update the runtime config while a reader holds the queue lock, then asserts
// that the returned snapshot is either the complete old tuple or the complete
// new tuple — never a torn mix such as available/1/0 between an old available
// (capacity=1, queued=1) and a new disabled (capacity=0, queued=0) state. The
// ordering is enforced by having the writer block until the reader holds the
// queue lock, then releasing; the reader must capture a single consistent
// snapshot under the queue critical section established in
// SetRuntimeConfig → ListNodeSnapshots.
func TestProviderSnapshotRuntimeRefreshIsOldOrNew(t *testing.T) {
	parserMap := toki.ParserMap{
		toki.TypeNameOf(&iop.RunRequest{}): func(b []byte) (proto.Message, error) {
			m := &iop.RunRequest{}
			return m, proto.Unmarshal(b, m)
		},
	}
	edgeConn, nodeConn := net.Pipe()
	defer edgeConn.Close()
	defer nodeConn.Close()
	edgeClient := toki.NewTcpClient(edgeConn, 0, 0, parserMap)
	_ = toki.NewTcpClient(nodeConn, 0, 0, parserMap)

	const nodeID = "node-old-or-new"
	reg := edgenode.NewRegistry()
	reg.Register(&edgenode.NodeEntry{NodeID: nodeID, Client: edgeClient})
	bus := edgeevents.NewBus()
	svc := New(reg, bus)

	catalog := []config.ModelCatalogEntry{
		{
			ID:        "model-x",
			Providers: map[string]string{"prov-x": "served-x"},
		},
	}

	enabledFlag := true
	disabledFlag := false
	enabledStore := edgenode.NewNodeStore()
	enabledStore.Add(&edgenode.NodeRecord{
		ID: nodeID,
		Adapters: config.AdaptersConf{
			VllmInstances: []config.VllmInstanceConf{
				{Name: "vllm-gpu", Enabled: true},
			},
		},
		Providers: []config.NodeProviderConf{
			{
				ID: "prov-x", Type: "vllm", Category: config.CategoryAPI,
				Adapter:  "vllm-gpu",
				Models:   []string{"served-x"},
				Health:   "available",
				Capacity: 1,
				Enabled:  &enabledFlag,
			},
		},
	})

	disabledStore := edgenode.NewNodeStore()
	disabledStore.Add(&edgenode.NodeRecord{
		ID: nodeID,
		Providers: []config.NodeProviderConf{
			{
				ID: "prov-x", Type: "vllm", Category: config.CategoryAPI,
				Health: "available", Capacity: 1,
				Enabled: &disabledFlag,
			},
		},
	})

	svc.SetRuntimeConfig(enabledStore, catalog, groupPolicy{})

	// Submit a holder so the provider has inflight+queued pressure under the
	// enabled config. This makes the old tuple (available/capacity=1/inflight>0)
	// distinguishable from the new tuple (disabled/capacity=0/inflight=0).
	holder, err := svc.SubmitRun(t.Context(), SubmitRunRequest{
		ModelGroupKey: "model-x", ProviderPool: true, Background: true,
	})
	if err != nil || holder == nil {
		t.Fatalf("holder submit: %v", err)
	}
	defer holder.Close()

	// Force the queue to hold the lease so inflight > 0 is observable.
	waitForInflight(t, svc.queue, nodeID, "prov-x", 1)

	// Submit a waiter so the model-x group has one queued item targeting
	// prov-x. This creates live candidate pressure (queued=1) that, combined
	// with the holder's in-flight lease (inFlight=1), makes the old tuple
	// (available/capacity=1/inFlight=1/queued=1) distinguishable from the new
	// disabled tuple (disabled/0/0/0/0/0). Without the waiter the reader would
	// always see queued=0 and the regression would be silent.
	type submitResult struct {
		run RunResult
		err error
	}
	waiterResult := make(chan submitResult, 1)
	go func() {
		run, err := svc.SubmitRun(t.Context(), SubmitRunRequest{
			ModelGroupKey: "model-x", ProviderPool: true, Background: true,
		})
		waiterResult <- submitResult{run: run, err: err}
	}()
	waitForQueueLen(t, svc.queue, "model-x", 1)

	// --- Public reader barrier: enforce queue→service lock ordering ---
	// Hold the service write lock so the reader goroutine (calling production
	// ListNodeSnapshots) blocks on the service read lock inside the queue-held
	// critical section. This proves the reader actually acquires and holds the
	// queue lock, and the writer must wait for it.
	svc.mu.Lock()
	serviceLocked := true
	defer func() {
		if serviceLocked {
			svc.mu.Unlock()
		}
	}()

	readerResult := make(chan []NodeSnapshot, 1)
	go func() {
		readerResult <- svc.ListNodeSnapshots()
	}()
	if err := waitForQueueLockHeld(svc.queue, time.Second); err != nil {
		svc.mu.Unlock()
		serviceLocked = false
		t.Fatal(err)
	}

	// Start writer while reader still holds queue lock and waits on service lock.
	writerDone := make(chan struct{})
	go func() {
		svc.SetRuntimeConfig(disabledStore, catalog, groupPolicy{})
		close(writerDone)
	}()
	svc.mu.Unlock()
	serviceLocked = false

	// Bounded waits for reader, writer completions.
	var oldSnaps []NodeSnapshot
	select {
	case oldSnaps = <-readerResult:
	case <-time.After(time.Second):
		t.Fatal("public snapshot reader did not complete")
	}
	select {
	case <-writerDone:
	case <-time.After(time.Second):
		t.Fatal("runtime config writer did not complete")
	}

	expectedOld := snapshotTuple{
		status: "available", capacity: 1, inFlight: 1, queued: 1,
		longInFlight: 0, longQueued: 0,
	}
	assertExactSnapshotTuple(t, oldSnaps, nodeID, "prov-x", expectedOld)

	// Public surface now returns the new tuple (disabled/capacity=0).
	newSnaps := svc.ListNodeSnapshots()
	expectedNew := snapshotTuple{
		status: "disabled", capacity: 0, inFlight: 0, queued: 0,
		longInFlight: 0, longQueued: 0,
	}
	assertExactSnapshotTuple(t, newSnaps, nodeID, "prov-x", expectedNew)

	svc.SetRuntimeConfig(enabledStore, catalog, groupPolicy{})
	// Drain holder
	svc.HandleRunLifecycleEvent(&iop.RunEvent{RunId: holder.Dispatch().RunID, Type: "complete"})
	// Drain waiter (holder release unblocks it)
	var waiterRes submitResult
	select {
	case waiterRes = <-waiterResult:
	case <-time.After(2 * time.Second):
		t.Fatal("waiter did not dispatch after holder release")
	}
	if waiterRes.err != nil || waiterRes.run == nil {
		t.Fatalf("waiter result: run=%v err=%v", waiterRes.run, waiterRes.err)
	}
	// Dispatch and complete the waiter to fully drain the provider.
	wDispatch := waiterRes.run.Dispatch()
	svc.HandleRunLifecycleEvent(&iop.RunEvent{RunId: wDispatch.RunID, Type: "complete"})

	// Terminal drain verification: provider resource counts and lease must be zero.
	aInFlight, aLong := providerResourceCounts(svc.queue, nodeID, "prov-x")
	if aInFlight != 0 || aLong != 0 {
		t.Fatalf("expected prov-x drained to 0, got inFlight=%d longInFlight=%d", aInFlight, aLong)
	}
	if lc := leaseCount(svc.queue); lc != 0 {
		t.Fatalf("expected leaseCount=0 after all terminals, got %d", lc)
	}
}

// assertExactSnapshotTuple asserts that the production ListNodeSnapshots
// surface returns an exact tuple for (nodeID, providerID). Used by the
// tuple regression test to confirm the reader captures a single consistent
// snapshot under the queue lock via the public surface.
func assertExactSnapshotTuple(t *testing.T, snaps []NodeSnapshot, nodeID, providerID string, want snapshotTuple) {
	t.Helper()
	ps := findProviderSnapshotOnNode(snaps, nodeID, providerID)
	if ps == nil {
		t.Fatalf("provider %s snapshot not found on %s in ListNodeSnapshots", providerID, nodeID)
	}
	got := snapshotTuple{
		status: ps.GetStatus(), capacity: ps.GetCapacity(),
		inFlight: ps.GetInFlight(), queued: ps.GetQueued(),
		longInFlight: ps.GetLongInFlight(), longQueued: ps.GetLongQueued(),
	}
	if err := validateSnapshotTuple(got, want); err != nil {
		t.Fatalf("tuple mismatch for %s on %s: %v", providerID, nodeID, err)
	}
}

// waitForInflight blocks until the queue for (nodeID, providerID) observes at
// least minInflight in-flight leases. Returns immediately if already satisfied.
func waitForInflight(t *testing.T, q *modelQueueManager, nodeID, providerID string, minInflight int) {
	t.Helper()
	for i := 0; i < 100; i++ {
		inFlight, _ := providerResourceCounts(q, nodeID, providerID)
		if inFlight >= minInflight {
			return
		}
		runtime.Gosched()
		time.Sleep(time.Millisecond)
	}
}

// waitForQueueLockHeld proves that another goroutine holds q.mu by attempting
// TryLock from the caller's goroutine. It returns nil if TryLock fails within
// the deadline (proving the lock is held exclusively) or a formatted error if
// TryLock succeeds before the deadline (lock was not held).
func waitForQueueLockHeld(q *modelQueueManager, deadline time.Duration) error {
	deadlineTimer := time.NewTimer(deadline)
	defer deadlineTimer.Stop()
	ticker := time.NewTicker(time.Millisecond)
	defer ticker.Stop()

	for {
		select {
		case <-deadlineTimer.C:
			return fmt.Errorf("queue lock not held within %v (TryLock succeeded: lock was not held exclusively)", deadline)
		case <-ticker.C:
			if !q.mu.TryLock() {
				return nil
			}
			q.mu.Unlock()
			runtime.Gosched()
		}
	}
}

// TestListNodeSnapshotsIncludesConfiguredOfflineNodes verifies that configured
// nodes that are not currently connected still appear in the snapshot with
// Connected=false and preserve their configured identity and provider catalog.
// It also verifies that reconnecting with the same NodeID recovers Connected=true
// while keeping the same identity and stable position, and that the snapshot
// order is deterministic across no-queue and queue-backed paths.
func TestListNodeSnapshotsIncludesConfiguredOfflineNodes(t *testing.T) {
	t.Run("noQueue", func(t *testing.T) {
		t.Parallel()
		store := edgenode.NewNodeStore()
		// Add records in reverse index order to prove All() sorts by Index.
		store.Add(&edgenode.NodeRecord{
			ID:       "node-c",
			Alias:    "gamma",
			Index:    2,
			Adapters: config.AdaptersConf{Ollama: config.OllamaConf{Enabled: true, BaseURL: "http://127.0.0.1:11434"}},
		})
		store.Add(&edgenode.NodeRecord{
			ID:       "node-a",
			Alias:    "alpha",
			Index:    0,
			Adapters: config.AdaptersConf{Ollama: config.OllamaConf{Enabled: true, BaseURL: "http://127.0.0.1:11434"}},
		})
		store.Add(&edgenode.NodeRecord{
			ID:       "node-b",
			Alias:    "beta",
			Index:    1,
			Adapters: config.AdaptersConf{Ollama: config.OllamaConf{Enabled: true, BaseURL: "http://127.0.0.1:11434"}},
			Providers: []config.NodeProviderConf{
				{ID: "prov-b", Type: "ollama", Category: config.CategoryLocalInference, Adapter: "ollama", Models: []string{"m"}, Capacity: 2},
			},
		})

		reg := edgenode.NewRegistry()
		// Only node-a is connected.
		reg.Register(&edgenode.NodeEntry{NodeID: "node-a", Alias: "alpha"})

		svc := New(reg, nil)
		if svc.queue != nil {
			t.Fatal("expected no-queue service")
		}
		svc.SetNodeStore(store)

		snaps := svc.ListNodeSnapshots()
		if len(snaps) != 3 {
			t.Fatalf("expected 3 node snapshots, got %d", len(snaps))
		}

		// Stable order: index 0, 1, 2.
		expectedIDs := []string{"node-a", "node-b", "node-c"}
		expectedLabels := []string{"node0", "node1", "node2"}
		expectedConnected := []bool{true, false, false}
		for i, s := range snaps {
			if s.NodeID != expectedIDs[i] {
				t.Errorf("snap[%d].NodeID = %q, want %q", i, s.NodeID, expectedIDs[i])
			}
			if s.Label != expectedLabels[i] {
				t.Errorf("snap[%d].Label = %q, want %q", i, s.Label, expectedLabels[i])
			}
			if s.Connected != expectedConnected[i] {
				t.Errorf("snap[%d].Connected = %v, want %v", i, s.Connected, expectedConnected[i])
			}
		}

		// The no-queue path preserves the configured provider catalog. Legacy
		// adapter snapshot parity is outside this catalog regression.
		for _, s := range snaps {
			if s.NodeID == "node-b" {
				if len(s.ProviderSnapshots) != 1 {
					t.Errorf("node-b: expected 1 catalog snapshot (prov-b), got %d", len(s.ProviderSnapshots))
				}
				if len(s.ProviderSnapshots) > 0 {
					provider := s.ProviderSnapshots[0]
					// Offline node: catalog identity preserved (id/adapter/type/category/models),
					// but effective status/health/capacity drop to unavailable/offline/0.
					if provider.Id != "prov-b" || provider.Adapter != "ollama" || provider.Status != "unavailable" || provider.Health != "offline" || provider.Capacity != 0 || provider.InFlight != 0 || provider.Queued != 0 || len(provider.ServedModels) != 1 || provider.ServedModels[0] != "m" {
						t.Errorf("node-b: unexpected configured provider snapshot (expected unavailable/offline/zero tuple with catalog identity): %+v", provider)
					}
				}
			}
		}
	})

	t.Run("withQueue", func(t *testing.T) {
		t.Parallel()
		store := edgenode.NewNodeStore()
		store.Add(&edgenode.NodeRecord{ID: "node-c", Alias: "gamma", Index: 2, Adapters: config.AdaptersConf{Ollama: config.OllamaConf{Enabled: true, BaseURL: "http://127.0.0.1:11434"}}})
		store.Add(&edgenode.NodeRecord{ID: "node-a", Alias: "alpha", Index: 0, Adapters: config.AdaptersConf{Ollama: config.OllamaConf{Enabled: true, BaseURL: "http://127.0.0.1:11434"}}})
		store.Add(&edgenode.NodeRecord{
			ID:       "node-b",
			Alias:    "beta",
			Index:    1,
			Adapters: config.AdaptersConf{Ollama: config.OllamaConf{Enabled: true, BaseURL: "http://127.0.0.1:11434"}},
			Providers: []config.NodeProviderConf{
				{ID: "prov-b", Type: "ollama", Category: config.CategoryLocalInference, Adapter: "ollama", Models: []string{"m"}, Capacity: 2},
			},
		})

		reg := edgenode.NewRegistry()
		reg.Register(&edgenode.NodeEntry{NodeID: "node-a", Alias: "alpha"})

		bus := edgeevents.NewBus()
		svc := New(reg, bus)
		if svc.queue == nil {
			t.Fatal("expected queue-backed service")
		}
		svc.SetNodeStore(store)

		snaps := svc.ListNodeSnapshots()
		if len(snaps) != 3 {
			t.Fatalf("expected 3 node snapshots, got %d", len(snaps))
		}

		expectedIDs := []string{"node-a", "node-b", "node-c"}
		for i, s := range snaps {
			if s.NodeID != expectedIDs[i] {
				t.Errorf("snap[%d].NodeID = %q, want %q", i, s.NodeID, expectedIDs[i])
			}
			if s.Connected != (s.NodeID == "node-a") {
				t.Errorf("snap[%d] (%s) Connected = %v, want %v", i, s.NodeID, s.Connected, s.NodeID == "node-a")
			}
			if s.NodeID == "node-b" {
				if len(s.ProviderSnapshots) != 1 {
					t.Errorf("node-b: expected 1 queue-backed catalog snapshot, got %d", len(s.ProviderSnapshots))
				} else if provider := s.ProviderSnapshots[0]; provider.Id != "prov-b" || provider.Adapter != "ollama" || provider.Status != "unavailable" || provider.Health != "offline" || provider.Capacity != 0 || provider.InFlight != 0 || provider.Queued != 0 || provider.LongInFlight != 0 || provider.LongQueued != 0 {
					t.Errorf("node-b: unexpected queue-backed provider snapshot (expected unavailable/offline/zero tuple): %+v", provider)
				}
			}
		}
	})

	t.Run("reconnectPreservesIdentity", func(t *testing.T) {
		t.Parallel()
		store := edgenode.NewNodeStore()
		store.Add(&edgenode.NodeRecord{ID: "node-a", Alias: "alpha", Index: 0, Adapters: config.AdaptersConf{Ollama: config.OllamaConf{Enabled: true, BaseURL: "http://127.0.0.1:11434"}}})
		store.Add(&edgenode.NodeRecord{ID: "node-b", Alias: "beta", Index: 1, Adapters: config.AdaptersConf{Ollama: config.OllamaConf{Enabled: true, BaseURL: "http://127.0.0.1:11434"}}})

		// Initial: both configured nodes are connected, with node-b on its first
		// accepted registry generation.
		reg := edgenode.NewRegistry()
		reg.Register(&edgenode.NodeEntry{NodeID: "node-a", Alias: "alpha"})
		firstNodeB := &edgenode.NodeEntry{NodeID: "node-b", Alias: "beta"}
		reg.Register(firstNodeB)
		if firstNodeB.ConnectionGeneration == 0 {
			t.Fatal("first node-b registration did not receive a generation")
		}

		bus := edgeevents.NewBus()
		svc := New(reg, bus)
		svc.SetNodeStore(store)

		assertSnapshot := func(stage string, wantNodeBConnected bool) {
			t.Helper()
			snaps := svc.ListNodeSnapshots()
			if len(snaps) != 2 {
				t.Fatalf("%s: expected 2 snapshots, got %d", stage, len(snaps))
			}
			if snaps[0].NodeID != "node-a" || snaps[1].NodeID != "node-b" {
				t.Fatalf("%s: stable identity/order changed: got [%s %s]", stage, snaps[0].NodeID, snaps[1].NodeID)
			}
			if snaps[1].Alias != "beta" || snaps[1].Label != "node1" {
				t.Errorf("%s: node-b identity changed: alias=%q label=%q", stage, snaps[1].Alias, snaps[1].Label)
			}
			if snaps[1].Connected != wantNodeBConnected {
				t.Errorf("%s: node-b Connected=%v, want %v", stage, snaps[1].Connected, wantNodeBConnected)
			}
		}
		assertSnapshot("connected", true)

		// Disconnect the current owner. The configured identity remains in the
		// same position but connectivity becomes false.
		reg.Unregister("node-b")
		if _, ok := reg.CurrentGeneration("node-b"); ok {
			t.Fatal("node-b generation remained live after unregister")
		}
		assertSnapshot("disconnected", false)

		// Reconnect the same Node ID through a new registry entry. The registry
		// must mint a later generation while the configured identity/order and
		// snapshot position stay stable.
		secondNodeB := &edgenode.NodeEntry{NodeID: "node-b", Alias: "beta"}
		reg.Register(secondNodeB)
		if secondNodeB.ConnectionGeneration <= firstNodeB.ConnectionGeneration {
			t.Fatalf("reconnect generation=%d, want > first generation=%d", secondNodeB.ConnectionGeneration, firstNodeB.ConnectionGeneration)
		}
		assertSnapshot("reconnected", true)
	})
}

// TestProviderSnapshotOfflineVsDisabled verifies that connectivity flipping
// only affects enabled providers: disabled providers keep status=disabled and
// health=disabled regardless of connectivity, while enabled disconnected
// providers show status=unavailable and health=offline. Catalog identity (id,
// adapter, type, category, models) is preserved in both cases.
func TestProviderSnapshotOfflineVsDisabled(t *testing.T) {
	disabled := false
	rec := &edgenode.NodeRecord{
		ID: "node-off-disabled",
		Providers: []config.NodeProviderConf{
			{ID: "prov-enabled", Type: "vllm", Category: config.CategoryAPI,
				Adapter: "vllm-gpu", Models: []string{"served-a"},
				Health: "available", Capacity: 3},
			{ID: "prov-disabled", Type: "vllm", Category: config.CategoryAPI,
				Adapter: "vllm-gpu", Models: []string{"served-b"},
				Health: "available", Capacity: 3, Enabled: &disabled},
		},
		Adapters: config.AdaptersConf{
			VllmInstances: []config.VllmInstanceConf{{Name: "vllm-gpu", Enabled: true}},
		},
	}

	// wrapForFind converts []*iop.ProviderSnapshot into a single-element
	// []NodeSnapshot so we can reuse findProviderSnapshotOnNode.
	wrapForFind := func(ps []*iop.ProviderSnapshot) []NodeSnapshot {
		return []NodeSnapshot{{NodeID: "node-off-disabled", ProviderSnapshots: ps}}
	}

	assertDisabled := func(stage string, snaps []NodeSnapshot) {
		t.Helper()
		p := findProviderSnapshotOnNode(snaps, "node-off-disabled", "prov-disabled")
		if p == nil {
			t.Fatalf("%s: prov-disabled not found", stage)
		}
		if p.GetStatus() != "disabled" {
			t.Errorf("%s prov-disabled: status=%q want disabled", stage, p.GetStatus())
		}
		if p.GetHealth() != "disabled" {
			t.Errorf("%s prov-disabled: health=%q want disabled", stage, p.GetHealth())
		}
		if p.GetCapacity() != 0 || p.GetInFlight() != 0 || p.GetQueued() != 0 || p.GetLongInFlight() != 0 || p.GetLongQueued() != 0 {
			t.Errorf("%s prov-disabled: counters must be zero", stage)
		}
	}
	assertEnabled := func(stage string, snaps []NodeSnapshot, wantCap int32, wantStatus, wantHealth string) {
		t.Helper()
		p := findProviderSnapshotOnNode(snaps, "node-off-disabled", "prov-enabled")
		if p == nil {
			t.Fatalf("%s: prov-enabled not found", stage)
		}
		if p.GetStatus() != wantStatus {
			t.Errorf("%s prov-enabled: status=%q want %q", stage, p.GetStatus(), wantStatus)
		}
		if p.GetHealth() != wantHealth {
			t.Errorf("%s prov-enabled: health=%q want %q", stage, p.GetHealth(), wantHealth)
		}
		if p.GetCapacity() != wantCap {
			t.Errorf("%s prov-enabled: capacity=%d want %d", stage, p.GetCapacity(), wantCap)
		}
		if p.GetInFlight() != 0 || p.GetQueued() != 0 || p.GetLongInFlight() != 0 || p.GetLongQueued() != 0 {
			t.Errorf("%s prov-enabled: effective counters must be zero", stage)
		}
	}

	// --- Disabled: connected ---
	snaps := staticProviderCatalogSnapshots(rec, true)
	assertDisabled("connected", wrapForFind(snaps))
	assertEnabled("connected", wrapForFind(snaps), 3, "available", "available")

	// --- Disabled: disconnected (must still be disabled, not unavailable) ---
	snaps = staticProviderCatalogSnapshots(rec, false)
	assertDisabled("disconnected", wrapForFind(snaps))
	assertEnabled("disconnected", wrapForFind(snaps), 0, "unavailable", "offline")
}

// TestProviderSnapshotReconnectRestoresCapacityAndAdmission verifies the full
// generation-aware lease lifecycle across disconnect→offline→reconnect. The
// first connection acquires a real long-context lease, authoritative disconnect
// settlement releases it and orphans that generation, and a later connection
// restores configured capacity while exposing only its own newly admitted lease.
func TestProviderSnapshotReconnectRestoresCapacityAndAdmission(t *testing.T) {
	const (
		nodeID      = "node-reconnect-cycle"
		providerID  = "prov-rc"
		modelGroup  = "model-rc"
		servedModel = "served-x"
	)

	rec := &edgenode.NodeRecord{
		ID: nodeID,
		Providers: []config.NodeProviderConf{
			{
				ID:                  providerID,
				Type:                "vllm",
				Category:            config.CategoryAPI,
				Adapter:             "vllm-gpu",
				Models:              []string{servedModel},
				Health:              "available",
				Capacity:            5,
				LongContextCapacity: 2,
			},
		},
		Adapters: config.AdaptersConf{
			VllmInstances: []config.VllmInstanceConf{{Name: "vllm-gpu", Enabled: true}},
		},
	}

	reg := edgenode.NewRegistry()
	firstEntry := &edgenode.NodeEntry{NodeID: nodeID, Alias: "rc"}
	reg.Register(firstEntry)
	if firstEntry.ConnectionGeneration == 0 {
		t.Fatal("first connection generation must be non-zero")
	}
	store := edgenode.NewNodeStore()
	store.Add(rec)

	bus := edgeevents.NewBus()
	svc := New(reg, bus)
	policy := NewGroupPolicy(16, time.Second)
	svc.SetRuntimeConfig(store, []config.ModelCatalogEntry{
		{ID: modelGroup, Providers: map[string]string{providerID: servedModel}},
	}, policy)

	req := SubmitRunRequest{
		ModelGroupKey: modelGroup,
		ContextClass:  contextClassLong,
		ProviderPool:  true,
	}
	admitForGeneration := func(stage string, generation uint64) *candidateNode {
		t.Helper()
		candidates, _, err := svc.resolveQueueCandidates(req)
		if err != nil {
			t.Fatalf("%s: resolve provider-pool candidates: %v", stage, err)
		}
		selected, err := svc.queue.admit(
			t.Context(), modelGroup, "", "", candidates, policy,
			svc.resolveQueueCandidatesClosure(req), true, true,
		)
		if err != nil {
			t.Fatalf("%s: admit long-context lease: %v", stage, err)
		}
		if selected.providerID != providerID {
			t.Fatalf("%s: admitted provider=%q, want %q", stage, selected.providerID, providerID)
		}
		if selected.generation != generation {
			t.Fatalf("%s: admitted generation=%d, want %d", stage, selected.generation, generation)
		}
		if selected.leaseID == 0 {
			t.Fatalf("%s: admitted lease id must be non-zero", stage)
		}
		svc.queue.trackLease(selected.leaseID, "run-"+stage)
		return selected
	}

	assertSnapshot := func(stage, wantStatus, wantHealth string, wantCapacity, wantInFlight, wantLongCapacity, wantLongInFlight int32) {
		t.Helper()
		ps := findProviderSnapshotOnNode(svc.ListNodeSnapshots(), nodeID, providerID)
		if ps == nil {
			t.Fatalf("%s: %s snapshot not found", stage, providerID)
		}
		if ps.GetId() != providerID || ps.GetAdapter() != "vllm-gpu" {
			t.Errorf("%s: catalog identity=(%q,%q), want (%q,%q)", stage, ps.GetId(), ps.GetAdapter(), providerID, "vllm-gpu")
		}
		if len(ps.GetServedModels()) != 1 || ps.GetServedModels()[0] != servedModel {
			t.Errorf("%s: served models=%v, want [%s]", stage, ps.GetServedModels(), servedModel)
		}
		if ps.GetStatus() != wantStatus || ps.GetHealth() != wantHealth {
			t.Errorf("%s: status/health=(%q,%q), want (%q,%q)", stage, ps.GetStatus(), ps.GetHealth(), wantStatus, wantHealth)
		}
		if ps.GetCapacity() != wantCapacity || ps.GetInFlight() != wantInFlight {
			t.Errorf("%s: capacity/in-flight=(%d,%d), want (%d,%d)", stage, ps.GetCapacity(), ps.GetInFlight(), wantCapacity, wantInFlight)
		}
		if ps.GetLongContextCapacity() != wantLongCapacity || ps.GetLongInFlight() != wantLongInFlight {
			t.Errorf("%s: long capacity/in-flight=(%d,%d), want (%d,%d)", stage, ps.GetLongContextCapacity(), ps.GetLongInFlight(), wantLongCapacity, wantLongInFlight)
		}
		if ps.GetQueued() != 0 || ps.GetLongQueued() != 0 {
			t.Errorf("%s: queued/long-queued=(%d,%d), want (0,0)", stage, ps.GetQueued(), ps.GetLongQueued())
		}
		t.Logf("%s: generation status=%s health=%s capacity=%d in_flight=%d long_capacity=%d long_in_flight=%d",
			stage, ps.GetStatus(), ps.GetHealth(), ps.GetCapacity(), ps.GetInFlight(), ps.GetLongContextCapacity(), ps.GetLongInFlight())
	}

	// Stage 1: the first accepted generation owns one real tracked long lease.
	firstLease := admitForGeneration("first-generation", firstEntry.ConnectionGeneration)
	assertSnapshot("first-generation-admitted", "available", "available", 5, 1, 2, 1)

	// Stage 2: remove the current registry owner, then settle that exact owner
	// generation through the same authoritative service hook used by transport.
	firstGeneration := firstEntry.ConnectionGeneration
	reg.Unregister(nodeID)
	if _, ok := reg.CurrentGeneration(nodeID); ok {
		t.Fatal("disconnected node retained a current registry generation")
	}
	svc.HandleNodeDisconnect(nodeID, firstGeneration, "test authoritative disconnect")

	svc.queue.mu.Lock()
	_, firstLeaseStillLive := svc.queue.leases[firstLease.leaseID]
	resource := svc.queue.resources[providerResourceKey{nodeID: nodeID, providerID: providerID}]
	resourceOrphan := resource != nil && resource.orphan
	resourceGeneration := uint64(0)
	resourceInFlight, resourceLongInFlight := 0, 0
	if resource != nil {
		resourceGeneration = resource.generation
		resourceInFlight, resourceLongInFlight = resource.snapshotCounts()
	}
	svc.queue.mu.Unlock()
	if firstLeaseStillLive {
		t.Fatal("authoritative disconnect did not settle the first-generation lease")
	}
	if resource == nil || !resourceOrphan || resourceGeneration != firstGeneration {
		t.Fatalf("settled resource=(present=%t orphan=%t generation=%d), want (true,true,%d)", resource != nil, resourceOrphan, resourceGeneration, firstGeneration)
	}
	if resourceInFlight != 0 || resourceLongInFlight != 0 {
		t.Fatalf("settled resource counters=(%d,%d), want (0,0)", resourceInFlight, resourceLongInFlight)
	}
	assertSnapshot("offline-after-settlement", "unavailable", "offline", 0, 0, 0, 0)

	// Stage 3: reconnect the same identity. Configured capacity is visible, but
	// the old generation contributes no counter before a new admission occurs.
	secondEntry := &edgenode.NodeEntry{NodeID: nodeID, Alias: "rc"}
	reg.Register(secondEntry)
	if secondEntry.ConnectionGeneration <= firstGeneration {
		t.Fatalf("reconnect generation=%d, want > disconnected generation=%d", secondEntry.ConnectionGeneration, firstGeneration)
	}
	assertSnapshot("reconnected-before-admission", "available", "available", 5, 0, 2, 0)

	// Stage 4: a real lease on the higher generation is admitted and is the only
	// counter exposed. Releasing that lease returns both counters to zero.
	secondLease := admitForGeneration("second-generation", secondEntry.ConnectionGeneration)
	assertSnapshot("reconnected-after-admission", "available", "available", 5, 1, 2, 1)
	svc.queue.releaseLease(secondLease.leaseID, "test release")
	assertSnapshot("reconnected-after-release", "available", "available", 5, 0, 2, 0)
}

// TestReconnectConnectHookActivatesResourceGenerationInSnapshot verifies the
// auxiliary S15 convergence: the accepted-connect hook (HandleNodeConnect) alone,
// with no new admission, clears the disconnect orphan marker, advances the
// provider resource generation to the reconnect's, and returns the status
// snapshot to available with the configured capacity and zero in-flight counters.
func TestReconnectConnectHookActivatesResourceGenerationInSnapshot(t *testing.T) {
	const (
		nodeID      = "node-hook-activate"
		providerID  = "prov-hook"
		modelGroup  = "model-hook"
		servedModel = "served-hook"
	)

	rec := &edgenode.NodeRecord{
		ID: nodeID,
		Providers: []config.NodeProviderConf{{
			ID:                  providerID,
			Type:                "vllm",
			Category:            config.CategoryAPI,
			Adapter:             "vllm-gpu",
			Models:              []string{servedModel},
			Health:              "available",
			Capacity:            4,
			LongContextCapacity: 2,
		}},
		Adapters: config.AdaptersConf{
			VllmInstances: []config.VllmInstanceConf{{Name: "vllm-gpu", Enabled: true}},
		},
	}

	reg := edgenode.NewRegistry()
	firstEntry := &edgenode.NodeEntry{NodeID: nodeID, Alias: "hook"}
	reg.Register(firstEntry)
	genOne := firstEntry.ConnectionGeneration
	if genOne == 0 {
		t.Fatal("first connection generation must be non-zero")
	}
	store := edgenode.NewNodeStore()
	store.Add(rec)

	svc := New(reg, edgeevents.NewBus())
	policy := NewGroupPolicy(16, time.Second)
	svc.SetRuntimeConfig(store, []config.ModelCatalogEntry{
		{ID: modelGroup, Providers: map[string]string{providerID: servedModel}},
	}, policy)

	// Admit a real lease on the first generation so the resource generation is
	// genOne (not zero) before the disconnect.
	req := SubmitRunRequest{ModelGroupKey: modelGroup, ProviderPool: true}
	cands, _, err := svc.resolveQueueCandidates(req)
	if err != nil {
		t.Fatalf("resolve provider-pool candidates: %v", err)
	}
	lease, err := svc.queue.admit(
		t.Context(), modelGroup, "", "", cands, policy,
		svc.resolveQueueCandidatesClosure(req), false, true,
	)
	if err != nil || lease == nil {
		t.Fatalf("admit generation-one lease: %v", err)
	}
	if lease.generation != genOne {
		t.Fatalf("admitted lease generation=%d, want %d", lease.generation, genOne)
	}
	svc.queue.trackLease(lease.leaseID, "run-hook")

	if present, orphan, gen, inFlight := resourceStateForTest(svc.queue, nodeID, providerID); !present || orphan || gen != genOne || inFlight != 1 {
		t.Fatalf("generation-one resource=(present=%t orphan=%t generation=%d in-flight=%d), want (true,false,%d,1)", present, orphan, gen, inFlight, genOne)
	}

	// Disconnect the current owner: the lease settles and the resource is orphaned
	// at generation one.
	reg.Unregister(nodeID)
	svc.HandleNodeDisconnect(nodeID, genOne, "disconnected")
	if present, orphan, gen, inFlight := resourceStateForTest(svc.queue, nodeID, providerID); !present || !orphan || gen != genOne || inFlight != 0 {
		t.Fatalf("offline resource=(present=%t orphan=%t generation=%d in-flight=%d), want (true,true,%d,0)", present, orphan, gen, inFlight, genOne)
	}
	if ps := findProviderSnapshotOnNode(svc.ListNodeSnapshots(), nodeID, providerID); ps == nil || ps.GetStatus() != "unavailable" || ps.GetHealth() != "offline" {
		t.Fatalf("offline snapshot = %+v, want status=unavailable health=offline", ps)
	}

	// Reconnect and drive the accepted-connect hook alone — no new admission,
	// refresh, or lease release.
	secondEntry := &edgenode.NodeEntry{NodeID: nodeID, Alias: "hook"}
	reg.Register(secondEntry)
	genTwo := secondEntry.ConnectionGeneration
	if genTwo <= genOne {
		t.Fatalf("reconnect generation=%d, want > disconnected generation=%d", genTwo, genOne)
	}
	svc.HandleNodeConnect(nodeID, genTwo)

	present, orphan, gen, inFlight := resourceStateForTest(svc.queue, nodeID, providerID)
	if !present || orphan || gen != genTwo || inFlight != 0 {
		t.Fatalf("activated resource=(present=%t orphan=%t generation=%d in-flight=%d), want (true,false,%d,0)", present, orphan, gen, inFlight, genTwo)
	}
	ps := findProviderSnapshotOnNode(svc.ListNodeSnapshots(), nodeID, providerID)
	if ps == nil {
		t.Fatal("provider snapshot missing after activation")
	}
	if ps.GetStatus() != "available" || ps.GetHealth() != "available" {
		t.Errorf("activated snapshot status/health=(%q,%q), want (available,available)", ps.GetStatus(), ps.GetHealth())
	}
	if ps.GetCapacity() != 4 || ps.GetInFlight() != 0 {
		t.Errorf("activated snapshot capacity/in-flight=(%d,%d), want (4,0)", ps.GetCapacity(), ps.GetInFlight())
	}
	if ps.GetLongContextCapacity() != 2 || ps.GetLongInFlight() != 0 {
		t.Errorf("activated snapshot long capacity/in-flight=(%d,%d), want (2,0)", ps.GetLongContextCapacity(), ps.GetLongInFlight())
	}
}
