package sfcrmappservice

import (
	"context"
	"errors"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
	"time"

	attachmentsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/recordattachmentsv1"
	mutationsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/recordmutationv1"
	semantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/recordviewv1"
)

type recordViewRuntimeStub struct {
	readResponse    semantic.ReadResponse
	readErr         error
	resolveResponse attachmentsemantic.ResolveResponse
	resolveErr      error
	reads           []semantic.ReadRequest
	resolves        []attachmentsemantic.ResolveRequest
	bearers         []string
}

func (stub *recordViewRuntimeStub) read(_ context.Context, bearer string, request semantic.ReadRequest) (semantic.ReadResponse, error) {
	stub.bearers = append(stub.bearers, bearer)
	stub.reads = append(stub.reads, request)
	return stub.readResponse, stub.readErr
}

func (stub *recordViewRuntimeStub) resolve(_ context.Context, bearer string, request attachmentsemantic.ResolveRequest) (attachmentsemantic.ResolveResponse, error) {
	stub.bearers = append(stub.bearers, bearer)
	stub.resolves = append(stub.resolves, request)
	return stub.resolveResponse, stub.resolveErr
}

func recordViewTestService(t *testing.T, stub *recordViewRuntimeStub) *Service {
	t.Helper()
	base := &fakeRuntime{}
	base.ready.Store(true)
	service := newTestService(t, base)
	client, err := NewRuntimeRecordViewClient(stub.read, stub.resolve)
	if err != nil {
		t.Fatal(err)
	}
	service.recordView = client
	return service
}

func recordViewRequest(path string) *http.Request {
	request := httptest.NewRequest(http.MethodGet, path, nil)
	request.Header.Set("Authorization", "Bearer end-user")
	return request
}

func recordViewReceipts() semantic.Receipts {
	return semantic.Receipts{ProtocolVersion: "1.0", CapabilityVersion: semantic.CapabilityName, CatalogRevision: 42}
}

func TestRecordViewIDRoutePreservesCRMProjectionAndBoundedDecoration(t *testing.T) {
	stub := &recordViewRuntimeStub{
		readResponse: semantic.ReadResponse{
			RecordID: "record-1",
			Root: semantic.Record{ObjectID: "WorkItem", Fields: []semantic.Field{
				{Name: "Active", Value: semantic.Value{Kind: semantic.ValueBoolean, Boolean: rvPtr(false)}},
				{Name: "Amount", Value: semantic.Value{Kind: semantic.ValueDecimal, Decimal: &semantic.Decimal{Coefficient: "0", Scale: 2}}},
				{Name: "Count", Value: semantic.Value{Kind: semantic.ValueInteger, Integer: rvPtr(int64(0))}},
				{Name: "Date", Value: semantic.Value{Kind: semantic.ValueDate, Date: rvPtr("2026-07-22")}},
				{Name: "DocumentLink", Value: semantic.Value{Kind: semantic.ValueString, String: rvPtr(`https://example.my.salesforce.com/sfc/p/00D/a/ABCDEF123456/secret`)}},
				{Name: "Empty", Value: semantic.Value{Kind: semantic.ValueString, String: rvPtr("")}},
				{Name: "OwnerId", Value: semantic.Value{Kind: semantic.ValueReference, Reference: rvPtr("user-1")}},
				{Name: "Summary", Value: semantic.Value{Kind: semantic.ValueString, Null: true}},
				{Name: "When", Value: semantic.Value{Kind: semantic.ValueDateTime, DateTime: rvPtr("2026-07-22T10:11:12Z")}},
			}},
			ReferenceDisplays: []semantic.ReferenceDisplay{{
				SourceFieldID: "OwnerId", RelationshipID: "Owner", TargetObjectID: "User", TargetRecordID: "user-1", DisplayName: "Ada Example",
			}},
			AttachmentSourceFields: []semantic.AttachmentSourceField{{SourceFieldID: "DocumentLink", ResolverID: "legacy_attachment"}},
			Receipts:               recordViewReceipts(),
		},
		resolveResponse: attachmentsemantic.ResolveResponse{
			Results:  []attachmentsemantic.SourceResult{{Index: 0, Outcome: attachmentsemantic.SourceResolved, FileID: "file-1", FileName: "Example.pdf"}},
			Receipts: attachmentSourceReceipts(),
		},
	}
	recorder := httptest.NewRecorder()
	recordViewTestService(t, stub).ServeHTTP(recorder, recordViewRequest("/services/data/v63.0/sobjects/WorkItem/record-1"))
	want := `{"Active":false,"Amount":0.00,"Count":0,"Date":"2026-07-22","DocumentLink":"\u003ca href=\"/services/data/v63.0/files/file-1/download\" target=\"_blank\" rel=\"noopener noreferrer\"\u003eExample.pdf\u003c/a\u003e","Empty":"","Id":"record-1","Owner":{"Id":"user-1","Name":"Ada Example","attributes":{"type":"User"}},"OwnerId":"user-1","Summary":null,"When":"2026-07-22T10:11:12Z","attributes":{"type":"WorkItem","url":"/services/data/v63.0/sobjects/WorkItem/record-1"}}`
	if recorder.Code != http.StatusOK || recorder.Body.String() != want {
		t.Fatalf("status=%d body=%s", recorder.Code, recorder.Body.String())
	}
	if len(stub.reads) != 1 || len(stub.resolves) != 1 || len(stub.bearers) != 2 ||
		stub.reads[0].Projection != semantic.ProjectionEnrichedView || stub.reads[0].Selector.RecordID != "record-1" ||
		stub.resolves[0].ResolverID != "legacy_attachment" || len(stub.resolves[0].Sources) != 1 || stub.resolves[0].Sources[0].SourceFieldID != "DocumentLink" ||
		stub.resolves[0].Sources[0].SourceValue != "ABCDEF123456" || stub.resolves[0].Sources[0].SourceValueOffset != 46 ||
		stub.resolves[0].MinCatalogRevision == nil || *stub.resolves[0].MinCatalogRevision != 42 {
		t.Fatalf("read=%#v resolve=%#v bearers=%#v", stub.reads, stub.resolves, stub.bearers)
	}
	if strings.Contains(recorder.Body.String(), "Hidden") {
		t.Fatal("absent/FLS-hidden field was projected")
	}
}

func TestRecordViewExternalFieldRouteUsesRootOnlyAndNoResolver(t *testing.T) {
	stub := &recordViewRuntimeStub{readResponse: semantic.ReadResponse{
		RecordID: "record-2",
		Root: semantic.Record{ObjectID: "Account", Fields: []semantic.Field{
			{Name: "ExternalKey", Value: semantic.Value{Kind: semantic.ValueString, String: rvPtr("key/1")}},
			{Name: "Id", Value: semantic.Value{Kind: semantic.ValueString, String: rvPtr("record-2")}},
		}}, Receipts: recordViewReceipts(),
	}}
	recorder := httptest.NewRecorder()
	recordViewTestService(t, stub).ServeHTTP(recorder, recordViewRequest("/services/data/v62.0/sobjects/Account/ExternalKey/key%2F1"))
	want := `{"ExternalKey":"key/1","Id":"record-2","attributes":{"type":"Account","url":"/services/data/v62.0/sobjects/Account/record-2"}}`
	if recorder.Code != http.StatusOK || recorder.Body.String() != want || len(stub.reads) != 1 || len(stub.resolves) != 0 {
		t.Fatalf("status=%d reads=%#v resolves=%#v body=%s", recorder.Code, stub.reads, stub.resolves, recorder.Body.String())
	}
	request := stub.reads[0]
	if request.Projection != semantic.ProjectionRoot || request.Selector.Kind != semantic.SelectorFieldEqual || request.Selector.FieldID != "ExternalKey" || request.Selector.FieldValue != "key/1" {
		t.Fatalf("request = %#v", request)
	}
}

func TestRuntimeRecordViewClientRejectsInvalidRuntimePayloads(t *testing.T) {
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	readRequest := semantic.ReadRequest{
		ObjectID: "Account", Selector: semantic.Selector{Kind: semantic.SelectorRecordID, RecordID: "record-1"}, Projection: semantic.ProjectionRoot,
	}
	readClient, err := NewRuntimeRecordViewClient(func(context.Context, string, semantic.ReadRequest) (semantic.ReadResponse, error) {
		return semantic.ReadResponse{
			RecordID: "other-record", Root: semantic.Record{ObjectID: "Account", Fields: []semantic.Field{{
				Name: "Id", Value: semantic.Value{Kind: semantic.ValueString, String: rvPtr("other-record")},
			}}}, Receipts: recordViewReceipts(),
		}, nil
	}, (&recordViewRuntimeStub{}).resolve)
	if err != nil {
		t.Fatal(err)
	}
	if _, err := readClient.Read(ctx, "end-user", readRequest); !isRecordViewInternalFailure(err) {
		t.Fatalf("invalid Runtime read = %v, want internal contract failure", err)
	}

	resolveRequest := attachmentsemantic.ResolveRequest{
		ParentObjectID: "Account", ParentRecordID: "record-1", ResolverID: "legacy_attachment",
		Sources: []attachmentsemantic.Source{{SourceFieldID: "Link", SourceValue: "one", SourceValueOffset: 0}, {SourceFieldID: "Link", SourceValue: "two", SourceValueOffset: 4}},
	}
	resolveClient, err := NewRuntimeRecordViewClient((&recordViewRuntimeStub{}).read, func(context.Context, string, attachmentsemantic.ResolveRequest) (attachmentsemantic.ResolveResponse, error) {
		return attachmentsemantic.ResolveResponse{Results: []attachmentsemantic.SourceResult{
			{Index: 1, Outcome: attachmentsemantic.SourceNotFound},
			{Index: 0, Outcome: attachmentsemantic.SourceNotFound},
		}, Receipts: attachmentSourceReceipts()}, nil
	})
	if err != nil {
		t.Fatal(err)
	}
	if _, err := resolveClient.ResolveAttachmentSourceProofs(ctx, "end-user", resolveRequest); !isAttachmentSourceInternalFailure(err) {
		t.Fatalf("reordered Runtime attachment response = %v, want internal contract failure", err)
	}
}

func TestRecordViewRedactsOriginalLinksWhenAttachmentCorrelationIsMalformed(t *testing.T) {
	alpha := "https://example.invalid/sfc/p/00D/a/AAAAAAAAAAAA/secret"
	beta := "https://example.invalid/sfc/p/00D/a/BBBBBBBBBBBB/secret"
	stub := &recordViewRuntimeStub{
		readResponse: semantic.ReadResponse{
			RecordID: "record-1", Root: semantic.Record{ObjectID: "WorkItem", Fields: []semantic.Field{
				{Name: "Alpha", Value: semantic.Value{Kind: semantic.ValueString, String: &alpha}},
				{Name: "Beta", Value: semantic.Value{Kind: semantic.ValueString, String: &beta}},
			}},
			AttachmentSourceFields: []semantic.AttachmentSourceField{
				{SourceFieldID: "Alpha", ResolverID: "legacy_attachment"},
				{SourceFieldID: "Beta", ResolverID: "legacy_attachment"},
			}, Receipts: recordViewReceipts(),
		},
		resolveResponse: attachmentsemantic.ResolveResponse{Results: []attachmentsemantic.SourceResult{
			{Index: 1, Outcome: attachmentsemantic.SourceResolved, FileID: "file-beta", FileName: "Beta.pdf"},
			{Index: 0, Outcome: attachmentsemantic.SourceResolved, FileID: "file-alpha", FileName: "Alpha.pdf"},
		}, Receipts: attachmentSourceReceipts()},
	}
	recorder := httptest.NewRecorder()
	recordViewTestService(t, stub).ServeHTTP(recorder, recordViewRequest("/services/data/v63.0/sobjects/WorkItem/record-1"))
	if recorder.Code != http.StatusOK || len(stub.resolves) != 1 ||
		strings.Contains(recorder.Body.String(), "AAAAAAAAAAAA") || strings.Contains(recorder.Body.String(), "BBBBBBBBBBBB") ||
		strings.Contains(recorder.Body.String(), "/files/file-") {
		t.Fatalf("status=%d resolves=%d body=%s", recorder.Code, len(stub.resolves), recorder.Body.String())
	}
}

func TestRecordViewPreservesMissingForbiddenAndMetadataErrors(t *testing.T) {
	tests := []struct {
		name, path string
		err        error
		status     int
		body       string
	}{
		{name: "missing or RLS masked", path: "/services/data/v63.0/sobjects/Account/record-1", err: &semantic.Failure{Category: semantic.FailureMissing}, status: 404, body: `[{"errorCode":"NOT_FOUND","message":"Record not found"}]`},
		{name: "object read denied", path: "/services/data/v63.0/sobjects/Account/record-1", err: &semantic.Failure{Category: semantic.FailureForbidden}, status: 403, body: `[{"errorCode":"FORBIDDEN","message":"Insufficient access"}]`},
		{name: "unknown object", path: "/services/data/v63.0/sobjects/Unknown/record-1", err: &semantic.Failure{Category: semantic.FailureInvalidRequest, InvalidComponent: semantic.InvalidComponentObjectID}, status: 404, body: `[{"errorCode":"NOT_FOUND","message":"Object not found"}]`},
		{name: "unknown lookup field", path: "/services/data/v63.0/sobjects/Account/Absent/key", err: &semantic.Failure{Category: semantic.FailureInvalidRequest, InvalidComponent: semantic.InvalidComponentField}, status: 400, body: `[{"errorCode":"INVALID_FIELD","message":"Field 'Absent' does not exist on object 'Account'"}]`},
		{name: "overlong object retains object grammar", path: "/services/data/v63.0/sobjects/Unknown/record-1", err: &semantic.Failure{Category: semantic.FailureResourceExhausted, LimitKind: semantic.LimitObjectID}, status: 404, body: `[{"errorCode":"NOT_FOUND","message":"Object not found"}]`},
		{name: "overlong lookup field retains field grammar", path: "/services/data/v63.0/sobjects/Account/Absent/key", err: &semantic.Failure{Category: semantic.FailureResourceExhausted, LimitKind: semantic.LimitFieldID}, status: 400, body: `[{"errorCode":"INVALID_FIELD","message":"Field 'Absent' does not exist on object 'Account'"}]`},
		{name: "overlong record retains masked grammar", path: "/services/data/v63.0/sobjects/Account/record-1", err: &semantic.Failure{Category: semantic.FailureResourceExhausted, LimitKind: semantic.LimitRecordID}, status: 404, body: `[{"errorCode":"NOT_FOUND","message":"Record not found"}]`},
	}
	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			stub := &recordViewRuntimeStub{readErr: test.err}
			recorder := httptest.NewRecorder()
			recordViewTestService(t, stub).ServeHTTP(recorder, recordViewRequest(test.path))
			if recorder.Code != test.status || recorder.Body.String() != test.body {
				t.Fatalf("status=%d body=%s", recorder.Code, recorder.Body.String())
			}
		})
	}
}

func TestRecordViewRouteDoesNotCaptureSiblingCRMOperations(t *testing.T) {
	for _, path := range []string{
		"/services/data/v63.0/sobjects/Account/describe",
		"/services/data/v63.0/sobjects/Account/listviews",
		"/services/data/v63.0/sobjects/Account/quickActions",
		"/services/data/v63.0/sobjects/Account/describe/layouts",
		"/services/data/v63.0/sobjects/Account/listviews/list-view-1",
		// FlowInterview has a dedicated CRM handler for this exact GET shape;
		// it must not be captured by the generic record-view capability.
		"/services/data/v63.0/sobjects/FlowInterview/interview-1",
		"/services/data/v63.0/sobjects/_System_File/file-1/download",
		"/services/data/v63.0/sobjects/ContentVersion/file-1/VersionData",
		"/services/data/v64.0/sobjects/Account/record-1",
	} {
		if route, ok := matchRecordViewRoute(path); ok {
			t.Fatalf("%s matched as %#v", path, route)
		}
	}
}

func TestRecordViewServiceDoesNotCallRuntimeForDedicatedCRMIDRead(t *testing.T) {
	stub := &recordViewRuntimeStub{}
	recorder := httptest.NewRecorder()
	recordViewTestService(t, stub).ServeHTTP(recorder, recordViewRequest("/services/data/v63.0/sobjects/FlowInterview/interview-1"))
	if recorder.Code != http.StatusNotFound || len(stub.reads) != 0 || len(stub.resolves) != 0 {
		t.Fatalf("status=%d reads=%d resolves=%d", recorder.Code, len(stub.reads), len(stub.resolves))
	}
}

func TestRecordViewGETOwnershipDoesNotCaptureMutationMethods(t *testing.T) {
	calls := 0
	service, _ := newMutationService(t, func(_ context.Context, _ string, request mutationsemantic.Request) (mutationsemantic.Response, error) {
		calls++
		return successfulMutationResponse(t, request), nil
	})
	stub := &recordViewRuntimeStub{}
	recordView, err := NewRuntimeRecordViewClient(stub.read, stub.resolve)
	if err != nil {
		t.Fatal(err)
	}
	service.recordView = recordView
	recorder := httptest.NewRecorder()
	service.ServeHTTP(recorder, mutationHTTPRequest(http.MethodPatch, "/services/data/v63.0/sobjects/Account/record-1", `{"Name":"Updated"}`))
	if recorder.Code != http.StatusNoContent || calls != 1 || len(stub.reads) != 0 {
		t.Fatalf("status=%d mutation calls=%d record reads=%d body=%s", recorder.Code, calls, len(stub.reads), recorder.Body.String())
	}
}

func TestRecordViewUnresolvedAttachmentOutcomesFailClosed(t *testing.T) {
	anchor := `<a href="https://example.invalid/sfc/p/00D/a/AAAAAAAAAAAA/secret">Original</a>`
	bare := `https://example.invalid/sfc/p/00D/a/BBBBBBBBBBBB/secret`
	stub := &recordViewRuntimeStub{
		readResponse: semantic.ReadResponse{
			RecordID: "record-1", Root: semantic.Record{ObjectID: "WorkItem", Fields: []semantic.Field{
				{Name: "Anchor", Value: semantic.Value{Kind: semantic.ValueString, String: &anchor}},
				{Name: "Bare", Value: semantic.Value{Kind: semantic.ValueString, String: &bare}},
			}},
			AttachmentSourceFields: []semantic.AttachmentSourceField{
				{SourceFieldID: "Anchor", ResolverID: "legacy_attachment"},
				{SourceFieldID: "Bare", ResolverID: "legacy_attachment"},
			}, Receipts: recordViewReceipts(),
		},
		resolveResponse: attachmentsemantic.ResolveResponse{
			Results: []attachmentsemantic.SourceResult{
				{Index: 0, Outcome: attachmentsemantic.SourceUnavailable},
				{Index: 1, Outcome: attachmentsemantic.SourceNotFound},
			}, Receipts: attachmentSourceReceipts(),
		},
	}
	recorder := httptest.NewRecorder()
	recordViewTestService(t, stub).ServeHTTP(recorder, recordViewRequest("/services/data/v63.0/sobjects/WorkItem/record-1"))
	if recorder.Code != http.StatusOK || strings.Contains(recorder.Body.String(), "AAAAAAAAAAAA") || strings.Contains(recorder.Body.String(), "BBBBBBBBBBBB") ||
		strings.Count(recorder.Body.String(), "File unavailable") != 2 || len(stub.resolves) != 1 {
		t.Fatalf("status=%d resolves=%d body=%s", recorder.Code, len(stub.resolves), recorder.Body.String())
	}
}

func TestRecordViewDoesNotTurnResolverDiversityIntoFollowupFanout(t *testing.T) {
	first := "https://example.invalid/sfc/p/00D/a/AAAAAAAAAAAA/secret"
	second := "https://example.invalid/sfc/p/00D/a/BBBBBBBBBBBB/secret"
	third := "https://example.invalid/sfc/p/00D/a/CCCCCCCCCCCC/secret"
	stub := &recordViewRuntimeStub{readResponse: semantic.ReadResponse{
		RecordID: "record-1", Root: semantic.Record{ObjectID: "WorkItem", Fields: []semantic.Field{
			{Name: "First", Value: semantic.Value{Kind: semantic.ValueString, String: &first}},
			{Name: "Second", Value: semantic.Value{Kind: semantic.ValueString, String: &second}},
			{Name: "Third", Value: semantic.Value{Kind: semantic.ValueString, String: &third}},
		}},
		AttachmentSourceFields: []semantic.AttachmentSourceField{
			{SourceFieldID: "First", ResolverID: "resolver_a"},
			{SourceFieldID: "Second", ResolverID: "resolver_b"},
			{SourceFieldID: "Third", ResolverID: "resolver_c"},
		}, Receipts: recordViewReceipts(),
	}}
	recorder := httptest.NewRecorder()
	recordViewTestService(t, stub).ServeHTTP(recorder, recordViewRequest("/services/data/v63.0/sobjects/WorkItem/record-1"))
	if recorder.Code != http.StatusOK || len(stub.resolves) != 0 || strings.Contains(recorder.Body.String(), "AAAAAAAAAAAA") ||
		strings.Contains(recorder.Body.String(), "BBBBBBBBBBBB") || strings.Contains(recorder.Body.String(), "CCCCCCCCCCCC") {
		t.Fatalf("status=%d resolves=%d body=%s", recorder.Code, len(stub.resolves), recorder.Body.String())
	}
}

func TestRecordViewUnparseableBoundAttachmentFailsClosedWithoutRuntime(t *testing.T) {
	raw := "https://storage.internal.example/tenant/private-object"
	stub := &recordViewRuntimeStub{readResponse: semantic.ReadResponse{
		RecordID: "record-1", Root: semantic.Record{ObjectID: "WorkItem", Fields: []semantic.Field{{
			Name: "Link", Value: semantic.Value{Kind: semantic.ValueString, String: &raw},
		}}},
		AttachmentSourceFields: []semantic.AttachmentSourceField{{SourceFieldID: "Link", ResolverID: "legacy_attachment"}},
		Receipts:               recordViewReceipts(),
	}}
	recorder := httptest.NewRecorder()
	recordViewTestService(t, stub).ServeHTTP(recorder, recordViewRequest("/services/data/v63.0/sobjects/WorkItem/record-1"))
	if recorder.Code != http.StatusOK || len(stub.resolves) != 0 || strings.Contains(recorder.Body.String(), "storage.internal.example") ||
		!strings.Contains(recorder.Body.String(), "File unavailable") {
		t.Fatalf("status=%d resolves=%d body=%s", recorder.Code, len(stub.resolves), recorder.Body.String())
	}
}

func TestRecordViewResolverFailureFailsClosedAndCancellationPropagates(t *testing.T) {
	stub := &recordViewRuntimeStub{
		readResponse: semantic.ReadResponse{
			RecordID: "record-1",
			Root: semantic.Record{ObjectID: "WorkItem", Fields: []semantic.Field{
				{Name: "Link", Value: semantic.Value{Kind: semantic.ValueString, String: rvPtr("https://example.invalid/sfc/p/00D/a/ABCDEF123456/secret")}},
			}},
			AttachmentSourceFields: []semantic.AttachmentSourceField{{SourceFieldID: "Link", ResolverID: "legacy_attachment"}}, Receipts: recordViewReceipts(),
		},
		resolveErr: errors.New("resolver unavailable"),
	}
	recorder := httptest.NewRecorder()
	recordViewTestService(t, stub).ServeHTTP(recorder, recordViewRequest("/services/data/v63.0/sobjects/WorkItem/record-1"))
	if recorder.Code != http.StatusOK || strings.Contains(recorder.Body.String(), "example.invalid") || !strings.Contains(recorder.Body.String(), "File unavailable") || len(stub.resolves) != 1 {
		t.Fatalf("status=%d resolves=%d body=%s", recorder.Code, len(stub.resolves), recorder.Body.String())
	}

	t.Run("canceled before Runtime entry is rejected locally", func(t *testing.T) {
		preCanceled := &recordViewRuntimeStub{}
		request := recordViewRequest("/services/data/v63.0/sobjects/WorkItem/record-1")
		ctx, cancel := context.WithCancel(request.Context())
		cancel()
		recorder := httptest.NewRecorder()
		recordViewTestService(t, preCanceled).ServeHTTP(recorder, request.WithContext(ctx))
		if len(preCanceled.reads) != 0 {
			t.Fatalf("pre-canceled request reached Runtime: %#v", preCanceled.reads)
		}
	})

	t.Run("cancellation during Runtime execution propagates", func(t *testing.T) {
		started := make(chan struct{}, 1)
		observed := make(chan error, 1)
		runtimeResult := make(chan error, 1)
		client, err := NewRuntimeRecordViewClient(func(ctx context.Context, _ string, _ semantic.ReadRequest) (semantic.ReadResponse, error) {
			started <- struct{}{}
			<-ctx.Done()
			observed <- ctx.Err()
			return semantic.ReadResponse{}, ctx.Err()
		}, (&recordViewRuntimeStub{}).resolve)
		if err != nil {
			t.Fatal(err)
		}
		parent, cancel := context.WithCancel(context.Background())
		ctx, timeout := context.WithTimeout(parent, time.Second)
		defer timeout()
		request := semantic.ReadRequest{ObjectID: "WorkItem", Selector: semantic.Selector{Kind: semantic.SelectorRecordID, RecordID: "record-1"}, Projection: semantic.ProjectionRoot}
		go func() {
			_, err := client.Read(ctx, "end-user", request)
			runtimeResult <- err
		}()
		select {
		case <-started:
		case <-time.After(time.Second):
			t.Fatal("Runtime call did not start")
		}
		cancel()
		select {
		case err := <-observed:
			if !errors.Is(err, context.Canceled) {
				t.Fatalf("Runtime context error = %v", err)
			}
		case <-time.After(time.Second):
			t.Fatal("cancellation did not reach Runtime port")
		}
		if err := <-runtimeResult; !errors.Is(err, context.Canceled) {
			t.Fatalf("Runtime result = %v", err)
		}
	})
}

func TestParseRecordAttachmentSourceCarriesRawParentFieldByteOffset(t *testing.T) {
	// The characters before href deliberately occupy more bytes than runes.
	// The Runtime proof applies to the raw parent-field bytes, so a rune index
	// would identify the wrong substring and must never be sent.
	raw := `<span title="漢字"><a href="https://example.invalid/sfc/p/00D/a/ABCDEF123456/secret">Document</a></span>`
	parsed, ok := parseRecordAttachmentSource("LegacyLink__c", "content_distribution", raw)
	if !ok {
		t.Fatal("expected CRM attachment URL to parse")
	}
	if parsed.sourceValue != "ABCDEF123456" || parsed.sourceValueOffset != uint32(strings.Index(raw, "ABCDEF123456")) {
		t.Fatalf("parsed source = %#v, want raw byte offset %d", parsed, strings.Index(raw, "ABCDEF123456"))
	}
}

func isRecordViewInternalFailure(err error) bool {
	var failure *semantic.Failure
	return errors.As(err, &failure) && failure.Category == semantic.FailureInternal
}

func attachmentSourceReceipts() attachmentsemantic.Receipts {
	return attachmentsemantic.Receipts{ProtocolVersion: "1.0", CapabilityVersion: attachmentsemantic.CapabilityName, CatalogRevision: 42}
}

func isAttachmentSourceInternalFailure(err error) bool {
	var failure *attachmentsemantic.Failure
	return errors.As(err, &failure) && failure.Category == attachmentsemantic.FailureInternal
}

func rvPtr[T any](value T) *T { return &value }
