package runtimeapi

import (
	"context"
	"errors"
	"testing"
	"time"

	"github.com/nexuscrm/metadata/catalogsnapshot"
	"github.com/nexuscrm/shared/pkg/models"
	commonsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/commonv1"
	mailboxauthorizationsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/mailboxauthorizationv1"
	"github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/permissionstatev1"
	"github.com/pingcap-inc/nexuscrm-contract/wire-go/mapping"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

type memoryMailboxHandleStore struct {
	record mailboxAuthorizationHandle
	mints  int
}

func (store *memoryMailboxHandleStore) Mint(
	_ context.Context,
	record mailboxAuthorizationHandle,
	ttl time.Duration,
) error {
	now := time.Now().UTC()
	record.CreatedAt, record.ExpiresAt = now, now.Add(ttl)
	store.record, store.mints = record, store.mints+1
	return nil
}

func (store *memoryMailboxHandleStore) ConsumeAuthorized(
	ctx context.Context,
	digest string,
	authorize func(context.Context, mailboxAuthorizationHandle) error,
) (bool, error) {
	now := time.Now().UTC()
	if store.record.HandleDigest != digest || !store.record.ExpiresAt.After(now) {
		return false, errMailboxAuthorizationDenied
	}
	if authorize == nil {
		return false, errMailboxAuthorizationUnavailable
	}
	if err := authorize(ctx, store.record); err != nil {
		return false, err
	}
	duplicate := store.record.ConsumedAt != nil
	if !duplicate {
		store.record.ConsumedAt = &now
	}
	return duplicate, nil
}

type mailboxPermissionStub struct {
	allowed          bool
	transactionalErr error
	calls            *int
}

func (stub mailboxPermissionStub) AuthorizeMailboxSubject(
	_ context.Context,
	_ permissionstatev1.Subject,
	floor permissionstatev1.Version,
	_ MailboxPermissionRequirement,
) error {
	if stub.calls != nil {
		*stub.calls++
	}
	if floor.Validate() != nil {
		return errMailboxAuthorizationUnavailable
	}
	if !stub.allowed {
		return errMailboxAuthorizationDenied
	}
	return nil
}

func (stub mailboxPermissionStub) AuthorizeMailboxSubjectWithinTransaction(
	ctx context.Context,
	subject permissionstatev1.Subject,
	floor permissionstatev1.Version,
	requiredPermission MailboxPermissionRequirement,
) error {
	if stub.transactionalErr != nil {
		return stub.transactionalErr
	}
	return stub.AuthorizeMailboxSubject(ctx, subject, floor, requiredPermission)
}

type mailboxSessionStub struct{ session mailboxAuthorizationSession }

func (stub mailboxSessionStub) ReadMailboxSession(
	context.Context,
	string,
	string,
) (mailboxAuthorizationSession, error) {
	return stub.session, nil
}

type failingMailboxHandleStore struct{ err error }

func (store failingMailboxHandleStore) Mint(
	context.Context,
	mailboxAuthorizationHandle,
	time.Duration,
) error {
	return store.err
}

func (store failingMailboxHandleStore) ConsumeAuthorized(
	context.Context,
	string,
	func(context.Context, mailboxAuthorizationHandle) error,
) (bool, error) {
	return false, store.err
}

func TestMailboxAuthorizationBeginMintsSessionAndRevisionBoundHandle(t *testing.T) {
	store := &memoryMailboxHandleStore{}
	subject, _ := permissionstatev1.NewSubject("user-1", "profile-1")
	server, err := NewMailboxAuthorizationServer(
		store,
		mailboxPermissionStub{allowed: true},
		mailboxSessionStub{},
		MailboxPermissionRequirement{CustomPermission: "SendRecordEmail"},
	)
	if err != nil {
		t.Fatal(err)
	}
	ctx := delegatedMailboxContext(t, subject)
	request := mailboxauthorizationsemantic.Request{
		Operation: mailboxauthorizationsemantic.OperationBegin,
	}
	wireRequest, err := mapping.ToWireAuthorizeConnectedMailboxRequest(ctx, request)
	if err != nil {
		t.Fatal(err)
	}
	wireResponse, err := server.AuthorizeConnectedMailbox(ctx, wireRequest)
	if err != nil {
		t.Fatal(err)
	}
	response, err := mapping.FromWireAuthorizeConnectedMailboxResponse(request, wireResponse)
	if err != nil {
		t.Fatal(err)
	}
	if response.AuthorizedSubjectID != "user-1" ||
		response.ReauthorizationHandle == "" || store.mints != 1 ||
		store.record.AppInstallationID != "01900000-0000-7000-8000-000000000001" ||
		store.record.SessionID != "session-1" || store.record.AuthEpoch != 7 ||
		store.record.PermissionFloor.Revision() != 11 ||
		store.record.CatalogRevision != 41 || store.record.SecurityEpoch != 9 {
		t.Fatalf("response/record = %#v / %#v", response, store.record)
	}
}

func TestMailboxAuthorizationAdmissionBindsMetadataFreeCatalogReceipts(t *testing.T) {
	current := validCatalogIntegrationBindingView(41)
	catalog := &catalogConsumerViewTestEngine{integrationView: current}
	admission, err := NewMailboxAuthorizationAdmission(
		t.Context(),
		MailboxAuthorizationSelection{
			OrgID: current.OrgID, AppInstallationID: current.AppInstallationID,
			WorkloadID: current.AuthorizedWorkloadID,
		},
		catalog,
	)
	if err != nil {
		t.Fatal(err)
	}
	if !catalog.integrationGetBounded {
		t.Fatal("mailbox Catalog admission read did not carry a deadline")
	}
	contexts := map[string]context.Context{
		"delegated": context.WithValue(t.Context(), trustedCallContextKey{}, TrustedCall{
			orgID: current.OrgID, principalID: "user-1", sessionID: "session-1",
			callerWorkloadID:  current.AuthorizedWorkloadID,
			appInstallationID: current.AppInstallationID,
			capabilities:      []string{mailboxauthorizationsemantic.CapabilityName}, securityEpoch: 3,
			user: models.UserSession{ID: "user-1", ProfileID: "profile-1"},
		}),
		"workload": context.WithValue(t.Context(), trustedWorkloadCallContextKey{}, TrustedWorkloadCall{
			orgID: current.OrgID, callerWorkloadID: current.AuthorizedWorkloadID,
			capability: mailboxauthorizationsemantic.CapabilityName, securityEpoch: 3,
		}),
	}
	for name, ctx := range contexts {
		t.Run(name, func(t *testing.T) {
			bound, err := admission.bind(ctx)
			if err != nil {
				t.Fatal(err)
			}
			scope, ok := runtimeExecutionScopeFromContext(bound)
			if !ok || scope.view != nil || scope.orgID != current.OrgID ||
				scope.appInstallationID != current.AppInstallationID ||
				scope.workloadID != current.AuthorizedWorkloadID ||
				scope.capability != mailboxauthorizationsemantic.CapabilityName ||
				scope.receipts.CatalogRevision != 41 || scope.receipts.SecurityEpoch != 3 {
				t.Fatalf("mailbox admission scope = %#v / %v", scope, ok)
			}
		})
	}
}

func TestMailboxAuthorizationAdmissionPreservesCatalogReadFailure(t *testing.T) {
	current := validCatalogIntegrationBindingView(41)
	cause := errors.New("catalog read probe")
	_, err := NewMailboxAuthorizationAdmission(
		t.Context(),
		MailboxAuthorizationSelection{
			OrgID: current.OrgID, AppInstallationID: current.AppInstallationID,
			WorkloadID: current.AuthorizedWorkloadID,
		},
		&catalogConsumerViewTestEngine{integrationGetError: cause},
	)
	if !errors.Is(err, cause) {
		t.Fatalf("NewMailboxAuthorizationAdmission() error = %v, want wrapped Catalog cause", err)
	}
}

func TestMailboxAuthorizationAdmissionReconcilesSecurityEpoch(t *testing.T) {
	current := validCatalogIntegrationBindingView(41)
	admission, err := NewMailboxAuthorizationAdmission(
		t.Context(),
		MailboxAuthorizationSelection{
			OrgID: current.OrgID, AppInstallationID: current.AppInstallationID,
			WorkloadID: current.AuthorizedWorkloadID,
		},
		&catalogConsumerViewTestEngine{integrationView: current},
	)
	if err != nil {
		t.Fatal(err)
	}
	trusted := TrustedWorkloadCall{
		orgID: current.OrgID, callerWorkloadID: current.AuthorizedWorkloadID,
		capability:    mailboxauthorizationsemantic.CapabilityName,
		securityEpoch: current.Receipts.SecurityEpoch,
	}
	oldCtx := context.WithValue(t.Context(), trustedWorkloadCallContextKey{}, trusted)
	if err := admission.ReconcileSecurityEpoch(current.Receipts.SecurityEpoch + 1); err != nil {
		t.Fatal(err)
	}
	if _, err := admission.bind(oldCtx); err == nil {
		t.Fatal("old security epoch remained admitted after reconcile")
	} else {
		var failure *mailboxauthorizationsemantic.Failure
		if !errors.As(err, &failure) ||
			failure.Category != commonsemantic.FailureStaleState ||
			failure.RequiredRevision != trusted.securityEpoch+1 ||
			failure.ServedRevision != trusted.securityEpoch {
			t.Fatalf("old security epoch failure = %#v / %v", failure, err)
		}
	}
	trusted.securityEpoch++
	newCtx := context.WithValue(t.Context(), trustedWorkloadCallContextKey{}, trusted)
	admitted, err := admission.bind(newCtx)
	if err != nil {
		t.Fatal(err)
	}
	scope, ok := runtimeExecutionScopeFromContext(admitted)
	if !ok || scope.receipts.SecurityEpoch != trusted.securityEpoch {
		t.Fatalf("reconciled mailbox scope = %#v / %v", scope, ok)
	}
}

func TestMailboxAuthorizationDenialCreatesNoHandle(t *testing.T) {
	store := &memoryMailboxHandleStore{}
	subject, _ := permissionstatev1.NewSubject("user-1", "profile-1")
	server, err := NewMailboxAuthorizationServer(
		store,
		mailboxPermissionStub{},
		mailboxSessionStub{},
		MailboxPermissionRequirement{CustomPermission: "SendRecordEmail"},
	)
	if err != nil {
		t.Fatal(err)
	}
	ctx := delegatedMailboxContext(t, subject)
	request := mailboxauthorizationsemantic.Request{
		Operation: mailboxauthorizationsemantic.OperationBegin,
	}
	wireRequest, err := mapping.ToWireAuthorizeConnectedMailboxRequest(ctx, request)
	if err != nil {
		t.Fatal(err)
	}
	_, err = server.AuthorizeConnectedMailbox(ctx, wireRequest)
	var failure *commonsemantic.Failure
	if !errors.As(mapping.FromPlatformStatusError(
		err,
		mailboxauthorizationsemantic.CapabilityName,
	), &failure) || failure.Category != commonsemantic.FailureForbidden || store.mints != 0 {
		t.Fatalf("denial = %#v, mints=%d", failure, store.mints)
	}
}

func TestMailboxAuthorizationRequiresCustomPermissionOnlyForBegin(t *testing.T) {
	subject, _ := permissionstatev1.NewSubject("user-1", "profile-1")
	for _, operation := range []mailboxauthorizationsemantic.Operation{
		mailboxauthorizationsemantic.OperationStatus,
		mailboxauthorizationsemantic.OperationDisconnect,
	} {
		t.Run(string(operation), func(t *testing.T) {
			permissionCalls := 0
			server, err := NewMailboxAuthorizationServer(
				&memoryMailboxHandleStore{},
				mailboxPermissionStub{calls: &permissionCalls},
				mailboxSessionStub{},
				MailboxPermissionRequirement{CustomPermission: "SendRecordEmail"},
			)
			if err != nil {
				t.Fatal(err)
			}
			ctx := delegatedMailboxContext(t, subject)
			request := mailboxauthorizationsemantic.Request{Operation: operation}
			wireRequest, err := mapping.ToWireAuthorizeConnectedMailboxRequest(ctx, request)
			if err != nil {
				t.Fatal(err)
			}
			if _, err := server.AuthorizeConnectedMailbox(ctx, wireRequest); err != nil {
				t.Fatalf("AuthorizeConnectedMailbox() error = %v", err)
			}
			if permissionCalls != 0 {
				t.Fatalf("permission checks = %d, want 0", permissionCalls)
			}
		})
	}
}

func TestMailboxAuthorizationPreservesCatalogStaleState(t *testing.T) {
	store := &memoryMailboxHandleStore{}
	subject, _ := permissionstatev1.NewSubject("user-1", "profile-1")
	server, err := NewMailboxAuthorizationServer(
		store,
		mailboxPermissionStub{allowed: true},
		mailboxSessionStub{},
		MailboxPermissionRequirement{CustomPermission: "SendRecordEmail"},
	)
	if err != nil {
		t.Fatal(err)
	}
	minimum := uint64(42)
	delegatedCtx := delegatedMailboxContext(t, subject)
	begin := mailboxauthorizationsemantic.Request{
		Operation:          mailboxauthorizationsemantic.OperationBegin,
		MinCatalogRevision: &minimum,
	}
	wireBegin, err := mapping.ToWireAuthorizeConnectedMailboxRequest(delegatedCtx, begin)
	if err != nil {
		t.Fatal(err)
	}
	_, err = server.AuthorizeConnectedMailbox(delegatedCtx, wireBegin)
	assertMailboxAuthorizationFailure(t, err, commonsemantic.FailureStaleState)
	if store.mints != 0 {
		t.Fatalf("stale begin minted %d handles", store.mints)
	}

	workloadCtx := workloadMailboxContext(t)
	reauthorize := mailboxauthorizationsemantic.ReauthorizeRequest{
		ReauthorizationHandle: "reauthorization-handle",
		MinCatalogRevision:    &minimum,
	}
	wireReauthorize, err := mapping.ToWireReauthorizeConnectedMailboxRequest(
		workloadCtx,
		reauthorize,
	)
	if err != nil {
		t.Fatal(err)
	}
	_, err = server.ReauthorizeConnectedMailbox(workloadCtx, wireReauthorize)
	assertMailboxAuthorizationFailure(t, err, commonsemantic.FailureStaleState)
}

func TestMailboxAuthorizationPreservesStorageCancellation(t *testing.T) {
	subject, _ := permissionstatev1.NewSubject("user-1", "profile-1")
	server, err := NewMailboxAuthorizationServer(
		failingMailboxHandleStore{err: context.Canceled},
		mailboxPermissionStub{allowed: true},
		mailboxSessionStub{},
		MailboxPermissionRequirement{CustomPermission: "SendRecordEmail"},
	)
	if err != nil {
		t.Fatal(err)
	}
	delegatedCtx := delegatedMailboxContext(t, subject)
	begin := mailboxauthorizationsemantic.Request{
		Operation: mailboxauthorizationsemantic.OperationBegin,
	}
	wireBegin, err := mapping.ToWireAuthorizeConnectedMailboxRequest(delegatedCtx, begin)
	if err != nil {
		t.Fatal(err)
	}
	if _, err := server.AuthorizeConnectedMailbox(delegatedCtx, wireBegin); status.Code(err) != codes.Canceled {
		t.Fatalf("begin cancellation code = %s, want Canceled", status.Code(err))
	}

	workloadCtx := workloadMailboxContext(t)
	reauthorize := mailboxauthorizationsemantic.ReauthorizeRequest{
		ReauthorizationHandle: "reauthorization-handle",
	}
	wireReauthorize, err := mapping.ToWireReauthorizeConnectedMailboxRequest(
		workloadCtx,
		reauthorize,
	)
	if err != nil {
		t.Fatal(err)
	}
	if _, err := server.ReauthorizeConnectedMailbox(
		workloadCtx,
		wireReauthorize,
	); status.Code(err) != codes.Canceled {
		t.Fatalf("reauthorization cancellation code = %s, want Canceled", status.Code(err))
	}
}

func TestMailboxReauthorizationRechecksCurrentSessionAndPermission(t *testing.T) {
	for _, tc := range []struct {
		name           string
		requirement    MailboxPermissionRequirement
		system, custom []string
	}{
		{"custom", MailboxPermissionRequirement{CustomPermission: "mail-access"}, nil, []string{"mail-access"}},
		{"system", MailboxPermissionRequirement{SystemPermission: "mail-access"}, []string{"mail-access"}, nil},
	} {
		t.Run(tc.name, func(t *testing.T) {

			store := &memoryMailboxHandleStore{}
			subject, _ := permissionstatev1.NewSubject("user-1", "profile-1")
			snapshot, err := permissionstatev1.NewEffectiveSnapshot(mailboxPermissionFloor(t, 11), tc.system, tc.custom)
			if err != nil {
				t.Fatal(err)
			}
			authorizer, err := newCurrentMailboxPermissionAuthorizer(effectiveSnapshotLoaderStub{snapshot: snapshot}, permissionFloorFencerStub{})
			if err != nil {
				t.Fatal(err)
			}
			server, err := NewMailboxAuthorizationServer(
				store,
				authorizer,
				mailboxSessionStub{session: mailboxAuthorizationSession{
					User:    models.UserSession{ID: "user-1", ProfileID: "profile-1"},
					Subject: subject, AuthEpoch: 7, PermissionFloor: mailboxPermissionFloor(t, 11),
				}},
				tc.requirement,
			)
			if err != nil {
				t.Fatal(err)
			}
			ctx := delegatedMailboxContext(t, subject)
			begin := mailboxauthorizationsemantic.Request{
				Operation: mailboxauthorizationsemantic.OperationBegin,
			}
			wireBegin, err := mapping.ToWireAuthorizeConnectedMailboxRequest(ctx, begin)
			if err != nil {
				t.Fatal(err)
			}
			wireStart, err := server.AuthorizeConnectedMailbox(ctx, wireBegin)
			if err != nil {
				t.Fatal(err)
			}
			start, err := mapping.FromWireAuthorizeConnectedMailboxResponse(begin, wireStart)
			if err != nil {
				t.Fatal(err)
			}
			workloadCtx := workloadMailboxContext(t)
			request := mailboxauthorizationsemantic.ReauthorizeRequest{
				ReauthorizationHandle: start.ReauthorizationHandle,
			}
			wireRequest, err := mapping.ToWireReauthorizeConnectedMailboxRequest(workloadCtx, request)
			if err != nil {
				t.Fatal(err)
			}
			wireResponse, err := server.ReauthorizeConnectedMailbox(workloadCtx, wireRequest)
			if err != nil {
				t.Fatal(err)
			}
			response, err := mapping.FromWireReauthorizeConnectedMailboxResponse(request, wireResponse)
			if err != nil || response.AuthorizedSubjectID != "user-1" || store.record.ConsumedAt == nil {
				t.Fatalf("response/record = %#v / %#v / %v", response, store.record, err)
			}
			if _, err := server.ReauthorizeConnectedMailbox(workloadCtx, wireRequest); err != nil {
				t.Fatalf("exact callback replay was not idempotent: %v", err)
			}
		})
	}
}

func TestMailboxReauthorizationRejectsForeignRuntimeScope(t *testing.T) {
	store := &memoryMailboxHandleStore{}
	subject, _ := permissionstatev1.NewSubject("user-1", "profile-1")
	now := time.Now().UTC()
	store.record = mailboxAuthorizationHandle{
		HandleDigest: digestMailboxAuthorizationHandle("reauthorization-handle"),
		OrgID:        "org-1", AppInstallationID: "01900000-0000-7000-8000-000000000001",
		AuthorizedSubjectID: "user-1", SessionID: "session-1", AuthEpoch: 7,
		PermissionFloor: mailboxPermissionFloor(t, 11),
		CatalogRevision: 41, SecurityEpoch: 9, ExpiresAt: now.Add(time.Minute),
		CreatedAt: now,
	}
	server, err := NewMailboxAuthorizationServer(
		store,
		mailboxPermissionStub{allowed: true},
		mailboxSessionStub{session: mailboxAuthorizationSession{
			User:    models.UserSession{ID: "user-1", ProfileID: "profile-1"},
			Subject: subject, AuthEpoch: 7, PermissionFloor: mailboxPermissionFloor(t, 11),
		}},
		MailboxPermissionRequirement{CustomPermission: "SendRecordEmail"},
	)
	if err != nil {
		t.Fatal(err)
	}
	ctx := workloadMailboxContext(t)
	scope, _ := runtimeExecutionScopeFromContext(ctx)
	scope.appInstallationID = "foreign-installation"
	ctx = context.WithValue(ctx, runtimeExecutionScopeContextKey{}, scope)
	request := mailboxauthorizationsemantic.ReauthorizeRequest{
		ReauthorizationHandle: "reauthorization-handle",
	}
	wireRequest, err := mapping.ToWireReauthorizeConnectedMailboxRequest(ctx, request)
	if err != nil {
		t.Fatal(err)
	}
	_, err = server.ReauthorizeConnectedMailbox(ctx, wireRequest)
	var failure *commonsemantic.Failure
	if !errors.As(mapping.FromPlatformStatusError(
		err,
		mailboxauthorizationsemantic.CapabilityName,
	), &failure) || failure.Category != commonsemantic.FailureForbidden ||
		store.record.ConsumedAt != nil {
		t.Fatalf("foreign scope = %#v, consumed=%v", failure, store.record.ConsumedAt)
	}
}

func TestMailboxReauthorizationRejectsChangedPermissionFloor(t *testing.T) {
	store := &memoryMailboxHandleStore{}
	subject, _ := permissionstatev1.NewSubject("user-1", "profile-1")
	now := time.Now().UTC()
	store.record = mailboxAuthorizationHandle{
		HandleDigest: digestMailboxAuthorizationHandle("reauthorization-handle"),
		OrgID:        "org-1", AppInstallationID: "01900000-0000-7000-8000-000000000001",
		AuthorizedSubjectID: "user-1", SessionID: "session-1", AuthEpoch: 7,
		PermissionFloor: mailboxPermissionFloor(t, 11),
		CatalogRevision: 41, SecurityEpoch: 9, ExpiresAt: now.Add(time.Minute),
		CreatedAt: now,
	}
	server, err := NewMailboxAuthorizationServer(
		store,
		mailboxPermissionStub{allowed: true},
		mailboxSessionStub{session: mailboxAuthorizationSession{
			User:    models.UserSession{ID: "user-1", ProfileID: "profile-1"},
			Subject: subject, AuthEpoch: 7, PermissionFloor: mailboxPermissionFloor(t, 12),
		}},
		MailboxPermissionRequirement{CustomPermission: "SendRecordEmail"},
	)
	if err != nil {
		t.Fatal(err)
	}
	ctx := workloadMailboxContext(t)
	request := mailboxauthorizationsemantic.ReauthorizeRequest{
		ReauthorizationHandle: "reauthorization-handle",
	}
	wireRequest, err := mapping.ToWireReauthorizeConnectedMailboxRequest(ctx, request)
	if err != nil {
		t.Fatal(err)
	}
	_, err = server.ReauthorizeConnectedMailbox(ctx, wireRequest)
	var failure *commonsemantic.Failure
	if !errors.As(mapping.FromPlatformStatusError(
		err,
		mailboxauthorizationsemantic.CapabilityName,
	), &failure) || failure.Category != commonsemantic.FailureUnavailable ||
		store.record.ConsumedAt != nil {
		t.Fatalf("changed floor = %#v, consumed=%v", failure, store.record.ConsumedAt)
	}
}

func TestMailboxReauthorizationFencesPermissionBeforeConsume(t *testing.T) {
	store := &memoryMailboxHandleStore{}
	subject, _ := permissionstatev1.NewSubject("user-1", "profile-1")
	now := time.Now().UTC()
	store.record = mailboxAuthorizationHandle{
		HandleDigest: digestMailboxAuthorizationHandle("reauthorization-handle"),
		OrgID:        "org-1", AppInstallationID: "01900000-0000-7000-8000-000000000001",
		AuthorizedSubjectID: "user-1", SessionID: "session-1", AuthEpoch: 7,
		PermissionFloor: mailboxPermissionFloor(t, 11),
		CatalogRevision: 41, SecurityEpoch: 9, ExpiresAt: now.Add(time.Minute),
		CreatedAt: now,
	}
	server, err := NewMailboxAuthorizationServer(
		store,
		mailboxPermissionStub{
			allowed: true, transactionalErr: errMailboxAuthorizationUnavailable,
		},
		mailboxSessionStub{session: mailboxAuthorizationSession{
			User:    models.UserSession{ID: "user-1", ProfileID: "profile-1"},
			Subject: subject, AuthEpoch: 7, PermissionFloor: mailboxPermissionFloor(t, 11),
		}},
		MailboxPermissionRequirement{CustomPermission: "SendRecordEmail"},
	)
	if err != nil {
		t.Fatal(err)
	}
	ctx := workloadMailboxContext(t)
	request := mailboxauthorizationsemantic.ReauthorizeRequest{
		ReauthorizationHandle: "reauthorization-handle",
	}
	wireRequest, err := mapping.ToWireReauthorizeConnectedMailboxRequest(ctx, request)
	if err != nil {
		t.Fatal(err)
	}
	_, err = server.ReauthorizeConnectedMailbox(ctx, wireRequest)
	assertMailboxAuthorizationFailure(t, err, commonsemantic.FailureUnavailable)
	if store.record.ConsumedAt != nil {
		t.Fatal("permission-fence failure consumed the callback handle")
	}
}

func TestMailboxReauthorizationClassifiesStoreOutageAsUnavailable(t *testing.T) {
	subject, _ := permissionstatev1.NewSubject("user-1", "profile-1")
	server, err := NewMailboxAuthorizationServer(
		failingMailboxHandleStore{err: errors.New("database unavailable")},
		mailboxPermissionStub{allowed: true},
		mailboxSessionStub{session: mailboxAuthorizationSession{
			User:    models.UserSession{ID: "user-1", ProfileID: "profile-1"},
			Subject: subject, AuthEpoch: 7, PermissionFloor: mailboxPermissionFloor(t, 11),
		}},
		MailboxPermissionRequirement{CustomPermission: "SendRecordEmail"},
	)
	if err != nil {
		t.Fatal(err)
	}
	ctx := workloadMailboxContext(t)
	request := mailboxauthorizationsemantic.ReauthorizeRequest{
		ReauthorizationHandle: "reauthorization-handle",
	}
	wireRequest, err := mapping.ToWireReauthorizeConnectedMailboxRequest(ctx, request)
	if err != nil {
		t.Fatal(err)
	}
	_, err = server.ReauthorizeConnectedMailbox(ctx, wireRequest)
	var failure *commonsemantic.Failure
	if !errors.As(mapping.FromPlatformStatusError(
		err,
		mailboxauthorizationsemantic.CapabilityName,
	), &failure) || failure.Category != commonsemantic.FailureUnavailable {
		t.Fatalf("store outage = %#v", failure)
	}
}

func delegatedMailboxContext(
	t *testing.T,
	subject permissionstatev1.Subject,
) context.Context {
	t.Helper()
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	t.Cleanup(cancel)
	trusted := TrustedCall{
		orgID: "org-1", principalID: "user-1", sessionID: "session-1",
		callerWorkloadID:  "integration-1",
		appInstallationID: "01900000-0000-7000-8000-000000000001",
		authEpoch:         7, securityEpoch: 9,
		user:    models.UserSession{ID: "user-1", ProfileID: "profile-1"},
		subject: subject, permissionFloor: mailboxPermissionFloor(t, 11),
	}
	ctx = context.WithValue(ctx, trustedCallContextKey{}, trusted)
	return context.WithValue(ctx, runtimeExecutionScopeContextKey{}, RuntimeExecutionScope{
		view: &catalogsnapshot.RuntimeMetadataView{}, orgID: "org-1",
		appInstallationID: "01900000-0000-7000-8000-000000000001",
		workloadID:        "integration-1", capability: mailboxauthorizationsemantic.CapabilityName,
		receipts: commonsemantic.Receipts{
			ProtocolVersion: "1.0", CatalogRevision: 41, SchemaGeneration: 3,
			EngineGeneration: 4, SecurityEpoch: 9,
		},
	})
}

func mailboxPermissionFloor(t *testing.T, revision uint64) permissionstatev1.Version {
	t.Helper()
	lineage, err := permissionstatev1.LineageFromBytes([]byte{
		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	})
	if err != nil {
		t.Fatal(err)
	}
	version, err := permissionstatev1.NewVersion(lineage, revision)
	if err != nil {
		t.Fatal(err)
	}
	return version
}

func assertMailboxAuthorizationFailure(
	t *testing.T,
	err error,
	want commonsemantic.FailureCategory,
) {
	t.Helper()
	var failure *commonsemantic.Failure
	if !errors.As(mapping.FromPlatformStatusError(
		err,
		mailboxauthorizationsemantic.CapabilityName,
	), &failure) || failure.Category != want {
		t.Fatalf("failure = %#v, want category %s (error %v)", failure, want, err)
	}
}

func workloadMailboxContext(t *testing.T) context.Context {
	t.Helper()
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	t.Cleanup(cancel)
	ctx = context.WithValue(ctx, trustedWorkloadCallContextKey{}, TrustedWorkloadCall{
		orgID: "org-1", callerWorkloadID: "integration-1",
		capability: mailboxauthorizationsemantic.CapabilityName, securityEpoch: 9,
	})
	return context.WithValue(ctx, runtimeExecutionScopeContextKey{}, RuntimeExecutionScope{
		view: &catalogsnapshot.RuntimeMetadataView{}, orgID: "org-1",
		appInstallationID: "01900000-0000-7000-8000-000000000001",
		workloadID:        "integration-1", capability: mailboxauthorizationsemantic.CapabilityName,
		receipts: commonsemantic.Receipts{
			ProtocolVersion: "1.0", CatalogRevision: 41, SchemaGeneration: 3,
			EngineGeneration: 4, SecurityEpoch: 9,
		},
	})
}
