package daemon

import (
	"context"
	"encoding/json"
	"errors"
	"testing"
	"time"

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/internal/runtimecontrol"
	"github.com/tidbcloud/AgentTeam/internal/store/agent"
)

type fakeElasticRequestLinkSender struct {
	messages []any
	closed   bool
}

func (sender *fakeElasticRequestLinkSender) SendJSON(message any) error {
	sender.messages = append(sender.messages, message)
	return nil
}

func (sender *fakeElasticRequestLinkSender) Close() error {
	sender.closed = true
	return nil
}

func TestElasticRequestLinkGrantTokenAndAssignmentLifecycle(t *testing.T) {
	now := time.Date(2026, 6, 30, 4, 0, 0, 123456789, time.UTC)
	manager := newTestElasticRequestLinkManager(t, &now, ElasticRequestLinkManagerConfig{MaxPerMachine: 3})
	client := newElasticReadyClient()
	descriptor := defaultWorkspaceListEndpoint(t)

	open, grant, err := manager.CreateLinkGrant(client, descriptor)
	require.NoError(t, err)
	require.Equal(t, elasticRequestLinkOpenType, open.Type)
	require.Equal(t, client.workspaceID, grant.WorkspaceID)
	require.Equal(t, client.machineID, grant.MachineID)
	require.Equal(t, client.currentSessionGeneration(), grant.SessionGeneration)
	require.Equal(t, open.LinkID, grant.LinkID)
	require.Equal(t, "node-a", grant.NodeHint)
	require.Equal(t, defaultElasticRequestLinkProtocolVersion, grant.ProtocolVersion)
	require.Equal(t, defaultEndpointRegistryVersion, grant.EndpointRegistryVersion)
	require.Equal(t, ElasticLinkPurposeDemand, grant.Purpose)
	require.Empty(t, grant.ProfileName)
	require.Equal(t, &RemoteEndpointScope{EndpointID: remoteEndpointWorkspaceList, Version: 1}, grant.PrimaryEndpoint)
	require.Equal(t, []RemoteEndpointScope{{EndpointID: remoteEndpointWorkspaceList, Version: 1}}, grant.AllowedEndpoints)
	require.Equal(t, now.Add(defaultElasticRequestLinkConnectTimeout), grant.ExpiresAt)
	require.Equal(t, ElasticLinkPurposeDemand, open.Purpose)
	require.Equal(t, grant.PrimaryEndpoint, open.PrimaryEndpoint)
	require.NotContains(t, open.Token, client.machineID)
	require.NoError(t, manager.PreviewLinkToken(client.workspaceID, open.LinkID, open.Token))

	sender := &fakeElasticRequestLinkSender{}
	accepted, err := manager.AcceptLink(client.workspaceID, open.LinkID, open.Token, sender)
	require.NoError(t, err)
	require.Equal(t, grant, accepted)

	err = manager.PreviewLinkToken(client.workspaceID, open.LinkID, open.Token)
	requireElasticRejectReason(t, err, ElasticRequestLinkRejectReplayed)
	require.NotContains(t, err.Error(), open.Token)

	deadline := now.Add(12 * time.Second)
	resultCh, err := manager.AssignRemoteRequest(context.Background(), open.LinkID, RemoteRequestAssignmentSpec{
		RemoteRequestID: "rrq_1",
		EndpointID:      remoteEndpointWorkspaceList,
		EndpointVersion: 1,
		Payload:         json.RawMessage(`{"cursor":""}`),
		DeadlineAt:      deadline,
		TimeoutBudget:   12 * time.Second,
		CancelToken:     "cancel_1",
		Limits:          descriptor.Limits,
	})
	require.NoError(t, err)
	require.Len(t, sender.messages, 1)
	assignment, ok := sender.messages[0].(RemoteRequestAssignment[json.RawMessage])
	require.True(t, ok)
	require.Equal(t, sessionLinkRemoteRequestAssignType, assignment.Type)
	require.Equal(t, 1, assignment.SchemaVersion)
	require.Equal(t, "rrq_1", assignment.RemoteRequestID)
	require.Equal(t, remoteEndpointWorkspaceList, assignment.EndpointID)
	require.Equal(t, 1, assignment.PayloadSchemaVersion)
	require.Equal(t, deadline.Format(time.RFC3339Nano), assignment.DeadlineAt)
	require.Equal(t, int64(12000), assignment.TimeoutBudgetMs)
	require.Equal(t, "cancel_1", assignment.CancelToken)
	require.Equal(t, descriptor.Limits, assignment.Limits)

	_, err = manager.AssignRemoteRequest(context.Background(), open.LinkID, RemoteRequestAssignmentSpec{
		RemoteRequestID: "rrq_2",
		EndpointID:      remoteEndpointWorkspaceList,
		EndpointVersion: 1,
		Payload:         json.RawMessage(`{}`),
		DeadlineAt:      deadline,
		TimeoutBudget:   12 * time.Second,
		CancelToken:     "cancel_2",
		Limits:          descriptor.Limits,
	})
	requireElasticRejectReason(t, err, ElasticRequestLinkRejectCapacity)

	completed := manager.CompleteRemoteRequest(RemoteRequestResult[json.RawMessage]{Type: sessionLinkRemoteRequestResultType, RequestID: "rrq_1", Success: true, Outcome: "ok", Payload: json.RawMessage(`{"ok":true}`)})
	require.True(t, completed)
	result := <-resultCh
	require.True(t, result.Success)
	require.Equal(t, "ok", result.Outcome)

	_, err = manager.AssignRemoteRequest(context.Background(), open.LinkID, RemoteRequestAssignmentSpec{
		RemoteRequestID: "rrq_3",
		EndpointID:      remoteEndpointWorkspaceList,
		EndpointVersion: 1,
		Payload:         json.RawMessage(`{}`),
		DeadlineAt:      deadline,
		TimeoutBudget:   12 * time.Second,
		CancelToken:     "cancel_3",
		Limits:          descriptor.Limits,
	})
	require.NoError(t, err, "link-scoped single-flight pool should allow reuse after completion")
}

func TestElasticRequestLinkRouteDecisionMatrix(t *testing.T) {
	now := time.Date(2026, 6, 30, 4, 10, 0, 0, time.UTC)
	manager := newTestElasticRequestLinkManager(t, &now, ElasticRequestLinkManagerConfig{MaxPerMachine: 1})
	descriptor := defaultWorkspaceListEndpoint(t)

	light := manager.DecideRoute(newElasticReadyClient(), descriptor, RemoteRequestRouteOptions{})
	require.Equal(t, RemoteRequestRouteSessionLink, light.Mode)
	require.Equal(t, "session_link_within_policy", light.Reason)

	oldDesktop := newElasticReadyClient()
	oldDesktop.capabilities = map[string]struct{}{}
	fallback := manager.DecideRoute(oldDesktop, descriptor, RemoteRequestRouteOptions{SessionLinkUnderPressure: true})
	require.Equal(t, RemoteRequestRouteLegacySessionLinkFallback, fallback.Mode)
	require.Equal(t, "missing_transport_capability", fallback.Reason)

	noFallback := descriptor
	noFallback.LinkPolicy = RemoteEndpointLinkPolicyElasticRequired
	noFallback.FallbackCommand = commandFallbackNone
	unavailable := manager.DecideRoute(oldDesktop, noFallback, RemoteRequestRouteOptions{SessionLinkUnderPressure: true})
	require.Equal(t, RemoteRequestRouteStableError, unavailable.Mode)
	require.Equal(t, RemoteRequestStableErrorDesktopUnavailable, unavailable.StableError)

	open := manager.DecideRoute(newElasticReadyClient(), descriptor, RemoteRequestRouteOptions{SessionLinkUnderPressure: true})
	require.Equal(t, RemoteRequestRouteOpenElasticRequestLink, open.Mode)
	require.NotNil(t, open.OpenCommand)

	capFallback := manager.DecideRoute(newElasticReadyClient(), descriptor, RemoteRequestRouteOptions{SessionLinkUnderPressure: true})
	require.Equal(t, RemoteRequestRouteLegacySessionLinkFallback, capFallback.Mode)
	require.Equal(t, "elastic_request_link_capacity", capFallback.Reason)

	capNoFallback := manager.DecideRoute(newElasticReadyClient(), noFallback, RemoteRequestRouteOptions{SessionLinkUnderPressure: true})
	require.Equal(t, RemoteRequestRouteStableError, capNoFallback.Mode)
	require.Equal(t, RemoteRequestStableErrorDesktopBusy, capNoFallback.StableError)

	disabled := newTestElasticRequestLinkManager(t, &now, ElasticRequestLinkManagerConfig{EmergencyDisabled: true})
	disabledDecision := disabled.DecideRoute(newElasticReadyClient(), descriptor, RemoteRequestRouteOptions{SessionLinkUnderPressure: true})
	require.Equal(t, RemoteRequestRouteLegacySessionLinkFallback, disabledDecision.Mode)
	require.Equal(t, "elastic_request_disabled", disabledDecision.Reason)
}

func TestElasticRequestLinkTokenRejectsExpiredMismatchAndTamper(t *testing.T) {
	now := time.Date(2026, 6, 30, 4, 20, 0, 0, time.UTC)
	manager := newTestElasticRequestLinkManager(t, &now, ElasticRequestLinkManagerConfig{})
	client := newElasticReadyClient()
	descriptor := defaultWorkspaceListEndpoint(t)
	open, _, err := manager.CreateLinkGrant(client, descriptor)
	require.NoError(t, err)

	requireElasticRejectReason(t, manager.PreviewLinkToken("other", open.LinkID, open.Token), ElasticRequestLinkRejectWorkspaceMismatch)
	requireElasticRejectReason(t, manager.PreviewLinkToken(client.workspaceID, "erl_other", open.Token), ElasticRequestLinkRejectLinkMismatch)
	requireElasticRejectReason(t, manager.PreviewLinkToken(client.workspaceID, open.LinkID, open.Token+"x"), ElasticRequestLinkRejectInvalidToken)

	manager.config.NodeID = "node-b"
	requireElasticRejectReason(t, manager.PreviewLinkToken(client.workspaceID, open.LinkID, open.Token), ElasticRequestLinkRejectNodeMismatch)
	manager.config.NodeID = "node-a"

	manager.config.EndpointRegistryVersion = "daemon-endpoints:v2"
	requireElasticRejectReason(t, manager.PreviewLinkToken(client.workspaceID, open.LinkID, open.Token), ElasticRequestLinkRejectRegistryMismatch)
	manager.config.EndpointRegistryVersion = defaultEndpointRegistryVersion

	now = now.Add(defaultElasticRequestLinkConnectTimeout + time.Second)
	requireElasticRejectReason(t, manager.PreviewLinkToken(client.workspaceID, open.LinkID, open.Token), ElasticRequestLinkRejectExpired)
}

func TestElasticRequestLinkCleanupPaths(t *testing.T) {
	now := time.Date(2026, 6, 30, 4, 30, 0, 0, time.UTC)
	manager := newTestElasticRequestLinkManager(t, &now, ElasticRequestLinkManagerConfig{})
	client := newElasticReadyClient()
	descriptor := defaultWorkspaceListEndpoint(t)

	open, _, err := manager.CreateLinkGrant(client, descriptor)
	require.NoError(t, err)
	now = now.Add(defaultElasticRequestLinkConnectTimeout + time.Second)
	summary := manager.CleanupExpired(now)
	require.Equal(t, 1, summary.ExpiredGrants)
	requireElasticRejectReason(t, manager.PreviewLinkToken(client.workspaceID, open.LinkID, open.Token), ElasticRequestLinkRejectUnknownLink)

	now = time.Date(2026, 6, 30, 4, 40, 0, 0, time.UTC)
	open, _, err = manager.CreateLinkGrant(client, descriptor)
	require.NoError(t, err)
	sender := &fakeElasticRequestLinkSender{}
	_, err = manager.AcceptLink(client.workspaceID, open.LinkID, open.Token, sender)
	require.NoError(t, err)
	now = now.Add(defaultElasticRequestLinkIdleTimeout + time.Second)
	summary = manager.CleanupExpired(now)
	require.Equal(t, 1, summary.ClosedLinks)
	require.True(t, sender.closed)

	now = time.Date(2026, 6, 30, 4, 50, 0, 0, time.UTC)
	open, _, err = manager.CreateLinkGrant(client, descriptor)
	require.NoError(t, err)
	sender = &fakeElasticRequestLinkSender{}
	_, err = manager.AcceptLink(client.workspaceID, open.LinkID, open.Token, sender)
	require.NoError(t, err)
	resultCh, err := manager.AssignRemoteRequest(context.Background(), open.LinkID, RemoteRequestAssignmentSpec{
		RemoteRequestID: "rrq_timeout",
		EndpointID:      remoteEndpointWorkspaceList,
		EndpointVersion: 1,
		Payload:         json.RawMessage(`{}`),
		DeadlineAt:      now.Add(time.Second),
		TimeoutBudget:   time.Second,
		CancelToken:     "cancel_timeout",
		Limits:          descriptor.Limits,
	})
	require.NoError(t, err)
	now = now.Add(2 * time.Second)
	summary = manager.CleanupExpired(now)
	require.Equal(t, 1, summary.CanceledAssignments)
	result := <-resultCh
	require.False(t, result.Success)
	require.Equal(t, "deadline_exceeded", result.Outcome)

	open, _, err = manager.CreateLinkGrant(client, descriptor)
	require.NoError(t, err)
	sender = &fakeElasticRequestLinkSender{}
	_, err = manager.AcceptLink(client.workspaceID, open.LinkID, open.Token, sender)
	require.NoError(t, err)
	resultCh, err = manager.AssignRemoteRequest(context.Background(), open.LinkID, RemoteRequestAssignmentSpec{
		RemoteRequestID: "rrq_cancel",
		EndpointID:      remoteEndpointWorkspaceList,
		EndpointVersion: 1,
		Payload:         json.RawMessage(`{}`),
		DeadlineAt:      now.Add(10 * time.Second),
		TimeoutBudget:   10 * time.Second,
		CancelToken:     "cancel_session",
		Limits:          descriptor.Limits,
	})
	require.NoError(t, err)
	summary = manager.CleanupSession(client.machineID, client.currentSessionGeneration(), "session_generation_changed")
	require.Equal(t, 2, summary.ClosedLinks)
	require.Equal(t, 1, summary.CanceledAssignments)
	require.True(t, sender.closed)
	result = <-resultCh
	require.Equal(t, "canceled", result.Outcome)
}

func TestElasticRequestLinkManagerRunCleanupLoop(t *testing.T) {
	t.Run("connect timeout frees grant capacity", func(t *testing.T) {
		now := time.Date(2026, 6, 30, 5, 0, 0, 0, time.UTC)
		manager := newTestElasticRequestLinkManager(t, &now, ElasticRequestLinkManagerConfig{MaxPerMachine: 1, CleanupInterval: time.Millisecond})
		client := newElasticReadyClient()
		descriptor := defaultWorkspaceListEndpoint(t)
		open, _, err := manager.CreateLinkGrant(client, descriptor)
		require.NoError(t, err)
		require.Equal(t, 1, manager.activeCount(client.machineID))

		ctx, cancel := context.WithCancel(context.Background())
		defer cancel()
		go manager.RunCleanupLoop(ctx)
		now = now.Add(defaultElasticRequestLinkConnectTimeout + time.Second)

		require.Eventually(t, func() bool {
			return manager.activeCount(client.machineID) == 0
		}, time.Second, time.Millisecond)
		requireElasticRejectReason(t, manager.PreviewLinkToken(client.workspaceID, open.LinkID, open.Token), ElasticRequestLinkRejectUnknownLink)
	})

	t.Run("idle link closes without a manual cleanup call", func(t *testing.T) {
		now := time.Date(2026, 6, 30, 5, 10, 0, 0, time.UTC)
		manager := newTestElasticRequestLinkManager(t, &now, ElasticRequestLinkManagerConfig{CleanupInterval: time.Millisecond})
		client := newElasticReadyClient()
		descriptor := defaultWorkspaceListEndpoint(t)
		open, _, err := manager.CreateLinkGrant(client, descriptor)
		require.NoError(t, err)
		sender := &fakeElasticRequestLinkSender{}
		_, err = manager.AcceptLink(client.workspaceID, open.LinkID, open.Token, sender)
		require.NoError(t, err)

		ctx, cancel := context.WithCancel(context.Background())
		defer cancel()
		go manager.RunCleanupLoop(ctx)
		now = now.Add(defaultElasticRequestLinkIdleTimeout + time.Second)

		require.Eventually(t, func() bool {
			return sender.closed && manager.activeCount(client.machineID) == 0
		}, time.Second, time.Millisecond)
	})

	t.Run("assignment deadline returns stable timeout", func(t *testing.T) {
		now := time.Date(2026, 6, 30, 5, 20, 0, 0, time.UTC)
		manager := newTestElasticRequestLinkManager(t, &now, ElasticRequestLinkManagerConfig{CleanupInterval: time.Millisecond})
		client := newElasticReadyClient()
		descriptor := defaultWorkspaceListEndpoint(t)
		open, _, err := manager.CreateLinkGrant(client, descriptor)
		require.NoError(t, err)
		sender := &fakeElasticRequestLinkSender{}
		_, err = manager.AcceptLink(client.workspaceID, open.LinkID, open.Token, sender)
		require.NoError(t, err)
		resultCh, err := manager.AssignRemoteRequest(context.Background(), open.LinkID, RemoteRequestAssignmentSpec{
			RemoteRequestID: "rrq_agentteam_timeout",
			EndpointID:      remoteEndpointWorkspaceList,
			EndpointVersion: 1,
			Payload:         json.RawMessage(`{}`),
			DeadlineAt:      now.Add(time.Second),
			TimeoutBudget:   time.Second,
			CancelToken:     "cancel_agentteam_timeout",
			Limits:          descriptor.Limits,
		})
		require.NoError(t, err)

		ctx, cancel := context.WithCancel(context.Background())
		defer cancel()
		go manager.RunCleanupLoop(ctx)
		now = now.Add(2 * time.Second)

		var result RemoteRequestResult[json.RawMessage]
		require.Eventually(t, func() bool {
			select {
			case result = <-resultCh:
				return true
			default:
				return false
			}
		}, time.Second, time.Millisecond)
		require.False(t, result.Success)
		require.Equal(t, "deadline_exceeded", result.Outcome)
	})
}

func TestRemoteEndpointRegistryGuardrails(t *testing.T) {
	registry := defaultRemoteEndpointRegistry()
	expected := map[string]struct {
		policy          RemoteEndpointLinkPolicy
		fallbackCommand string
		safeRetry       bool
		warmEligible    bool
		warmSafety      RemoteEndpointWarmSafety
		version         int
	}{
		remoteEndpointWorkspaceList:                {policy: RemoteEndpointLinkPolicySessionPreferred, fallbackCommand: sessionLinkCommandAgentWorkspaceList, safeRetry: true, warmEligible: true, warmSafety: RemoteEndpointWarmSafetyReadOnly},
		remoteEndpointWorkspaceRead:                {policy: RemoteEndpointLinkPolicyElasticPreferred, fallbackCommand: sessionLinkCommandAgentWorkspaceRead, safeRetry: true, warmEligible: true, warmSafety: RemoteEndpointWarmSafetyReadOnly},
		remoteEndpointWorkspaceApplySeedFiles:      {policy: RemoteEndpointLinkPolicyElasticPreferred, fallbackCommand: sessionLinkCommandAgentWorkspaceApplySeedFiles, warmSafety: RemoteEndpointWarmSafetyNonIdempotent},
		remoteEndpointWorkspaceDelete:              {policy: RemoteEndpointLinkPolicySessionPreferred, fallbackCommand: sessionLinkCommandAgentWorkspaceDelete, warmSafety: RemoteEndpointWarmSafetyNonIdempotent},
		remoteEndpointReviewSummary:                {policy: RemoteEndpointLinkPolicyElasticPreferred, fallbackCommand: sessionLinkCommandAgentReviewSummary, safeRetry: true, warmEligible: true, warmSafety: RemoteEndpointWarmSafetyReadOnly},
		remoteEndpointReviewSnapshot:               {policy: RemoteEndpointLinkPolicyElasticPreferred, fallbackCommand: commandFallbackNone, safeRetry: false, warmEligible: false, warmSafety: RemoteEndpointWarmSafetyReadOnly},
		remoteEndpointReviewFingerprint:            {policy: RemoteEndpointLinkPolicyElasticPreferred, fallbackCommand: commandFallbackNone, safeRetry: true, warmEligible: true, warmSafety: RemoteEndpointWarmSafetyReadOnly},
		remoteEndpointReviewFiles:                  {policy: RemoteEndpointLinkPolicyElasticPreferred, fallbackCommand: sessionLinkCommandAgentReviewFiles, safeRetry: true, warmEligible: true, warmSafety: RemoteEndpointWarmSafetyReadOnly},
		remoteEndpointReviewDiff:                   {policy: RemoteEndpointLinkPolicyElasticPreferred, fallbackCommand: sessionLinkCommandAgentReviewDiff, safeRetry: true, warmEligible: true, warmSafety: RemoteEndpointWarmSafetyReadOnly},
		remoteEndpointReviewDiffBatch:              {policy: RemoteEndpointLinkPolicyElasticPreferred, fallbackCommand: commandFallbackNone, safeRetry: true, warmEligible: true, warmSafety: RemoteEndpointWarmSafetyReadOnly},
		remoteEndpointOutputTargetValidate:         {policy: RemoteEndpointLinkPolicySessionPreferred, fallbackCommand: sessionLinkCommandOutputTargetValidate, safeRetry: true, warmEligible: true, warmSafety: RemoteEndpointWarmSafetyIdempotent},
		remoteEndpointMachineWorkspaceScan:         {policy: RemoteEndpointLinkPolicyElasticPreferred, fallbackCommand: sessionLinkCommandMachineWorkspaceScan, safeRetry: true, warmEligible: true, warmSafety: RemoteEndpointWarmSafetyReadOnly},
		remoteEndpointMachineWorkspaceDelete:       {policy: RemoteEndpointLinkPolicySessionPreferred, fallbackCommand: sessionLinkCommandMachineWorkspaceDelete, warmSafety: RemoteEndpointWarmSafetyNonIdempotent},
		remoteEndpointMachineDirectoryList:         {policy: RemoteEndpointLinkPolicyElasticPreferred, fallbackCommand: commandFallbackNone, safeRetry: false, warmEligible: false, warmSafety: RemoteEndpointWarmSafetyReadOnly},
		remoteEndpointMachineDashboard:             {policy: RemoteEndpointLinkPolicyElasticPreferred, fallbackCommand: commandFallbackNone, safeRetry: false, warmEligible: false, warmSafety: RemoteEndpointWarmSafetyReadOnly, version: remoteEndpointMachineDashboardVersion},
		remoteEndpointMachineSettings:              {policy: RemoteEndpointLinkPolicyElasticPreferred, fallbackCommand: commandFallbackNone, safeRetry: false, warmEligible: false, warmSafety: RemoteEndpointWarmSafetyReadOnly},
		remoteEndpointMachineSettingsUpdate:        {policy: RemoteEndpointLinkPolicyElasticPreferred, fallbackCommand: commandFallbackNone, safeRetry: false, warmEligible: false, warmSafety: RemoteEndpointWarmSafetyNonIdempotent},
		remoteEndpointMachineRuntimesBundle:        {policy: RemoteEndpointLinkPolicyElasticPreferred, fallbackCommand: commandFallbackNone, safeRetry: false, warmEligible: false, warmSafety: RemoteEndpointWarmSafetyReadOnly},
		remoteEndpointMachineRuntimeConfigRead:     {policy: RemoteEndpointLinkPolicyElasticPreferred, fallbackCommand: commandFallbackNone, safeRetry: false, warmEligible: false, warmSafety: RemoteEndpointWarmSafetyReadOnly},
		remoteEndpointMachineRuntimeConfigUpdate:   {policy: RemoteEndpointLinkPolicyElasticPreferred, fallbackCommand: commandFallbackNone, safeRetry: false, warmEligible: false, warmSafety: RemoteEndpointWarmSafetyNonIdempotent},
		remoteEndpointMachineRuntimeConfigValidate: {policy: RemoteEndpointLinkPolicyElasticPreferred, fallbackCommand: commandFallbackNone, safeRetry: false, warmEligible: false, warmSafety: RemoteEndpointWarmSafetyReadOnly},
		remoteEndpointMachineRuntimesDetect:        {policy: RemoteEndpointLinkPolicyElasticPreferred, fallbackCommand: commandFallbackNone, safeRetry: false, warmEligible: false, warmSafety: RemoteEndpointWarmSafetyNonIdempotent},
		remoteEndpointMachineMCPServerList:         {policy: RemoteEndpointLinkPolicyElasticPreferred, fallbackCommand: commandFallbackNone, safeRetry: false, warmEligible: false, warmSafety: RemoteEndpointWarmSafetyReadOnly},
		remoteEndpointMachineMCPServerUpsert:       {policy: RemoteEndpointLinkPolicyElasticPreferred, fallbackCommand: commandFallbackNone, safeRetry: false, warmEligible: false, warmSafety: RemoteEndpointWarmSafetyNonIdempotent},
		remoteEndpointMachineMCPServerDelete:       {policy: RemoteEndpointLinkPolicyElasticPreferred, fallbackCommand: commandFallbackNone, safeRetry: false, warmEligible: false, warmSafety: RemoteEndpointWarmSafetyNonIdempotent},
		remoteEndpointMachineMCPServerTest:         {policy: RemoteEndpointLinkPolicyElasticPreferred, fallbackCommand: commandFallbackNone, safeRetry: false, warmEligible: false, warmSafety: RemoteEndpointWarmSafetyReadOnly},
		remoteEndpointRuntimeTrajectoryHistory:     {policy: RemoteEndpointLinkPolicyElasticPreferred, fallbackCommand: sessionLinkCommandAgentTrajectoryHistory, safeRetry: true, warmEligible: true, warmSafety: RemoteEndpointWarmSafetyReadOnly},
		remoteEndpointRuntimeRestoreRecoveryPoint:  {policy: RemoteEndpointLinkPolicySessionPreferred, fallbackCommand: sessionLinkCommandAgentRestoreRecoveryPoint, warmSafety: RemoteEndpointWarmSafetyNonIdempotent},
		remoteEndpointRuntimeMemorySyncStatus:      {policy: RemoteEndpointLinkPolicySessionPreferred, fallbackCommand: commandFallbackNone, warmSafety: RemoteEndpointWarmSafetyReadOnly},
		remoteEndpointRuntimeMemorySyncRetry:       {policy: RemoteEndpointLinkPolicyElasticPreferred, fallbackCommand: commandFallbackNone, warmSafety: RemoteEndpointWarmSafetyIdempotent},
	}
	require.Len(t, registry.Descriptors(), len(expected))
	for endpointID, want := range expected {
		lookupVersion := want.version
		if lookupVersion == 0 {
			lookupVersion = 1
		}
		descriptor, ok := registry.Lookup(endpointID, lookupVersion)
		require.True(t, ok, "missing descriptor %s", endpointID)
		require.Equal(t, want.policy, descriptor.LinkPolicy)
		require.Equal(t, want.fallbackCommand, descriptor.FallbackCommand)
		require.Equal(t, want.safeRetry, descriptor.SafeRetryFallback)
		if descriptor.FallbackCommand != commandFallbackNone {
			_, commandRegistered := defaultSessionLinkCommandRegistry().Lookup(descriptor.FallbackCommand)
			require.True(t, commandRegistered, "fallback command %s for endpoint %s must be registered", descriptor.FallbackCommand, endpointID)
		}
		require.NotEmpty(t, descriptor.Owner)
		require.NotEmpty(t, descriptor.CapabilityGate)
		require.NotEmpty(t, descriptor.RegistryVersion)
		require.NotEmpty(t, descriptor.MetricsName)
		require.Positive(t, descriptor.Timeout)
		require.Positive(t, descriptor.DialTimeout)
		require.Positive(t, descriptor.Limits.RequestBytes)
		require.Positive(t, descriptor.Limits.ResponseBytes)
		require.Equal(t, want.warmEligible, descriptor.WarmMetadata.Eligible, endpointID)
		require.Equal(t, want.warmSafety, descriptor.WarmMetadata.Safety, endpointID)
		if want.warmEligible {
			require.Equal(t, defaultWarmEndpointProfileName, descriptor.WarmMetadata.Profile, endpointID)
			require.NotEmpty(t, descriptor.WarmMetadata.Rationale, endpointID)
		} else {
			require.Empty(t, descriptor.WarmMetadata.Profile, endpointID)
		}
	}
	descriptor, ok := registry.Lookup(remoteEndpointWorkspaceList, 1)
	require.True(t, ok)

	_, err := NewRemoteEndpointRegistry([]RemoteEndpointDescriptor{{EndpointID: "bad"}})
	require.ErrorIs(t, err, ErrRemoteEndpointDescriptorInvalid)

	_, err = NewRemoteEndpointRegistry([]RemoteEndpointDescriptor{descriptor, descriptor})
	require.ErrorIs(t, err, ErrRemoteEndpointAlreadyRegistered)
}

func TestWarmEndpointProfileDefaultMembership(t *testing.T) {
	registry := defaultRemoteEndpointRegistry()
	profile, err := registry.WarmEndpointProfile(defaultWarmEndpointProfileName)
	require.NoError(t, err)
	require.Equal(t, defaultWarmEndpointProfileName, profile.Name)
	require.False(t, profile.MutatingAllowed)
	require.Equal(t, []RemoteEndpointWarmSafety{RemoteEndpointWarmSafetyIdempotent, RemoteEndpointWarmSafetyReadOnly}, profile.SafetyClasses)
	require.Equal(t, []RemoteEndpointScope{
		{EndpointID: remoteEndpointMachineWorkspaceScan, Version: 1},
		{EndpointID: remoteEndpointOutputTargetValidate, Version: 1},
		{EndpointID: remoteEndpointReviewDiff, Version: 1},
		{EndpointID: remoteEndpointReviewDiffBatch, Version: 1},
		{EndpointID: remoteEndpointReviewFiles, Version: 1},
		{EndpointID: remoteEndpointReviewFingerprint, Version: 1},
		{EndpointID: remoteEndpointReviewSummary, Version: 1},
		{EndpointID: remoteEndpointRuntimeTrajectoryHistory, Version: 1},
		{EndpointID: remoteEndpointWorkspaceList, Version: 1},
		{EndpointID: remoteEndpointWorkspaceRead, Version: 1},
	}, profile.EndpointScopes)

	for _, demandOnly := range []string{
		remoteEndpointWorkspaceApplySeedFiles,
		remoteEndpointWorkspaceDelete,
		remoteEndpointMachineWorkspaceDelete,
		remoteEndpointMachineDirectoryList,
		remoteEndpointRuntimeRestoreRecoveryPoint,
	} {
		require.False(t, remoteEndpointScopesContain(profile.EndpointScopes, RemoteEndpointScope{EndpointID: demandOnly, Version: 1}), demandOnly)
	}
}

func TestWarmEndpointProfileRejectsDestructiveDefaultMembership(t *testing.T) {
	descriptor := defaultWorkspaceListEndpoint(t)
	descriptor.EndpointID = remoteEndpointWorkspaceDelete
	descriptor.FallbackCommand = sessionLinkCommandAgentWorkspaceDelete
	descriptor.MetricsName = remoteEndpointWorkspaceDelete
	descriptor.SafeRetryFallback = false
	descriptor.WarmMetadata = warmEligible(RemoteEndpointWarmSafetyReadOnly, "invalid destructive warm membership")
	_, err := NewRemoteEndpointRegistry([]RemoteEndpointDescriptor{descriptor})
	require.ErrorIs(t, err, ErrRemoteEndpointDescriptorInvalid)
}

func TestLinkGrantSpecSupportsWarmProfileAllowlist(t *testing.T) {
	now := time.Date(2026, 7, 1, 6, 0, 0, 0, time.UTC)
	manager := newTestElasticRequestLinkManager(t, &now, ElasticRequestLinkManagerConfig{})
	client := newElasticReadyClient()
	spec, err := manager.WarmLinkGrantSpec(defaultWarmEndpointProfileName)
	require.NoError(t, err)
	require.Equal(t, ElasticLinkPurposeWarm, spec.Purpose)
	require.Equal(t, defaultWarmEndpointProfileName, spec.ProfileName)
	require.Nil(t, spec.PrimaryEndpoint)
	require.Greater(t, len(spec.AllowedEndpoints), 1)

	open, grant, err := manager.CreateLinkGrantForSpec(client, spec)
	require.NoError(t, err)
	require.Equal(t, ElasticLinkPurposeWarm, grant.Purpose)
	require.Equal(t, defaultWarmEndpointProfileName, grant.ProfileName)
	require.Nil(t, grant.PrimaryEndpoint)
	require.Equal(t, spec.AllowedEndpoints, grant.AllowedEndpoints)
	require.Equal(t, ElasticLinkPurposeWarm, open.Purpose)
	require.Equal(t, defaultWarmEndpointProfileName, open.ProfileName)
	require.Equal(t, spec.AllowedEndpoints, open.AllowedEndpoints)
	require.NoError(t, manager.PreviewLinkToken(client.workspaceID, open.LinkID, open.Token))

	sender := &fakeElasticRequestLinkSender{}
	_, err = manager.AcceptLink(client.workspaceID, open.LinkID, open.Token, sender)
	require.NoError(t, err)
	deadline := now.Add(12 * time.Second)
	resultCh, err := manager.AssignRemoteRequest(context.Background(), open.LinkID, RemoteRequestAssignmentSpec{
		RemoteRequestID: "rrq_review",
		EndpointID:      remoteEndpointReviewSummary,
		EndpointVersion: 1,
		Payload:         json.RawMessage(`{}`),
		DeadlineAt:      deadline,
		TimeoutBudget:   12 * time.Second,
		CancelToken:     "cancel_review",
		Limits:          RemoteEndpointLimits{RequestBytes: 1024, ResponseBytes: 1024},
	})
	require.NoError(t, err)
	require.NotNil(t, resultCh)
	manager.CompleteRemoteRequest(RemoteRequestResult[json.RawMessage]{Type: sessionLinkRemoteRequestResultType, RequestID: "rrq_review", Success: true, Outcome: "ok", Payload: json.RawMessage(`{}`)})
	<-resultCh

	_, err = manager.AssignRemoteRequest(context.Background(), open.LinkID, RemoteRequestAssignmentSpec{
		RemoteRequestID: "rrq_delete",
		EndpointID:      remoteEndpointWorkspaceDelete,
		EndpointVersion: 1,
		Payload:         json.RawMessage(`{}`),
		DeadlineAt:      deadline,
		TimeoutBudget:   12 * time.Second,
		CancelToken:     "cancel_delete",
		Limits:          RemoteEndpointLimits{RequestBytes: 1024, ResponseBytes: 1024},
	})
	requireElasticRejectReason(t, err, ElasticRequestLinkRejectRegistryMismatch)
}

func TestLinkGrantSpecRejectsWarmAllowlistOutsideProfile(t *testing.T) {
	now := time.Date(2026, 7, 1, 6, 10, 0, 0, time.UTC)
	manager := newTestElasticRequestLinkManager(t, &now, ElasticRequestLinkManagerConfig{})
	client := newElasticReadyClient()
	_, _, err := manager.CreateLinkGrantForSpec(client, LinkGrantSpec{
		Purpose:     ElasticLinkPurposeWarm,
		ProfileName: defaultWarmEndpointProfileName,
		AllowedEndpoints: []RemoteEndpointScope{
			{EndpointID: remoteEndpointWorkspaceList, Version: 1},
			{EndpointID: remoteEndpointWorkspaceDelete, Version: 1},
		},
	})
	requireElasticRejectReason(t, err, ElasticRequestLinkRejectRegistryMismatch)

	limitedClient := newElasticReadyClient()
	delete(limitedClient.supportedEndpointVersions, remoteEndpointReviewSummary)
	spec, err := manager.WarmLinkGrantSpec(defaultWarmEndpointProfileName)
	require.NoError(t, err)
	_, _, err = manager.CreateLinkGrantForSpec(limitedClient, spec)
	requireElasticRejectReason(t, err, ElasticRequestLinkRejectRegistryMismatch)
}

func TestWarmPoolControllerCreatesAndReusesWarmLink(t *testing.T) {
	now := time.Date(2026, 7, 1, 7, 0, 0, 0, time.UTC)
	var opens []ElasticRequestLinkOpenCommand
	manager := newTestElasticRequestLinkManager(t, &now, ElasticRequestLinkManagerConfig{
		WarmOpenSender: func(_ *clientState, open ElasticRequestLinkOpenCommand) error {
			opens = append(opens, open)
			return nil
		},
	})
	client := newElasticReadyClient()
	descriptor := defaultWorkspaceListEndpoint(t)

	manager.OnRequestActivity(context.Background(), client, descriptor, userInteractiveRemoteRequestContext())
	require.Len(t, opens, 1)
	require.Equal(t, ElasticLinkPurposeWarm, opens[0].Purpose)
	require.Equal(t, defaultWarmEndpointProfileName, opens[0].ProfileName)
	require.True(t, remoteEndpointScopesContain(opens[0].AllowedEndpoints, RemoteEndpointScope{EndpointID: remoteEndpointWorkspaceRead, Version: 1}))
	require.False(t, remoteEndpointScopesContain(opens[0].AllowedEndpoints, RemoteEndpointScope{EndpointID: remoteEndpointWorkspaceDelete, Version: 1}))

	sender := &fakeElasticRequestLinkSender{}
	_, err := manager.AcceptLink(client.workspaceID, opens[0].LinkID, opens[0].Token, sender)
	require.NoError(t, err)

	readDescriptor, ok := defaultRemoteEndpointRegistry().Lookup(remoteEndpointWorkspaceRead, 1)
	require.True(t, ok)
	decision := manager.DecideRoute(client, readDescriptor, RemoteRequestRouteOptions{})
	require.Equal(t, RemoteRequestRouteElasticRequestLink, decision.Mode)
	require.Equal(t, opens[0].LinkID, decision.LinkID)

	// Warm presence must not force a session_preferred endpoint into ERL.
	decision = manager.DecideRoute(client, descriptor, RemoteRequestRouteOptions{})
	require.Equal(t, RemoteRequestRouteSessionLink, decision.Mode)
}

func TestWarmPoolControllerFirstUserRequestDoesNotWaitForWarmReady(t *testing.T) {
	serverConn, desktopConn := newDaemonProtocolTestPair(t)
	client := newWorkspaceListRemoteReadyClient(serverConn)
	now := time.Date(2026, 7, 1, 7, 10, 0, 0, time.UTC)
	manager := newTestElasticRequestLinkManager(t, &now, ElasticRequestLinkManagerConfig{})
	hub := &Hub{remoteEndpoints: defaultRemoteEndpointRegistry(), elasticRequestLinks: manager}
	openCh := make(chan ElasticRequestLinkOpenCommand, 1)

	go func() {
		var assignment RemoteRequestAssignment[json.RawMessage]
		require.NoError(t, desktopConn.ReadJSON(&assignment))
		require.Equal(t, sessionLinkRemoteRequestAssignType, assignment.Type)
		require.Equal(t, remoteEndpointWorkspaceList, assignment.EndpointID)
		result := RemoteRequestResult[json.RawMessage]{
			Type:      sessionLinkRemoteRequestResultType,
			RequestID: assignment.RequestID,
			Success:   true,
			Outcome:   "ok",
			Payload:   workspaceListRemotePayload(t, "first-user.txt"),
		}
		require.NoError(t, handleSessionLinkRemoteRequestResultCommand(hub, context.Background(), client, mustMarshalRemoteWorkspaceTest(t, result)))
		var open ElasticRequestLinkOpenCommand
		require.NoError(t, desktopConn.ReadJSON(&open))
		openCh <- open
	}()

	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	ctx = runtimecontrol.WithRemoteRequestContext(ctx, userInteractiveRemoteRequestContext())
	page, err := hub.listWorkspace(ctx, client, "agt_1", "", "", agent.WorkspaceListOptions{Limit: 10})
	require.NoError(t, err)
	require.Equal(t, "first-user.txt", page.Files[0].Name)
	select {
	case open := <-openCh:
		require.Equal(t, elasticRequestLinkOpenType, open.Type)
		require.Equal(t, ElasticLinkPurposeWarm, open.Purpose)
	case <-time.After(time.Second):
		t.Fatal("timed out waiting for deferred warm open")
	}
}

func TestWarmPoolControllerDemandOnlyRefreshesLeaseWithoutChangingRoute(t *testing.T) {
	now := time.Date(2026, 7, 1, 7, 20, 0, 0, time.UTC)
	var opens []ElasticRequestLinkOpenCommand
	manager := newTestElasticRequestLinkManager(t, &now, ElasticRequestLinkManagerConfig{
		WarmOpenSender: func(_ *clientState, open ElasticRequestLinkOpenCommand) error {
			opens = append(opens, open)
			return nil
		},
	})
	client := newElasticReadyClient()
	descriptor, ok := defaultRemoteEndpointRegistry().Lookup(remoteEndpointWorkspaceApplySeedFiles, 1)
	require.True(t, ok)

	key, profileName, ok := manager.PrepareWarmPoolActivity(context.Background(), client, descriptor, userInteractiveRemoteRequestContext())
	require.True(t, ok)
	decision := manager.DecideRoute(client, descriptor, RemoteRequestRouteOptions{ForceElastic: true})
	require.Equal(t, RemoteRequestRouteOpenElasticRequestLink, decision.Mode)
	require.NotNil(t, decision.OpenCommand)
	require.Equal(t, ElasticLinkPurposeDemand, decision.OpenCommand.Purpose)
	require.Equal(t, &RemoteEndpointScope{EndpointID: remoteEndpointWorkspaceApplySeedFiles, Version: 1}, decision.OpenCommand.PrimaryEndpoint)

	manager.ReconcileWarmPool(client, key, profileName)
	require.Len(t, opens, 1)
	require.Equal(t, ElasticLinkPurposeWarm, opens[0].Purpose)
	require.False(t, remoteEndpointScopesContain(opens[0].AllowedEndpoints, RemoteEndpointScope{EndpointID: remoteEndpointWorkspaceApplySeedFiles, Version: 1}))

	manager.mu.Lock()
	defer manager.mu.Unlock()
	manager.ensureWarmControllerLocked()
	require.Len(t, manager.warm.leases, 1)
}

func TestWarmPoolControllerBackgroundDoesNotCreateLease(t *testing.T) {
	now := time.Date(2026, 7, 1, 7, 30, 0, 0, time.UTC)
	var opens []ElasticRequestLinkOpenCommand
	manager := newTestElasticRequestLinkManager(t, &now, ElasticRequestLinkManagerConfig{
		WarmOpenSender: func(_ *clientState, open ElasticRequestLinkOpenCommand) error {
			opens = append(opens, open)
			return nil
		},
	})
	client := newElasticReadyClient()

	manager.OnRequestActivity(context.Background(), client, defaultWorkspaceListEndpoint(t), runtimecontrol.RemoteRequestContext{})
	require.Empty(t, opens)
	manager.mu.Lock()
	defer manager.mu.Unlock()
	require.Empty(t, manager.warm.leases)
}

func TestWarmPoolControllerBusySingleFlightReplacement(t *testing.T) {
	now := time.Date(2026, 7, 1, 7, 40, 0, 0, time.UTC)
	var opens []ElasticRequestLinkOpenCommand
	manager := newTestElasticRequestLinkManager(t, &now, ElasticRequestLinkManagerConfig{
		WarmMaxLinks: 2,
		WarmOpenSender: func(_ *clientState, open ElasticRequestLinkOpenCommand) error {
			opens = append(opens, open)
			return nil
		},
	})
	client := newElasticReadyClient()
	descriptor := defaultWorkspaceListEndpoint(t)

	manager.OnRequestActivity(context.Background(), client, descriptor, userInteractiveRemoteRequestContext())
	require.Len(t, opens, 1)
	sender := &fakeElasticRequestLinkSender{}
	_, err := manager.AcceptLink(client.workspaceID, opens[0].LinkID, opens[0].Token, sender)
	require.NoError(t, err)
	_, err = manager.AssignRemoteRequest(context.Background(), opens[0].LinkID, RemoteRequestAssignmentSpec{
		RemoteRequestID: "rrq_busy",
		EndpointID:      remoteEndpointWorkspaceRead,
		EndpointVersion: 1,
		Payload:         json.RawMessage(`{}`),
		DeadlineAt:      now.Add(10 * time.Second),
		TimeoutBudget:   10 * time.Second,
		CancelToken:     "cancel_busy",
		Limits:          RemoteEndpointLimits{RequestBytes: 1024, ResponseBytes: 1024},
	})
	require.NoError(t, err)

	manager.OnRequestActivity(context.Background(), client, descriptor, userInteractiveRemoteRequestContext())
	require.Len(t, opens, 2)
	require.NotEqual(t, opens[0].LinkID, opens[1].LinkID)
}

func TestWarmPoolControllerLeaseExpiryDrainsWarmLink(t *testing.T) {
	now := time.Date(2026, 7, 1, 7, 50, 0, 0, time.UTC)
	var opens []ElasticRequestLinkOpenCommand
	manager := newTestElasticRequestLinkManager(t, &now, ElasticRequestLinkManagerConfig{
		WarmActiveTTL: time.Second,
		WarmOpenSender: func(_ *clientState, open ElasticRequestLinkOpenCommand) error {
			opens = append(opens, open)
			return nil
		},
	})
	client := newElasticReadyClient()

	manager.OnRequestActivity(context.Background(), client, defaultWorkspaceListEndpoint(t), userInteractiveRemoteRequestContext())
	require.Len(t, opens, 1)
	sender := &fakeElasticRequestLinkSender{}
	_, err := manager.AcceptLink(client.workspaceID, opens[0].LinkID, opens[0].Token, sender)
	require.NoError(t, err)

	now = now.Add(2 * time.Second)
	summary := manager.CleanupExpired(now)
	require.Equal(t, 1, summary.ClosedLinks)
	require.True(t, sender.closed)
	manager.mu.Lock()
	defer manager.mu.Unlock()
	require.Empty(t, manager.warm.leases)
}

func TestWarmPoolControllerSessionCleanupRemovesWarmState(t *testing.T) {
	now := time.Date(2026, 7, 1, 8, 0, 0, 0, time.UTC)
	var opens []ElasticRequestLinkOpenCommand
	manager := newTestElasticRequestLinkManager(t, &now, ElasticRequestLinkManagerConfig{
		WarmOpenSender: func(_ *clientState, open ElasticRequestLinkOpenCommand) error {
			opens = append(opens, open)
			return nil
		},
	})
	client := newElasticReadyClient()
	manager.OnRequestActivity(context.Background(), client, defaultWorkspaceListEndpoint(t), userInteractiveRemoteRequestContext())
	require.Len(t, opens, 1)
	manager.CleanupLinkGrant(opens[0].LinkID, "connect_timeout")

	summary := manager.CleanupSession(client.machineID, client.currentSessionGeneration(), "session_generation_changed")
	require.Zero(t, summary.ExpiredGrants)
	manager.mu.Lock()
	defer manager.mu.Unlock()
	require.Empty(t, manager.warm.leases)
	require.Empty(t, manager.warm.cooldowns)
}

func TestWarmPoolControllerCooldownCapacityAndEmergencyDisable(t *testing.T) {
	t.Run("cooldown suppresses reconnect after connect timeout", func(t *testing.T) {
		now := time.Date(2026, 7, 1, 8, 10, 0, 0, time.UTC)
		var opens []ElasticRequestLinkOpenCommand
		manager := newTestElasticRequestLinkManager(t, &now, ElasticRequestLinkManagerConfig{
			WarmCooldownBase: 10 * time.Second,
			WarmOpenSender: func(_ *clientState, open ElasticRequestLinkOpenCommand) error {
				opens = append(opens, open)
				return nil
			},
		})
		client := newElasticReadyClient()
		manager.OnRequestActivity(context.Background(), client, defaultWorkspaceListEndpoint(t), userInteractiveRemoteRequestContext())
		require.Len(t, opens, 1)
		manager.CleanupLinkGrant(opens[0].LinkID, "connect_timeout")
		manager.OnRequestActivity(context.Background(), client, defaultWorkspaceListEndpoint(t), userInteractiveRemoteRequestContext())
		require.Len(t, opens, 1)
	})

	t.Run("expired unaccepted warm grant enters cooldown", func(t *testing.T) {
		now := time.Date(2026, 7, 1, 8, 15, 0, 0, time.UTC)
		var opens []ElasticRequestLinkOpenCommand
		manager := newTestElasticRequestLinkManager(t, &now, ElasticRequestLinkManagerConfig{
			WarmCooldownBase: 10 * time.Second,
			WarmOpenSender: func(_ *clientState, open ElasticRequestLinkOpenCommand) error {
				opens = append(opens, open)
				return nil
			},
		})
		client := newElasticReadyClient()

		manager.OnRequestActivity(context.Background(), client, defaultWorkspaceListEndpoint(t), userInteractiveRemoteRequestContext())
		require.Len(t, opens, 1)
		expiresAt, err := time.Parse(time.RFC3339, opens[0].ExpiresAt)
		require.NoError(t, err)
		now = expiresAt.Add(time.Millisecond)
		summary := manager.CleanupExpired(now)
		require.Equal(t, 1, summary.ExpiredGrants)

		manager.OnRequestActivity(context.Background(), client, defaultWorkspaceListEndpoint(t), userInteractiveRemoteRequestContext())
		require.Len(t, opens, 1)
		manager.mu.Lock()
		defer manager.mu.Unlock()
		require.Len(t, manager.warm.cooldowns, 1)
	})

	t.Run("capacity skip does not enter cooldown", func(t *testing.T) {
		now := time.Date(2026, 7, 1, 8, 20, 0, 0, time.UTC)
		var opens []ElasticRequestLinkOpenCommand
		manager := newTestElasticRequestLinkManager(t, &now, ElasticRequestLinkManagerConfig{
			MaxPerMachine: 1,
			WarmOpenSender: func(_ *clientState, open ElasticRequestLinkOpenCommand) error {
				opens = append(opens, open)
				return nil
			},
		})
		client := newElasticReadyClient()
		_, _, err := manager.CreateLinkGrant(client, defaultWorkspaceListEndpoint(t))
		require.NoError(t, err)
		manager.OnRequestActivity(context.Background(), client, defaultWorkspaceListEndpoint(t), userInteractiveRemoteRequestContext())
		require.Empty(t, opens)
		manager.mu.Lock()
		defer manager.mu.Unlock()
		require.Empty(t, manager.warm.cooldowns)
	})

	t.Run("emergency disabled does not create warm lease", func(t *testing.T) {
		now := time.Date(2026, 7, 1, 8, 30, 0, 0, time.UTC)
		var opens []ElasticRequestLinkOpenCommand
		manager := newTestElasticRequestLinkManager(t, &now, ElasticRequestLinkManagerConfig{
			EmergencyDisabled: true,
			WarmOpenSender: func(_ *clientState, open ElasticRequestLinkOpenCommand) error {
				opens = append(opens, open)
				return nil
			},
		})
		client := newElasticReadyClient()
		manager.OnRequestActivity(context.Background(), client, defaultWorkspaceListEndpoint(t), userInteractiveRemoteRequestContext())
		require.Empty(t, opens)
		manager.mu.Lock()
		defer manager.mu.Unlock()
		require.Empty(t, manager.warm.leases)
	})
}

func userInteractiveRemoteRequestContext() runtimecontrol.RemoteRequestContext {
	return runtimecontrol.RemoteRequestContext{Origin: runtimecontrol.RemoteRequestOriginUserInteractive, Cause: runtimecontrol.RemoteRequestCauseWebAPI}
}

func newTestElasticRequestLinkManager(t *testing.T, now *time.Time, config ElasticRequestLinkManagerConfig) *ElasticRequestLinkManager {
	t.Helper()
	config.NodeID = "node-a"
	config.TokenSecret = []byte("test-secret-that-is-long-enough")
	config.Now = func() time.Time { return *now }
	var next int
	config.NewID = func(prefix string) string {
		next++
		return prefix + string(rune('a'+next-1))
	}
	return NewElasticRequestLinkManager(config, defaultRemoteEndpointRegistry(), nil)
}

func newElasticReadyClient() *clientState {
	client := &clientState{
		machineID:                 "mac_1",
		workspaceID:               "wsp_1",
		capabilities:              make(map[string]struct{}),
		supportedEndpointVersions: make(map[string]map[int]struct{}),
	}
	client.setCapabilities([]string{daemonTransportCapabilityV1, daemonTransportElasticRequestCapability, daemonEndpointsCapabilityV1})
	client.setDaemonTransportReady(daemonTransportReady{
		SchemaVersion:           defaultElasticRequestLinkProtocolVersion,
		SessionGeneration:       "gen_1",
		EndpointRegistryVersion: defaultEndpointRegistryVersion,
		SupportedEndpoints:      defaultRemoteEndpointRefs(),
	})
	return client
}

func defaultWorkspaceListEndpoint(t *testing.T) RemoteEndpointDescriptor {
	t.Helper()
	descriptor, ok := defaultRemoteEndpointRegistry().Lookup(remoteEndpointWorkspaceList, 1)
	require.True(t, ok)
	return descriptor
}

func requireElasticRejectReason(t *testing.T, err error, reason ElasticRequestLinkRejectReason) {
	t.Helper()
	var linkErr ElasticRequestLinkError
	require.Truef(t, errors.As(err, &linkErr), "error %v should be ElasticRequestLinkError", err)
	require.Equal(t, reason, linkErr.Reason)
}

func defaultRemoteEndpointRefs() []daemonTransportEndpointRef {
	descriptors := defaultRemoteEndpointRegistry().Descriptors()
	refs := make([]daemonTransportEndpointRef, 0, len(descriptors))
	for _, descriptor := range descriptors {
		refs = append(refs, daemonTransportEndpointRef{EndpointID: descriptor.EndpointID, Version: descriptor.Version})
	}
	return refs
}
