package sfcrmappservice

import (
	"bytes"
	"context"
	"errors"
	"io"
	"mime/multipart"
	"net/http"
	"net/http/httptest"
	"strings"
	"sync"
	"sync/atomic"
	"testing"
	"time"

	"github.com/pingcap-inc/nexuscrm-api-host/runtimegrpc"
	commonsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/commonv1"
	filessemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/filesv1"
	querysemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/queryv1"
	accesssemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/recordaccessv1"
	mutationsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/recordmutationv1"
)

type fakeRecordFileUpload struct {
	mu        sync.Mutex
	chunks    [][]byte
	sendErr   error
	response  filessemantic.CreateResponse
	closeErr  error
	cancelled atomic.Bool
}

func (upload *fakeRecordFileUpload) Send(data []byte) error {
	upload.mu.Lock()
	defer upload.mu.Unlock()
	if upload.sendErr != nil {
		return upload.sendErr
	}
	upload.chunks = append(upload.chunks, append([]byte(nil), data...))
	return nil
}

func (upload *fakeRecordFileUpload) CloseAndRecv() (filessemantic.CreateResponse, error) {
	return upload.response, upload.closeErr
}

func (upload *fakeRecordFileUpload) Cancel() { upload.cancelled.Store(true) }

type fakeRecordFileDownload struct {
	mu        sync.Mutex
	chunks    []filessemantic.OpenChunk
	finalErr  error
	cancelled atomic.Bool
}

func (download *fakeRecordFileDownload) Recv() (filessemantic.OpenChunk, error) {
	download.mu.Lock()
	defer download.mu.Unlock()
	if len(download.chunks) > 0 {
		chunk := download.chunks[0]
		download.chunks = download.chunks[1:]
		return chunk, nil
	}
	if download.finalErr != nil {
		err := download.finalErr
		download.finalErr = nil
		return filessemantic.OpenChunk{}, err
	}
	return filessemantic.OpenChunk{}, io.EOF
}

func (download *fakeRecordFileDownload) Cancel() { download.cancelled.Store(true) }

type fakeRecordFilesRuntime struct {
	mu sync.Mutex

	beginCalls  int
	openCalls   int
	deleteCalls int
	bearer      string
	header      filessemantic.CreateHeader
	openRequest filessemantic.OpenRequest
	deleteReq   filessemantic.DeleteRequest

	upload         RuntimeFileUpload
	beginErr       error
	download       RuntimeFileDownload
	openErr        error
	deleteResponse filessemantic.DeleteResponse
	deleteErr      error
}

func (runtime *fakeRecordFilesRuntime) Begin(
	_ context.Context,
	bearer string,
	header filessemantic.CreateHeader,
) (RuntimeFileUpload, error) {
	runtime.mu.Lock()
	defer runtime.mu.Unlock()
	runtime.beginCalls++
	runtime.bearer, runtime.header = bearer, header
	return runtime.upload, runtime.beginErr
}

func (runtime *fakeRecordFilesRuntime) Open(
	_ context.Context,
	bearer string,
	request filessemantic.OpenRequest,
) (RuntimeFileDownload, error) {
	runtime.mu.Lock()
	defer runtime.mu.Unlock()
	runtime.openCalls++
	runtime.bearer, runtime.openRequest = bearer, request
	return runtime.download, runtime.openErr
}

func (runtime *fakeRecordFilesRuntime) Delete(
	_ context.Context,
	bearer string,
	request filessemantic.DeleteRequest,
) (filessemantic.DeleteResponse, error) {
	runtime.mu.Lock()
	defer runtime.mu.Unlock()
	runtime.deleteCalls++
	runtime.bearer, runtime.deleteReq = bearer, request
	return runtime.deleteResponse, runtime.deleteErr
}

func validFileReceipts() filessemantic.Receipts {
	return filessemantic.Receipts{
		ProtocolVersion: "1.0", CapabilityVersion: filessemantic.CapabilityName, CatalogRevision: 41,
	}
}

func newRecordFilesTestService(t *testing.T, files *fakeRecordFilesRuntime) *Service {
	t.Helper()
	return newRecordFilesServiceWithPorts(t, files.Begin, files.Open, files.Delete)
}

func newRecordFilesServiceWithPorts(
	t *testing.T,
	begin RuntimeBeginFileCreateFunc,
	open RuntimeOpenFileFunc,
	deleteFile RuntimeDeleteFileFunc,
) *Service {
	t.Helper()
	service, err := NewService(ServiceConfig{
		RuntimeEvaluate: func(context.Context, string, accesssemantic.Request) (accesssemantic.Response, error) {
			return accesssemantic.Response{}, nil
		},
		RuntimeQuery: func(context.Context, string, querysemantic.Request) (querysemantic.Response, error) {
			return querysemantic.Response{}, nil
		},
		RuntimeHistoryQuery: func(context.Context, string, querysemantic.HistoryRequest) (querysemantic.HistoryResponse, error) {
			return querysemantic.HistoryResponse{}, nil
		},
		RuntimeReady:           func() bool { return true },
		RuntimeMetrics:         func() runtimegrpc.RuntimeClientMetrics { return runtimegrpc.RuntimeClientMetrics{} },
		RuntimeBeginFileCreate: begin,
		RuntimeOpenFile:        open,
		RuntimeDeleteFile:      deleteFile,
		RequestTimeout:         time.Second,
		MaxRequestBytes:        30 * 1024 * 1024,
	})
	if err != nil {
		t.Fatal(err)
	}
	return service
}

func recordFileUploadRequest(t *testing.T, route, fileName string, content []byte, fields map[string]string) *http.Request {
	t.Helper()
	var body bytes.Buffer
	writer := multipart.NewWriter(&body)
	for name, value := range fields {
		if err := writer.WriteField(name, value); err != nil {
			t.Fatal(err)
		}
	}
	part, err := writer.CreateFormFile("file", fileName)
	if err != nil {
		t.Fatal(err)
	}
	if _, err := part.Write(content); err != nil {
		t.Fatal(err)
	}
	if err := writer.Close(); err != nil {
		t.Fatal(err)
	}
	request := httptest.NewRequest(http.MethodPost, route, &body)
	request.Header.Set("Content-Type", writer.FormDataContentType())
	request.Header.Set("Authorization", "Bearer user-secret")
	return request
}

func TestRecordFileUploadOwnsCRMProjectionAndStreamsBoundedChunks(t *testing.T) {
	content := bytes.Repeat([]byte("a"), filessemantic.MaxChunkBytes*2+17)
	upload := &fakeRecordFileUpload{response: filessemantic.CreateResponse{
		FileID: "file-1", FileName: "proof.txt", Size: uint64(len(content)), ContentType: "text/plain; charset=utf-8",
		Receipts: validFileReceipts(),
	}}
	runtime := &fakeRecordFilesRuntime{upload: upload}
	request := recordFileUploadRequest(t, "/services/data/v63.0/record-files", "proof.txt", content, map[string]string{
		fileUploadFieldParentID: "record-1", fileUploadFieldParentObjectAPIName: "Account",
		fileUploadFieldAttachmentKind: "record.attachment",
	})
	request.Header.Set(crmMutationIdempotencyHeader, "stable-upload")
	recorder := httptest.NewRecorder()

	newRecordFilesTestService(t, runtime).ServeHTTP(recorder, request)

	wantID, err := mutationCommandID([]string{"stable-upload"})
	if err != nil {
		t.Fatal(err)
	}
	if recorder.Code != http.StatusCreated ||
		recorder.Body.String() != `{"data":{"DownloadUrl":"/services/data/v63.0/files/file-1/download","Id":"file-1","Mime":"text/plain; charset=utf-8","Name":"proof.txt","Size":245777}}` {
		t.Fatalf("status=%d body=%q", recorder.Code, recorder.Body.String())
	}
	if runtime.beginCalls != 1 || runtime.bearer != "user-secret" {
		t.Fatalf("calls=%d bearer=%q", runtime.beginCalls, runtime.bearer)
	}
	if runtime.header.IdempotencyKey != wantID || runtime.header.ParentObjectID != "Account" ||
		runtime.header.ParentRecordID != "record-1" || runtime.header.AttachmentKind != "record.attachment" ||
		runtime.header.ContentLength != uint64(len(content)) {
		t.Fatalf("header=%+v", runtime.header)
	}
	if len(upload.chunks) != 3 || len(upload.chunks[0]) != filessemantic.MaxChunkBytes ||
		len(upload.chunks[1]) != filessemantic.MaxChunkBytes || len(upload.chunks[2]) != 17 {
		t.Fatalf("chunk sizes=%v", []int{len(upload.chunks[0]), len(upload.chunks[1]), len(upload.chunks[2])})
	}
	if !upload.cancelled.Load() {
		t.Fatal("upload stream was not released")
	}
}

func TestRecordFileUploadRejectsUnsafeOrIncompleteInputBeforeRuntime(t *testing.T) {
	tests := []struct {
		name     string
		fileName string
		content  []byte
		fields   map[string]string
		want     string
	}{
		{
			name: "missing parent", fileName: "proof.txt", content: []byte("safe"),
			fields: map[string]string{}, want: "parentId and parentObjectApiName are required",
		},
		{
			name: "extension", fileName: "proof.exe", content: []byte("safe"),
			fields: map[string]string{fileUploadFieldParentID: "record-1", fileUploadFieldParentObjectAPIName: "Account"},
			want:   "File type '.exe' not allowed",
		},
		{
			name: "active content", fileName: "proof.txt", content: []byte("<!doctype html><script>alert(1)</script>"),
			fields: map[string]string{fileUploadFieldParentID: "record-1", fileUploadFieldParentObjectAPIName: "Account"},
			want:   "File content type not allowed",
		},
	}
	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			runtime := &fakeRecordFilesRuntime{}
			recorder := httptest.NewRecorder()
			newRecordFilesTestService(t, runtime).ServeHTTP(
				recorder,
				recordFileUploadRequest(t, "/services/data/v63.0/files", test.fileName, test.content, test.fields),
			)
			if recorder.Code != http.StatusBadRequest || !strings.Contains(recorder.Body.String(), test.want) {
				t.Fatalf("status=%d body=%q", recorder.Code, recorder.Body.String())
			}
			if runtime.beginCalls != 0 {
				t.Fatalf("Runtime calls=%d", runtime.beginCalls)
			}
		})
	}
}

func TestRecordFileUploadEnforcesConfiguredRequestBoundBeforeRuntime(t *testing.T) {
	runtime := &fakeRecordFilesRuntime{}
	service := newRecordFilesTestService(t, runtime)
	service.maxRequestBytes = 128
	request := recordFileUploadRequest(t, "/services/data/v63.0/files", "proof.txt", bytes.Repeat([]byte("a"), 1024), map[string]string{
		fileUploadFieldParentID: "record-1", fileUploadFieldParentObjectAPIName: "Account",
	})
	recorder := httptest.NewRecorder()

	service.ServeHTTP(recorder, request)

	if recorder.Code != http.StatusRequestEntityTooLarge || runtime.beginCalls != 0 {
		t.Fatalf("status=%d calls=%d body=%q", recorder.Code, runtime.beginCalls, recorder.Body.String())
	}
}

func TestRecordFileDownloadStreamsAuthorizedContentAndHardensHeaders(t *testing.T) {
	receipts := validFileReceipts()
	download := &fakeRecordFileDownload{chunks: []filessemantic.OpenChunk{
		{
			FileName: "../report\".html", ContentType: "text/html", TotalSize: 5,
			Data: []byte("he"), Receipts: &receipts,
		},
		{FileName: "../report\".html", ContentType: "text/html", TotalSize: 5, Data: []byte("llo")},
	}}
	runtime := &fakeRecordFilesRuntime{download: download}
	request := httptest.NewRequest(http.MethodGet, "/services/data/v62.0/sobjects/_System_File/file-1/download", nil)
	request.Header.Set("Authorization", "Bearer user-secret")
	recorder := httptest.NewRecorder()

	newRecordFilesTestService(t, runtime).ServeHTTP(recorder, request)

	if recorder.Code != http.StatusOK || recorder.Body.String() != "hello" ||
		recorder.Header().Get("Content-Type") != "application/octet-stream" ||
		recorder.Header().Get("Content-Length") != "5" ||
		strings.ContainsAny(recorder.Header().Get("Content-Disposition"), "\r\n") {
		t.Fatalf("status=%d headers=%v body=%q", recorder.Code, recorder.Header(), recorder.Body.String())
	}
	if runtime.openCalls != 1 || runtime.openRequest.FileID != "file-1" || runtime.bearer != "user-secret" {
		t.Fatalf("calls=%d request=%+v bearer=%q", runtime.openCalls, runtime.openRequest, runtime.bearer)
	}
	if !download.cancelled.Load() {
		t.Fatal("download stream was not released")
	}
}

func TestRecordFileDownloadRejectsMissingReceiptBeforeStartingHTTPResponse(t *testing.T) {
	runtime := &fakeRecordFilesRuntime{download: &fakeRecordFileDownload{
		chunks: []filessemantic.OpenChunk{{
			FileName: "report.txt", ContentType: "text/plain", TotalSize: 2, Data: []byte("ok"),
		}},
	}}
	service := newRecordFilesTestService(t, runtime)
	request := httptest.NewRequest(http.MethodGet, "/services/data/v63.0/files/file-1/download", nil)
	request.Header.Set("Authorization", "Bearer user-secret")
	recorder := httptest.NewRecorder()

	service.ServeHTTP(recorder, request)

	if recorder.Code != http.StatusInternalServerError || service.successes.Load() != 0 ||
		service.failures.Load() != 1 {
		t.Fatalf(
			"status=%d successes=%d failures=%d body=%q",
			recorder.Code,
			service.successes.Load(),
			service.failures.Load(),
			recorder.Body.String(),
		)
	}
}

func TestRecordFileDownloadIncompleteOrMixedStreamClosesShortResponse(t *testing.T) {
	receipts := validFileReceipts()
	for _, test := range []struct {
		name   string
		chunks []filessemantic.OpenChunk
	}{
		{
			name: "truncated",
			chunks: []filessemantic.OpenChunk{{
				FileName: "report.txt", ContentType: "text/plain", TotalSize: 5,
				Data: []byte("he"), Receipts: &receipts,
			}},
		},
		{
			name: "metadata drift",
			chunks: []filessemantic.OpenChunk{
				{
					FileName: "report.txt", ContentType: "text/plain", TotalSize: 5,
					Data: []byte("he"), Receipts: &receipts,
				},
				{
					FileName: "other.txt", ContentType: "text/plain", TotalSize: 5,
					Data: []byte("llo"),
				},
			},
		},
		{
			name: "cumulative size overrun",
			chunks: []filessemantic.OpenChunk{
				{
					FileName: "report.txt", ContentType: "text/plain", TotalSize: 5,
					Data: []byte("he"), Receipts: &receipts,
				},
				{
					FileName: "report.txt", ContentType: "text/plain", TotalSize: 5,
					Data: []byte("lloo"),
				},
			},
		},
	} {
		t.Run(test.name, func(t *testing.T) {
			runtime := &fakeRecordFilesRuntime{
				download: &fakeRecordFileDownload{chunks: test.chunks},
			}
			service := newRecordFilesTestService(t, runtime)
			server := httptest.NewServer(service)
			defer server.Close()

			request, err := http.NewRequest(
				http.MethodGet,
				server.URL+"/services/data/v63.0/files/file-1/download",
				nil,
			)
			if err != nil {
				t.Fatal(err)
			}
			request.Header.Set("Authorization", "Bearer user-secret")
			response, err := server.Client().Do(request)
			if err != nil {
				t.Fatal(err)
			}
			body, readErr := io.ReadAll(response.Body)
			_ = response.Body.Close()

			if response.StatusCode != http.StatusOK ||
				!errors.Is(readErr, io.ErrUnexpectedEOF) ||
				string(body) != "he" ||
				service.successes.Load() != 0 ||
				service.failures.Load() != 1 {
				t.Fatalf(
					"status=%d readErr=%v body=%q successes=%d failures=%d",
					response.StatusCode,
					readErr,
					body,
					service.successes.Load(),
					service.failures.Load(),
				)
			}
		})
	}
}

func TestRecordFileDeleteAndMissingFailurePreserveCRMWireSemantics(t *testing.T) {
	t.Run("delete", func(t *testing.T) {
		runtime := &fakeRecordFilesRuntime{deleteResponse: filessemantic.DeleteResponse{Receipts: validFileReceipts()}}
		request := httptest.NewRequest(http.MethodDelete, "/services/data/v61.0/files/file-1", nil)
		request.Header.Set("Authorization", "Bearer user-secret")
		recorder := httptest.NewRecorder()

		newRecordFilesTestService(t, runtime).ServeHTTP(recorder, request)

		if recorder.Code != http.StatusNoContent || recorder.Body.Len() != 0 ||
			runtime.deleteCalls != 1 || runtime.deleteReq.FileID != "file-1" {
			t.Fatalf("status=%d calls=%d request=%+v body=%q", recorder.Code, runtime.deleteCalls, runtime.deleteReq, recorder.Body.String())
		}
	})
	t.Run("missing", func(t *testing.T) {
		runtime := &fakeRecordFilesRuntime{openErr: &commonsemantic.Failure{Category: commonsemantic.FailureMissing}}
		request := httptest.NewRequest(http.MethodGet, "/services/data/v63.0/files/missing/download", nil)
		request.Header.Set("Authorization", "Bearer user-secret")
		recorder := httptest.NewRecorder()

		newRecordFilesTestService(t, runtime).ServeHTTP(recorder, request)

		if recorder.Code != http.StatusNotFound || recorder.Body.String() != `[{"errorCode":"NOT_FOUND","message":"File not found"}]` {
			t.Fatalf("status=%d body=%q", recorder.Code, recorder.Body.String())
		}
	})
}

func TestRecordFilesFailClosedForAuthorizationDrainAndStreamFailure(t *testing.T) {
	t.Run("authorization", func(t *testing.T) {
		runtime := &fakeRecordFilesRuntime{}
		request := httptest.NewRequest(http.MethodGet, "/services/data/v63.0/files/file-1/download", nil)
		recorder := httptest.NewRecorder()
		newRecordFilesTestService(t, runtime).ServeHTTP(recorder, request)
		if recorder.Code != http.StatusUnauthorized || runtime.openCalls != 0 {
			t.Fatalf("status=%d calls=%d body=%q", recorder.Code, runtime.openCalls, recorder.Body.String())
		}
	})
	t.Run("drain", func(t *testing.T) {
		runtime := &fakeRecordFilesRuntime{}
		service := newRecordFilesTestService(t, runtime)
		service.BeginDrain()
		request := httptest.NewRequest(http.MethodDelete, "/services/data/v63.0/files/file-1", nil)
		request.Header.Set("Authorization", "Bearer user-secret")
		recorder := httptest.NewRecorder()
		service.ServeHTTP(recorder, request)
		if recorder.Code != http.StatusServiceUnavailable || runtime.deleteCalls != 0 {
			t.Fatalf("status=%d calls=%d body=%q", recorder.Code, runtime.deleteCalls, recorder.Body.String())
		}
	})
	t.Run("stream failure", func(t *testing.T) {
		stream := &fakeRecordFileDownload{finalErr: &commonsemantic.Failure{Category: commonsemantic.FailureUnavailable}}
		runtime := &fakeRecordFilesRuntime{download: stream}
		request := httptest.NewRequest(http.MethodGet, "/services/data/v63.0/files/file-1/download", nil)
		request.Header.Set("Authorization", "Bearer user-secret")
		recorder := httptest.NewRecorder()
		newRecordFilesTestService(t, runtime).ServeHTTP(recorder, request)
		if recorder.Code != http.StatusServiceUnavailable || !stream.cancelled.Load() {
			t.Fatalf("status=%d cancelled=%v body=%q", recorder.Code, stream.cancelled.Load(), recorder.Body.String())
		}
	})
}

func TestRecordFilesRouteOwnershipPreservesGenericRecordRead(t *testing.T) {
	for _, version := range []string{"v59.0", "v60.0", "v61.0", "v62.0", "v63.0"} {
		for _, test := range []struct {
			method string
			path   string
			kind   recordFilesRouteKind
		}{
			{http.MethodPost, "/services/data/" + version + "/files", recordFilesRouteUpload},
			{http.MethodPost, "/services/data/" + version + "/record-files", recordFilesRouteUpload},
			{http.MethodGet, "/services/data/" + version + "/files/file-1/download", recordFilesRouteDownload},
			{http.MethodDelete, "/services/data/" + version + "/files/file-1", recordFilesRouteDelete},
			{http.MethodGet, "/services/data/" + version + "/sobjects/_System_File/file-1/download", recordFilesRouteDownload},
			{http.MethodDelete, "/services/data/" + version + "/sobjects/_System_File/file-1", recordFilesRouteDelete},
		} {
			route, _, ok := matchRecordFilesRoute(test.path, test.method)
			if !ok || route.kind != test.kind {
				t.Fatalf("%s %s = %+v, %v", test.method, test.path, route, ok)
			}
		}
	}
	if _, _, ok := matchRecordFilesRoute("/services/data/v63.0/sobjects/_System_File/file-1", http.MethodGet); ok {
		t.Fatal("generic _System_File record read was captured by the Files adapter")
	}
	if _, ok := matchRecordViewRoute("/services/data/v63.0/sobjects/_System_File/file-1"); !ok {
		t.Fatal("generic _System_File record read lost its existing owner")
	}
}

func TestServiceRoutesSystemFileDescribeDeleteToFilesBeforeGenericMutation(t *testing.T) {
	files := &fakeRecordFilesRuntime{
		deleteResponse: filessemantic.DeleteResponse{Receipts: validFileReceipts()},
	}
	service := newRecordFilesTestService(t, files)
	var mutationCalls atomic.Uint64
	mutation, err := NewRuntimeMutationClient(func(
		_ context.Context,
		_ string,
		request mutationsemantic.Request,
	) (mutationsemantic.Response, error) {
		mutationCalls.Add(1)
		return successfulMutationResponse(t, request), nil
	})
	if err != nil {
		t.Fatal(err)
	}
	service.mutation = mutation

	request := httptest.NewRequest(
		http.MethodDelete,
		"/services/data/v63.0/sobjects/_System_File/describe",
		nil,
	)
	request.Header.Set("Authorization", "Bearer user-secret")
	recorder := httptest.NewRecorder()
	service.ServeHTTP(recorder, request)

	if recorder.Code != http.StatusNoContent || recorder.Body.Len() != 0 {
		t.Fatalf("status=%d body=%q", recorder.Code, recorder.Body.String())
	}
	if files.deleteCalls != 1 || files.deleteReq.FileID != "describe" {
		t.Fatalf("Files calls=%d request=%+v", files.deleteCalls, files.deleteReq)
	}
	if mutationCalls.Load() != 0 {
		t.Fatalf("generic mutation received Files-owned delete %d times", mutationCalls.Load())
	}
}

func TestRecordFilesConstructionRejectsPartialCapabilityInstallation(t *testing.T) {
	base := ServiceConfig{
		RuntimeEvaluate: func(context.Context, string, accesssemantic.Request) (accesssemantic.Response, error) {
			return accesssemantic.Response{}, nil
		},
		RuntimeQuery: func(context.Context, string, querysemantic.Request) (querysemantic.Response, error) {
			return querysemantic.Response{}, nil
		},
		RuntimeHistoryQuery: func(context.Context, string, querysemantic.HistoryRequest) (querysemantic.HistoryResponse, error) {
			return querysemantic.HistoryResponse{}, nil
		},
		RuntimeReady: func() bool { return true }, RuntimeMetrics: func() runtimegrpc.RuntimeClientMetrics {
			return runtimegrpc.RuntimeClientMetrics{}
		},
		RequestTimeout: time.Second, MaxRequestBytes: 1024,
	}
	runtime := &fakeRecordFilesRuntime{}
	for _, mutate := range []func(*ServiceConfig){
		func(config *ServiceConfig) { config.RuntimeBeginFileCreate = runtime.Begin },
		func(config *ServiceConfig) { config.RuntimeOpenFile = runtime.Open },
		func(config *ServiceConfig) { config.RuntimeDeleteFile = runtime.Delete },
		func(config *ServiceConfig) {
			config.RuntimeBeginFileCreate, config.RuntimeOpenFile = runtime.Begin, runtime.Open
		},
	} {
		config := base
		mutate(&config)
		if service, err := NewService(config); err == nil || service != nil {
			t.Fatalf("NewService(%+v) = %#v, %v; want partial Files ports rejected", config, service, err)
		}
	}
	base.RuntimeBeginFileCreate, base.RuntimeOpenFile, base.RuntimeDeleteFile = runtime.Begin, runtime.Open, runtime.Delete
	base.MaxRequestBytes = maxRecordFileUploadBytes
	if service, err := NewService(base); err == nil || service != nil {
		t.Fatalf("NewService with undersized Files body bound = %#v, %v; want rejected", service, err)
	}
}

func TestRecordFilesRemainUnclaimedWithoutAppReleaseActivation(t *testing.T) {
	runtime := &fakeRuntime{}
	runtime.ready.Store(true)
	request := httptest.NewRequest(http.MethodGet, "/services/data/v63.0/files/file-1/download", nil)
	request.Header.Set("Authorization", "Bearer user-secret")
	recorder := httptest.NewRecorder()

	newTestService(t, runtime).ServeHTTP(recorder, request)

	if recorder.Code != http.StatusNotFound {
		t.Fatalf("status=%d body=%q", recorder.Code, recorder.Body.String())
	}
}

func TestRecordFilesPropagatesRequestCancellationToRuntime(t *testing.T) {
	var sawCancellation atomic.Bool
	started := make(chan struct{})
	runtime := &fakeRecordFilesRuntime{}
	runtime.openErr = errors.New("uninitialized")
	runtimeOpen := func(ctx context.Context, _ string, _ filessemantic.OpenRequest) (RuntimeFileDownload, error) {
		close(started)
		<-ctx.Done()
		sawCancellation.Store(errors.Is(ctx.Err(), context.Canceled))
		return nil, &commonsemantic.Failure{Category: commonsemantic.FailureCanceled}
	}
	service := newRecordFilesTestService(t, runtime)
	service.files.open = runtimeOpen
	ctx, cancel := context.WithCancel(context.Background())
	request := httptest.NewRequest(http.MethodGet, "/services/data/v63.0/files/file-1/download", nil).WithContext(ctx)
	request.Header.Set("Authorization", "Bearer user-secret")
	recorder := httptest.NewRecorder()
	done := make(chan struct{})
	go func() {
		defer close(done)
		service.ServeHTTP(recorder, request)
	}()
	<-started
	cancel()
	<-done

	if recorder.Code != 499 || !sawCancellation.Load() {
		t.Fatalf("status=%d saw cancellation=%v body=%q", recorder.Code, sawCancellation.Load(), recorder.Body.String())
	}
}
