package audit

import (
	"context"
	"testing"
)

// TestEntrypointFromContext_Missing asserts that reading from a bare ctx
// returns EntrypointUnknown (not "", not a panic). This is the §3.1 CH-4
// invariant: no silent REST_API fallback for callers that forgot to wrap.
func TestEntrypointFromContext_Missing(t *testing.T) {
	got := EntrypointFromContext(context.Background())
	if got != EntrypointUnknown {
		t.Fatalf("missing ctx: got %q, want %q", got, EntrypointUnknown)
	}
}

// TestEntrypointFromContext_NilCtx asserts a defensive nil-ctx path returns
// UNKNOWN instead of panicking on ctx.Value.
func TestEntrypointFromContext_NilCtx(t *testing.T) {
	got := EntrypointFromContext(nil) //nolint:staticcheck // intentional nil test
	if got != EntrypointUnknown {
		t.Fatalf("nil ctx: got %q, want %q", got, EntrypointUnknown)
	}
}

// TestWithEntrypoint_RoundTrip covers every entrypoint value that might
// plausibly appear on the stack for this commit's scope.
func TestWithEntrypoint_RoundTrip(t *testing.T) {
	cases := []AuditEntrypoint{
		EntrypointFlow,
		EntrypointTrigger,
		EntrypointRestAPI,
		EntrypointRestUI,
		EntrypointBulkAPI,
		EntrypointConvert,
		EntrypointApproval,
		EntrypointScheduler,
		EntrypointUnknown,
	}
	for _, ep := range cases {
		t.Run(string(ep), func(t *testing.T) {
			ctx := WithEntrypoint(context.Background(), ep)
			if got := EntrypointFromContext(ctx); got != ep {
				t.Fatalf("round-trip: got %q, want %q", got, ep)
			}
		})
	}
}

// TestWithEntrypoint_StackPushOverwrites asserts §3.5 stack-push semantics:
// a nested WithEntrypoint overrides the outer value. Flow invoked from a
// Trigger must surface as FLOW at the leaf, not TRIGGER.
func TestWithEntrypoint_StackPushOverwrites(t *testing.T) {
	outer := WithEntrypoint(context.Background(), EntrypointTrigger)
	inner := WithEntrypoint(outer, EntrypointFlow)

	if got := EntrypointFromContext(inner); got != EntrypointFlow {
		t.Fatalf("inner: got %q, want %q", got, EntrypointFlow)
	}
	// Outer ctx must be unaffected (immutability).
	if got := EntrypointFromContext(outer); got != EntrypointTrigger {
		t.Fatalf("outer: got %q, want %q", got, EntrypointTrigger)
	}
}

// TestEntrypointFromContext_TypeSafety asserts that an unrelated value stored
// under a different key on ctx does not leak in as a false-positive.
func TestEntrypointFromContext_TypeSafety(t *testing.T) {
	type otherKey struct{}
	ctx := context.WithValue(context.Background(), otherKey{}, "FLOW")
	if got := EntrypointFromContext(ctx); got != EntrypointUnknown {
		t.Fatalf("foreign key: got %q, want %q", got, EntrypointUnknown)
	}
}

