package runner

import (
	"context"
	"testing"
	"time"
)

func TestRequestExecutionContextCancelsBeforeSubmission(t *testing.T) {
	requestCtx, cancelRequest := context.WithCancel(context.Background())
	serverCtx, cancelServer := context.WithCancel(context.Background())
	defer cancelServer()
	ctx, cancel := NewRequestExecutionContext(requestCtx, serverCtx)
	defer cancel()

	cancelRequest()
	select {
	case <-ctx.Done():
	case <-time.After(time.Second):
		t.Fatal("request context did not cancel before upstream submission")
	}
}

func TestRequestExecutionContextSurvivesDisconnectAfterSubmission(t *testing.T) {
	requestCtx, cancelRequest := context.WithCancel(context.Background())
	serverCtx, cancelServer := context.WithCancel(context.Background())
	ctx, cancel := NewRequestExecutionContext(requestCtx, serverCtx)
	defer cancel()

	markUpstreamSubmissionStarted(ctx)
	cancelRequest()
	select {
	case <-ctx.Done():
		t.Fatal("client disconnect propagated after upstream submission")
	case <-time.After(50 * time.Millisecond):
	}

	cancelServer()
	select {
	case <-ctx.Done():
	case <-time.After(time.Second):
		t.Fatal("server shutdown did not cancel detached execution")
	}
}

func TestRequestExecutionContextPreservesRequestValues(t *testing.T) {
	type contextKey struct{}
	requestCtx := context.WithValue(context.Background(), contextKey{}, "trace-value")
	ctx, cancel := NewRequestExecutionContext(requestCtx, context.Background())
	defer cancel()

	if got := ctx.Value(contextKey{}); got != "trace-value" {
		t.Fatalf("request context value = %v, want trace-value", got)
	}
}
