//go:build unit

package service

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

	infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors"
	"github.com/Wei-Shaw/sub2api/internal/pkg/xai"
	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/require"
)

type grokCredentialPersistingRepo struct {
	*tokenRefreshAccountRepo
}

func TestClassifyGrokCredentialFailureBillingExhaustionIsTransient(t *testing.T) {
	account := expiredGrokOAuthAccountForCredentialTest(9901)
	for _, message := range []string{
		"Grok OAuth refresh failed: spending limit reached",
		"included free usage exhausted",
		"credits exhausted",
	} {
		class := classifyGrokCredentialFailure(account, errors.New(message))
		require.Equal(t, GrokCredentialReasonRefreshTransient, class.reason, message)
		require.True(t, class.transient, message)
		require.False(t, class.permanent, message)
	}
}

func (r *grokCredentialPersistingRepo) SetError(ctx context.Context, id int64, message string) error {
	if err := ctx.Err(); err != nil {
		return err
	}
	if err := r.tokenRefreshAccountRepo.SetError(ctx, id, message); err != nil {
		return err
	}
	if account := r.accountsByID[id]; account != nil {
		account.Status = StatusError
		account.Schedulable = false
		account.ErrorMessage = message
	}
	return nil
}

type grokCredentialProxyRepoStub struct {
	ProxyRepository
	proxy *Proxy
	err   error
}

func (r *grokCredentialProxyRepoStub) GetByID(context.Context, int64) (*Proxy, error) {
	return r.proxy, r.err
}

type grokCredentialBlockingRepo struct {
	*tokenRefreshAccountRepo
	setErrorStarted chan struct{}
	setTempStarted  chan struct{}
	onceError       sync.Once
	onceTemp        sync.Once
}

type grokCredentialCommitThenCancelRepo struct {
	*tokenRefreshAccountRepo
	returnErr error
}

type grokCredentialUncommittedDeadlineRepo struct {
	*tokenRefreshAccountRepo
}

func (r *grokCredentialUncommittedDeadlineRepo) SetGrokCredentialErrorIfMatch(
	context.Context,
	int64,
	GrokCredentialMutationSnapshot,
	string,
) (bool, error) {
	return false, context.DeadlineExceeded
}

func (r *grokCredentialUncommittedDeadlineRepo) SetGrokCredentialTempUnschedulableIfMatch(
	context.Context,
	int64,
	GrokCredentialMutationSnapshot,
	time.Time,
	string,
) (bool, error) {
	return false, context.DeadlineExceeded
}

func (r *grokCredentialCommitThenCancelRepo) SetGrokCredentialErrorIfMatch(
	ctx context.Context,
	id int64,
	_ GrokCredentialMutationSnapshot,
	reason string,
) (bool, error) {
	account := r.accountsByID[id]
	account.Status = StatusError
	account.Schedulable = false
	account.ErrorMessage = reason
	if r.returnErr != nil {
		return false, r.returnErr
	}
	<-ctx.Done()
	return false, ctx.Err()
}

func (r *grokCredentialCommitThenCancelRepo) SetGrokCredentialTempUnschedulableIfMatch(
	ctx context.Context,
	id int64,
	_ GrokCredentialMutationSnapshot,
	until time.Time,
	reason string,
) (bool, error) {
	account := r.accountsByID[id]
	account.TempUnschedulableUntil = &until
	account.TempUnschedulableReason = reason
	if r.returnErr != nil {
		return false, r.returnErr
	}
	<-ctx.Done()
	return false, ctx.Err()
}

func (r *grokCredentialBlockingRepo) SetError(ctx context.Context, _ int64, _ string) error {
	r.onceError.Do(func() { close(r.setErrorStarted) })
	<-ctx.Done()
	return ctx.Err()
}

func (r *grokCredentialBlockingRepo) SetTempUnschedulable(ctx context.Context, _ int64, _ time.Time, _ string) error {
	r.onceTemp.Do(func() { close(r.setTempStarted) })
	<-ctx.Done()
	return ctx.Err()
}

func (r *grokCredentialBlockingRepo) SetGrokCredentialErrorIfMatch(
	ctx context.Context,
	_ int64,
	_ GrokCredentialMutationSnapshot,
	_ string,
) (bool, error) {
	r.onceError.Do(func() { close(r.setErrorStarted) })
	<-ctx.Done()
	return false, ctx.Err()
}

func (r *grokCredentialBlockingRepo) SetGrokCredentialTempUnschedulableIfMatch(
	ctx context.Context,
	_ int64,
	_ GrokCredentialMutationSnapshot,
	_ time.Time,
	_ string,
) (bool, error) {
	r.onceTemp.Do(func() { close(r.setTempStarted) })
	<-ctx.Done()
	return false, ctx.Err()
}

type grokCredentialBlockingCache struct {
	GrokTokenCache
	deleteStarted chan struct{}
	releaseDelete chan struct{}
	once          sync.Once
	mu            sync.Mutex
	deleted       bool
}

type grokCredentialSequencedRepo struct {
	*tokenRefreshAccountRepo
	mu      sync.Mutex
	latest  *Account
	getCall int
}

type grokCredentialRereadFailureRepo struct {
	*tokenRefreshAccountRepo
	account *Account
	err     error
}

type grokCredentialCountingRefresher struct {
	refreshCalls int
}

func (r *grokCredentialCountingRefresher) CacheKey(account *Account) string {
	return GrokTokenCacheKey(account)
}

func (r *grokCredentialCountingRefresher) CanRefresh(*Account) bool { return true }

func (r *grokCredentialCountingRefresher) NeedsRefresh(*Account, time.Duration) bool { return true }

func (r *grokCredentialCountingRefresher) Refresh(context.Context, *Account) (map[string]any, error) {
	r.refreshCalls++
	return map[string]any{"access_token": "must-not-be-used"}, nil
}

func (r *grokCredentialRereadFailureRepo) GetByID(context.Context, int64) (*Account, error) {
	return r.account, r.err
}

func (r *grokCredentialSequencedRepo) GetByID(ctx context.Context, id int64) (*Account, error) {
	r.mu.Lock()
	defer r.mu.Unlock()
	r.getCall++
	if r.getCall > 1 && r.latest != nil {
		return r.latest, nil
	}
	return r.tokenRefreshAccountRepo.GetByID(ctx, id)
}

func (c *grokCredentialBlockingCache) DeleteAccessToken(ctx context.Context, _ string) error {
	c.once.Do(func() { close(c.deleteStarted) })
	select {
	case <-c.releaseDelete:
		c.mu.Lock()
		c.deleted = true
		c.mu.Unlock()
		return nil
	case <-ctx.Done():
		return ctx.Err()
	}
}

func (c *grokCredentialBlockingCache) wasDeleted() bool {
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.deleted
}

func TestUpstreamFailoverErrorNextAccountActionPreservesLegacyRetry(t *testing.T) {
	t.Parallel()

	require.True(t, (&UpstreamFailoverError{}).ShouldRetryNextAccount())
	require.True(t, (&UpstreamFailoverError{NextAccountAction: NextAccountRetry}).ShouldRetryNextAccount())
	require.False(t, (&UpstreamFailoverError{NextAccountAction: NextAccountStop}).ShouldRetryNextAccount())
}

func TestGetRequestCredentialMapsPermanentGrokOAuthFailureAndRedactsSecrets(t *testing.T) {
	gin.SetMode(gin.TestMode)
	account := expiredGrokOAuthAccountForCredentialTest(701)
	repo := &tokenRefreshAccountRepo{}
	repo.accountsByID = map[int64]*Account{account.ID: account}
	cache := &grokTokenCacheForProviderTest{lockResult: true}
	provider := NewGrokTokenProvider(repo, cache)
	provider.SetRefreshAPI(NewOAuthRefreshAPI(repo, cache), &tokenRefresherStub{
		err: infraerrors.New(http.StatusBadGateway, "GROK_OAUTH_TOKEN_REFRESH_FAILED", "invalid_grant access_token=leaked-access refresh_token=leaked-refresh"),
	})
	svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: provider}
	c, _ := gin.CreateTestContext(httptest.NewRecorder())

	token, kind, err := svc.getRequestCredential(context.Background(), c, account)
	require.Error(t, err)
	require.Empty(t, token)
	require.Empty(t, kind)

	var failoverErr *UpstreamFailoverError
	require.ErrorAs(t, err, &failoverErr)
	require.Equal(t, GatewayFailureStageAccountAuth, failoverErr.Stage)
	require.Equal(t, GatewayFailureScopeAccount, failoverErr.Scope)
	require.Equal(t, GrokCredentialReasonRevoked, failoverErr.Reason)
	require.True(t, failoverErr.ShouldRetryNextAccount())
	require.Equal(t, 0, failoverErr.StatusCode)
	require.Equal(t, http.StatusServiceUnavailable, failoverErr.ClientStatusCode)
	require.NotContains(t, err.Error(), "leaked-access")
	require.NotContains(t, err.Error(), "leaked-refresh")

	require.Equal(t, 1, repo.setErrorCalls)
	require.Zero(t, repo.setTempUnschedCalls)
	require.True(t, svc.isOpenAIAccountRuntimeBlocked(account))
	require.Equal(t, []string{GrokTokenCacheKey(account)}, cache.deletedKeys)
	require.NotContains(t, repo.lastErrorMessage, "leaked-access")
	require.NotContains(t, repo.lastErrorMessage, "leaked-refresh")

	rawEvents, ok := c.Get(OpsUpstreamErrorsKey)
	require.True(t, ok)
	events, ok := rawEvents.([]*OpsUpstreamErrorEvent)
	require.True(t, ok)
	require.Len(t, events, 1)
	require.Equal(t, string(GatewayFailureStageAccountAuth), events[0].Stage)
	require.Equal(t, string(GatewayFailureScopeAccount), events[0].Scope)
	require.Equal(t, string(GrokCredentialReasonRevoked), events[0].Reason)
	require.Zero(t, events[0].UpstreamStatusCode)
	require.NotContains(t, events[0].Message, "leaked-access")
	require.NotContains(t, events[0].Message, "leaked-refresh")
}

func TestGetRequestCredentialPermanentMappingsPersistAndInvalidate(t *testing.T) {
	gin.SetMode(gin.TestMode)
	tests := []struct {
		name        string
		prepare     func(*Account)
		refreshErr  error
		wantReason  GatewayFailureReason
		cachedToken string
	}{
		{
			name: "missing refresh credential",
			prepare: func(account *Account) {
				delete(account.Credentials, "refresh_token")
			},
			wantReason: GrokCredentialReasonMissing,
		},
		{
			name: "missing access credential",
			prepare: func(account *Account) {
				delete(account.Credentials, "access_token")
				account.Credentials["expires_at"] = time.Now().Add(2 * time.Hour).UTC().Format(time.RFC3339)
			},
			wantReason:  GrokCredentialReasonMissing,
			cachedToken: "stale-cached-access",
		},
		{
			name:       "explicit entitlement action required",
			prepare:    func(*Account) {},
			refreshErr: infraerrors.New(http.StatusForbidden, "GROK_OAUTH_ENTITLEMENT_DENIED", "access_denied"),
			wantReason: GrokCredentialReasonEntitlement,
		},
	}

	for index, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			account := expiredGrokOAuthAccountForCredentialTest(int64(720 + index))
			account.Status = StatusActive
			account.Schedulable = true
			tt.prepare(account)
			baseRepo := &tokenRefreshAccountRepo{}
			baseRepo.accountsByID = map[int64]*Account{account.ID: account}
			repo := &grokCredentialPersistingRepo{tokenRefreshAccountRepo: baseRepo}
			cache := &grokTokenCacheForProviderTest{lockResult: true, token: tt.cachedToken}
			provider := NewGrokTokenProvider(repo, cache)
			provider.SetRefreshAPI(NewOAuthRefreshAPI(repo, cache), &tokenRefresherStub{err: tt.refreshErr})
			svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: provider}
			c, _ := gin.CreateTestContext(httptest.NewRecorder())

			_, _, err := svc.getRequestCredential(context.Background(), c, account)
			var failoverErr *UpstreamFailoverError
			require.ErrorAs(t, err, &failoverErr)
			require.Equal(t, tt.wantReason, failoverErr.Reason)
			require.Equal(t, GatewayFailureScopeAccount, failoverErr.Scope)
			require.Equal(t, 1, baseRepo.setErrorCalls)
			require.Equal(t, StatusError, account.Status)
			require.False(t, account.Schedulable)
			require.True(t, svc.isOpenAIAccountRuntimeBlocked(account))
			require.Equal(t, []string{GrokTokenCacheKey(account)}, cache.deletedKeys)
		})
	}
}

func TestGetRequestCredentialMissingAccessNeverRefreshesAndPermanentlyFailsOver(t *testing.T) {
	gin.SetMode(gin.TestMode)
	tests := []struct {
		name      string
		expiresAt *time.Time
	}{
		{name: "expiry missing"},
		{name: "expired", expiresAt: func() *time.Time { value := time.Now().Add(-time.Minute); return &value }()},
		{name: "near expiry", expiresAt: func() *time.Time { value := time.Now().Add(30 * time.Minute); return &value }()},
	}

	for index, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			account := expiredGrokOAuthAccountForCredentialTest(int64(760 + index))
			account.Schedulable = true
			delete(account.Credentials, "access_token")
			if tt.expiresAt == nil {
				delete(account.Credentials, "expires_at")
			} else {
				account.Credentials["expires_at"] = tt.expiresAt.UTC().Format(time.RFC3339)
			}
			baseRepo := &tokenRefreshAccountRepo{}
			baseRepo.accountsByID = map[int64]*Account{account.ID: account}
			repo := &grokCredentialPersistingRepo{tokenRefreshAccountRepo: baseRepo}
			cache := &grokTokenCacheForProviderTest{lockResult: true, token: "stale-cache-must-not-win"}
			refresher := &grokCredentialCountingRefresher{}
			provider := NewGrokTokenProvider(repo, cache)
			provider.SetRefreshAPI(NewOAuthRefreshAPI(repo, cache), refresher)
			svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: provider}
			c, _ := gin.CreateTestContext(httptest.NewRecorder())

			token, kind, err := svc.getRequestCredential(context.Background(), c, account)
			var failoverErr *UpstreamFailoverError
			require.ErrorAs(t, err, &failoverErr)
			require.Empty(t, token)
			require.Empty(t, kind)
			require.Equal(t, GrokCredentialReasonMissing, failoverErr.Reason)
			require.Equal(t, NextAccountRetry, failoverErr.NextAccountAction)
			require.Zero(t, refresher.refreshCalls, "structurally missing access credentials must not reach the token endpoint")
			require.Equal(t, 1, baseRepo.setErrorCalls)
			require.Equal(t, StatusError, account.Status)
			require.False(t, account.Schedulable)
			require.Equal(t, []string{GrokTokenCacheKey(account)}, cache.deletedKeys)
			require.True(t, svc.isOpenAIAccountRuntimeBlocked(account))
		})
	}
}

func TestGetRequestCredentialWarmCachedAccessWithMissingRefreshPermanentlyFailsOver(t *testing.T) {
	account := expiredGrokOAuthAccountForCredentialTest(764)
	account.Credentials["access_token"] = "valid-access"
	account.Credentials["expires_at"] = time.Now().Add(2 * time.Hour).UTC().Format(time.RFC3339)
	delete(account.Credentials, "refresh_token")
	baseRepo := &tokenRefreshAccountRepo{}
	baseRepo.accountsByID = map[int64]*Account{account.ID: account}
	repo := &grokCredentialPersistingRepo{tokenRefreshAccountRepo: baseRepo}
	cache := &grokTokenCacheForProviderTest{lockResult: true, token: "valid-access"}
	refresher := &grokCredentialCountingRefresher{}
	provider := NewGrokTokenProvider(repo, cache)
	provider.SetRefreshAPI(NewOAuthRefreshAPI(repo, cache), refresher)
	svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: provider}
	c, _ := gin.CreateTestContext(httptest.NewRecorder())

	_, _, err := svc.getRequestCredential(context.Background(), c, account)

	var failoverErr *UpstreamFailoverError
	require.ErrorAs(t, err, &failoverErr)
	require.Equal(t, GrokCredentialReasonMissing, failoverErr.Reason)
	require.Equal(t, NextAccountRetry, failoverErr.NextAccountAction)
	require.Zero(t, refresher.refreshCalls)
	require.Equal(t, 1, baseRepo.setErrorCalls)
	require.Equal(t, []string{GrokTokenCacheKey(account)}, cache.deletedKeys)
	require.True(t, svc.isOpenAIAccountRuntimeBlocked(account))
}

func TestGetRequestCredentialMapsTransientAndProviderFailuresSeparately(t *testing.T) {
	gin.SetMode(gin.TestMode)

	t.Run("account transient temporarily unschedules", func(t *testing.T) {
		account := expiredGrokOAuthAccountForCredentialTest(702)
		repo := &tokenRefreshAccountRepo{}
		repo.accountsByID = map[int64]*Account{account.ID: account}
		cache := &grokTokenCacheForProviderTest{lockResult: true}
		provider := NewGrokTokenProvider(repo, cache)
		provider.SetRefreshAPI(NewOAuthRefreshAPI(repo, cache), &tokenRefresherStub{err: errors.New("temporary refresh transport failure")})
		svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: provider}
		c, _ := gin.CreateTestContext(httptest.NewRecorder())

		_, _, err := svc.getRequestCredential(context.Background(), c, account)
		var failoverErr *UpstreamFailoverError
		require.ErrorAs(t, err, &failoverErr)
		require.Equal(t, GatewayFailureScopeAccount, failoverErr.Scope)
		require.Equal(t, GrokCredentialReasonRefreshTransient, failoverErr.Reason)
		require.True(t, failoverErr.ShouldRetryNextAccount())
		require.Zero(t, repo.setErrorCalls)
		require.Equal(t, 1, repo.setTempUnschedCalls)
		require.True(t, svc.isOpenAIAccountRuntimeBlocked(account))
	})

	t.Run("shared provider configuration stops without mutation", func(t *testing.T) {
		account := expiredGrokOAuthAccountForCredentialTest(703)
		repo := &tokenRefreshAccountRepo{}
		repo.accountsByID = map[int64]*Account{account.ID: account}
		provider := NewGrokTokenProvider(repo, nil)
		svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: provider}
		c, _ := gin.CreateTestContext(httptest.NewRecorder())

		_, _, err := svc.getRequestCredential(context.Background(), c, account)
		var failoverErr *UpstreamFailoverError
		require.ErrorAs(t, err, &failoverErr)
		require.Equal(t, GatewayFailureScopeProvider, failoverErr.Scope)
		require.Equal(t, NextAccountStop, failoverErr.NextAccountAction)
		require.Zero(t, repo.setErrorCalls)
		require.Zero(t, repo.setTempUnschedCalls)
		require.False(t, svc.isOpenAIAccountRuntimeBlocked(account))
	})

	t.Run("account reread failures preserve shared versus missing-row scope", func(t *testing.T) {
		for _, tt := range []struct {
			name    string
			account *Account
			err     error
		}{
			{name: "repository error", err: errors.New("database temporarily unavailable")},
			{name: "missing row"},
		} {
			t.Run(tt.name, func(t *testing.T) {
				account := expiredGrokOAuthAccountForCredentialTest(712)
				baseRepo := &tokenRefreshAccountRepo{}
				baseRepo.accountsByID = map[int64]*Account{account.ID: account}
				repo := &grokCredentialRereadFailureRepo{tokenRefreshAccountRepo: baseRepo, account: tt.account, err: tt.err}
				cache := &grokTokenCacheForProviderTest{lockResult: true}
				provider := NewGrokTokenProvider(repo, cache)
				provider.SetRefreshAPI(NewOAuthRefreshAPI(repo, cache), NewGrokTokenRefresher(nil))
				svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: provider}
				c, _ := gin.CreateTestContext(httptest.NewRecorder())

				_, _, err := svc.getRequestCredential(context.Background(), c, account)
				var failoverErr *UpstreamFailoverError
				require.ErrorAs(t, err, &failoverErr)
				if tt.err != nil {
					require.Equal(t, GatewayFailureScopeProvider, failoverErr.Scope)
					require.Equal(t, GrokCredentialReasonProviderDown, failoverErr.Reason)
					require.Equal(t, NextAccountStop, failoverErr.NextAccountAction)
				} else {
					require.Equal(t, GatewayFailureScopeAccount, failoverErr.Scope)
					require.Equal(t, GrokCredentialReasonAccountChanged, failoverErr.Reason)
					require.Equal(t, NextAccountRetry, failoverErr.NextAccountAction)
				}
				require.Zero(t, baseRepo.setErrorCalls)
				require.Zero(t, baseRepo.setTempUnschedCalls)
				require.Empty(t, cache.deletedKeys)
				require.False(t, svc.isOpenAIAccountRuntimeBlocked(account))
			})
		}
	})

	t.Run("fresh account eligibility changes retry without mutating stale state", func(t *testing.T) {
		for _, tt := range []struct {
			name   string
			mutate func(*Account)
		}{
			{
				name: "account disabled",
				mutate: func(account *Account) {
					account.Status = StatusDisabled
				},
			},
			{
				name: "account converted",
				mutate: func(account *Account) {
					account.Type = AccountTypeUpstream
				},
			},
			{
				name: "account manually unschedulable",
				mutate: func(account *Account) {
					account.Schedulable = false
				},
			},
			{
				name: "account temporarily unschedulable",
				mutate: func(account *Account) {
					until := time.Now().Add(time.Minute)
					account.TempUnschedulableUntil = &until
				},
			},
		} {
			t.Run(tt.name, func(t *testing.T) {
				staleAccount := expiredGrokOAuthAccountForCredentialTest(713)
				freshAccount := *staleAccount
				freshAccount.Credentials = shallowCopyMap(staleAccount.Credentials)
				tt.mutate(&freshAccount)
				repo := &tokenRefreshAccountRepo{}
				repo.accountsByID = map[int64]*Account{staleAccount.ID: &freshAccount}
				cache := &grokTokenCacheForProviderTest{lockResult: true}
				provider := NewGrokTokenProvider(repo, cache)
				provider.SetRefreshAPI(NewOAuthRefreshAPI(repo, cache), NewGrokTokenRefresher(nil))
				svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: provider}
				c, _ := gin.CreateTestContext(httptest.NewRecorder())

				_, _, err := svc.getRequestCredential(context.Background(), c, staleAccount)
				var failoverErr *UpstreamFailoverError
				require.ErrorAs(t, err, &failoverErr)
				require.Equal(t, GatewayFailureScopeAccount, failoverErr.Scope)
				require.Equal(t, GrokCredentialReasonAccountChanged, failoverErr.Reason)
				require.Equal(t, NextAccountRetry, failoverErr.NextAccountAction)
				require.Zero(t, repo.setErrorCalls)
				require.Zero(t, repo.setTempUnschedCalls)
				require.Empty(t, cache.deletedKeys)
				require.False(t, svc.isOpenAIAccountRuntimeBlocked(staleAccount))
			})
		}
	})

	t.Run("fresh missing refresh credential permanently blocks the account", func(t *testing.T) {
		staleAccount := expiredGrokOAuthAccountForCredentialTest(714)
		staleAccount.Schedulable = true
		freshAccount := *staleAccount
		freshAccount.Credentials = shallowCopyMap(staleAccount.Credentials)
		delete(freshAccount.Credentials, "refresh_token")
		baseRepo := &tokenRefreshAccountRepo{}
		baseRepo.accountsByID = map[int64]*Account{staleAccount.ID: &freshAccount}
		repo := &grokCredentialPersistingRepo{tokenRefreshAccountRepo: baseRepo}
		cache := &grokTokenCacheForProviderTest{lockResult: true}
		provider := NewGrokTokenProvider(repo, cache)
		provider.SetRefreshAPI(NewOAuthRefreshAPI(repo, cache), NewGrokTokenRefresher(nil))
		svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: provider}
		c, _ := gin.CreateTestContext(httptest.NewRecorder())

		_, _, err := svc.getRequestCredential(context.Background(), c, staleAccount)
		var failoverErr *UpstreamFailoverError
		require.ErrorAs(t, err, &failoverErr)
		require.Equal(t, GatewayFailureScopeAccount, failoverErr.Scope)
		require.Equal(t, GrokCredentialReasonMissing, failoverErr.Reason)
		require.Equal(t, NextAccountRetry, failoverErr.NextAccountAction)
		require.Equal(t, 1, baseRepo.setErrorCalls)
		require.Zero(t, baseRepo.setTempUnschedCalls)
		require.Equal(t, StatusError, freshAccount.Status)
		require.False(t, freshAccount.Schedulable)
		require.Equal(t, []string{GrokTokenCacheKey(staleAccount)}, cache.deletedKeys)
		require.True(t, svc.isOpenAIAccountRuntimeBlocked(staleAccount))
	})

	t.Run("refresh added after locked structural failure wins conditional mutation", func(t *testing.T) {
		staleAccount := expiredGrokOAuthAccountForCredentialTest(717)
		freshAccount := *staleAccount
		freshAccount.Credentials = shallowCopyMap(staleAccount.Credentials)
		delete(freshAccount.Credentials, "refresh_token")
		repo := &tokenRefreshAccountRepo{}
		repo.accountsByID = map[int64]*Account{staleAccount.ID: &freshAccount}
		repo.beforeConditionalState = func() {
			repaired := freshAccount
			repaired.Credentials = shallowCopyMap(freshAccount.Credentials)
			repaired.Credentials["refresh_token"] = "repaired-refresh-token"
			repaired.Credentials["expires_at"] = time.Now().Add(time.Hour).UTC().Format(time.RFC3339)
			repo.accountsByID[staleAccount.ID] = &repaired
		}
		cache := &grokTokenCacheForProviderTest{lockResult: true}
		provider := NewGrokTokenProvider(repo, cache)
		provider.SetRefreshAPI(NewOAuthRefreshAPI(repo, cache), NewGrokTokenRefresher(nil))
		svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: provider}
		c, _ := gin.CreateTestContext(httptest.NewRecorder())

		token, kind, err := svc.getRequestCredential(context.Background(), c, staleAccount)

		require.NoError(t, err)
		require.Equal(t, "expired-access-token", token)
		require.Equal(t, "oauth", kind)
		require.Zero(t, repo.setErrorCalls)
		require.Zero(t, repo.setTempUnschedCalls)
		require.Empty(t, cache.deletedKeys)
		require.False(t, svc.isOpenAIAccountRuntimeBlocked(staleAccount))
	})

	t.Run("expiry-only repair wins full credential fingerprint CAS", func(t *testing.T) {
		account := expiredGrokOAuthAccountForCredentialTest(718)
		repo := &tokenRefreshAccountRepo{}
		repo.accountsByID = map[int64]*Account{account.ID: account}
		repo.beforeConditionalState = func() {
			repaired := *account
			repaired.Credentials = shallowCopyMap(account.Credentials)
			repaired.Credentials["expires_at"] = time.Now().Add(time.Hour).UTC().Format(time.RFC3339)
			repo.accountsByID[account.ID] = &repaired
		}
		cache := &grokTokenCacheForProviderTest{lockResult: true}
		provider := NewGrokTokenProvider(repo, cache)
		provider.SetRefreshAPI(NewOAuthRefreshAPI(repo, cache), &tokenRefresherStub{
			err: infraerrors.New(http.StatusBadGateway, "GROK_OAUTH_TOKEN_REFRESH_FAILED", "invalid_grant"),
		})
		svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: provider}
		c, _ := gin.CreateTestContext(httptest.NewRecorder())

		token, kind, err := svc.getRequestCredential(context.Background(), c, account)

		require.NoError(t, err)
		require.Equal(t, "expired-access-token", token)
		require.Equal(t, "oauth", kind)
		require.Zero(t, repo.setErrorCalls)
		require.Empty(t, cache.deletedKeys)
		require.False(t, svc.isOpenAIAccountRuntimeBlocked(account))
	})

	t.Run("generic token endpoint 403 stops as shared provider failure", func(t *testing.T) {
		account := expiredGrokOAuthAccountForCredentialTest(708)
		repo := &tokenRefreshAccountRepo{}
		repo.accountsByID = map[int64]*Account{account.ID: account}
		cache := &grokTokenCacheForProviderTest{lockResult: true}
		provider := NewGrokTokenProvider(repo, cache)
		provider.SetRefreshAPI(NewOAuthRefreshAPI(repo, cache), &tokenRefresherStub{
			err: infraerrors.New(http.StatusBadGateway, "GROK_OAUTH_TOKEN_REFRESH_FAILED", "token refresh failed: status 403, body: forbidden"),
		})
		svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: provider}
		c, _ := gin.CreateTestContext(httptest.NewRecorder())

		_, _, err := svc.getRequestCredential(context.Background(), c, account)
		var failoverErr *UpstreamFailoverError
		require.ErrorAs(t, err, &failoverErr)
		require.Equal(t, GatewayFailureScopeProvider, failoverErr.Scope)
		require.Equal(t, GrokCredentialReasonProviderDown, failoverErr.Reason)
		require.Equal(t, NextAccountStop, failoverErr.NextAccountAction)
		require.Zero(t, repo.setErrorCalls)
		require.Zero(t, repo.setTempUnschedCalls)
		require.Empty(t, cache.deletedKeys)
		require.False(t, svc.isOpenAIAccountRuntimeBlocked(account))
	})

	t.Run("account proxy generic 403 remains bounded account transient", func(t *testing.T) {
		account := expiredGrokOAuthAccountForCredentialTest(711)
		proxyID := int64(43)
		account.ProxyID = &proxyID
		account.Proxy = &Proxy{}
		repo := &tokenRefreshAccountRepo{}
		repo.accountsByID = map[int64]*Account{account.ID: account}
		cache := &grokTokenCacheForProviderTest{lockResult: true}
		provider := NewGrokTokenProvider(repo, cache)
		provider.SetRefreshAPI(NewOAuthRefreshAPI(repo, cache), &tokenRefresherStub{
			err: infraerrors.New(http.StatusBadGateway, "GROK_OAUTH_TOKEN_REFRESH_FAILED", "token refresh failed: status 403, body: forbidden"),
		})
		svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: provider}
		c, _ := gin.CreateTestContext(httptest.NewRecorder())

		_, _, err := svc.getRequestCredential(context.Background(), c, account)
		var failoverErr *UpstreamFailoverError
		require.ErrorAs(t, err, &failoverErr)
		require.Equal(t, GatewayFailureScopeAccount, failoverErr.Scope)
		require.Equal(t, GrokCredentialReasonRefreshTransient, failoverErr.Reason)
		require.Equal(t, NextAccountRetry, failoverErr.NextAccountAction)
		require.Zero(t, repo.setErrorCalls)
		require.Equal(t, 1, repo.setTempUnschedCalls)
		require.Empty(t, cache.deletedKeys)
		require.True(t, svc.isOpenAIAccountRuntimeBlocked(account))
	})

	t.Run("proxy repository read failure stops without account mutation", func(t *testing.T) {
		account := expiredGrokOAuthAccountForCredentialTest(709)
		proxyID := int64(41)
		account.ProxyID = &proxyID
		account.Proxy = &Proxy{}
		repo := &tokenRefreshAccountRepo{}
		repo.accountsByID = map[int64]*Account{account.ID: account}
		cache := &grokTokenCacheForProviderTest{lockResult: true}
		oauthSvc := NewGrokOAuthService(&grokCredentialProxyRepoStub{err: errors.New("database temporarily unavailable")}, &grokOAuthClientStub{})
		defer oauthSvc.Stop()
		provider := NewGrokTokenProvider(repo, cache)
		provider.SetRefreshAPI(NewOAuthRefreshAPI(repo, cache), NewGrokTokenRefresher(oauthSvc))
		svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: provider}
		c, _ := gin.CreateTestContext(httptest.NewRecorder())

		_, _, err := svc.getRequestCredential(context.Background(), c, account)
		var failoverErr *UpstreamFailoverError
		require.ErrorAs(t, err, &failoverErr)
		require.Equal(t, GatewayFailureScopeProvider, failoverErr.Scope)
		require.Equal(t, GrokCredentialReasonProviderDown, failoverErr.Reason)
		require.Equal(t, NextAccountStop, failoverErr.NextAccountAction)
		require.Zero(t, repo.setErrorCalls)
		require.Zero(t, repo.setTempUnschedCalls)
		require.Empty(t, cache.deletedKeys)
		require.False(t, svc.isOpenAIAccountRuntimeBlocked(account))
	})

	t.Run("structurally missing configured proxy permanently blocks only that account", func(t *testing.T) {
		account := expiredGrokOAuthAccountForCredentialTest(710)
		account.Status = StatusActive
		account.Schedulable = true
		proxyID := int64(42)
		account.ProxyID = &proxyID
		baseRepo := &tokenRefreshAccountRepo{}
		baseRepo.accountsByID = map[int64]*Account{account.ID: account}
		repo := &grokCredentialPersistingRepo{tokenRefreshAccountRepo: baseRepo}
		cache := &grokTokenCacheForProviderTest{lockResult: true}
		oauthSvc := NewGrokOAuthService(&grokCredentialProxyRepoStub{err: ErrProxyNotFound}, &grokOAuthClientStub{})
		defer oauthSvc.Stop()
		provider := NewGrokTokenProvider(repo, cache)
		provider.SetRefreshAPI(NewOAuthRefreshAPI(repo, cache), NewGrokTokenRefresher(oauthSvc))
		svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: provider}
		c, _ := gin.CreateTestContext(httptest.NewRecorder())

		_, _, err := svc.getRequestCredential(context.Background(), c, account)
		var failoverErr *UpstreamFailoverError
		require.ErrorAs(t, err, &failoverErr)
		require.Equal(t, GatewayFailureScopeAccount, failoverErr.Scope)
		require.Equal(t, GrokCredentialReasonProxyInvalid, failoverErr.Reason)
		require.Equal(t, NextAccountRetry, failoverErr.NextAccountAction)
		require.Equal(t, 1, baseRepo.setErrorCalls)
		require.Equal(t, StatusError, account.Status)
		require.False(t, account.Schedulable)
		require.Equal(t, []string{GrokTokenCacheKey(account)}, cache.deletedKeys)
		require.True(t, svc.isOpenAIAccountRuntimeBlocked(account))
	})
}

func TestGetRequestCredentialRuntimeBlockWinsBeforeWarmTokenCache(t *testing.T) {
	account := expiredGrokOAuthAccountForCredentialTest(716)
	account.Credentials["access_token"] = "valid-access"
	account.Credentials["expires_at"] = time.Now().Add(2 * time.Hour).UTC().Format(time.RFC3339)
	repo := &tokenRefreshAccountRepo{}
	repo.accountsByID = map[int64]*Account{account.ID: account}
	cache := &grokTokenCacheForProviderTest{token: "valid-access"}
	provider := NewGrokTokenProvider(repo, cache)
	svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: provider}
	svc.BlockAccountScheduling(account, time.Now().Add(time.Minute), "independent")
	c, _ := gin.CreateTestContext(httptest.NewRecorder())

	_, _, err := svc.getRequestCredential(context.Background(), c, account)

	var failoverErr *UpstreamFailoverError
	require.ErrorAs(t, err, &failoverErr)
	require.Equal(t, GrokCredentialReasonAccountChanged, failoverErr.Reason)
	require.Equal(t, NextAccountRetry, failoverErr.NextAccountAction)
	require.Zero(t, cache.getCalls)
	require.Zero(t, repo.setErrorCalls)
	require.Zero(t, repo.setTempUnschedCalls)
}

func TestGetRequestCredentialWarmCachedAccessWithMissingConfiguredProxyPermanentlyFailsOver(t *testing.T) {
	account := expiredGrokOAuthAccountForCredentialTest(715)
	account.Credentials["access_token"] = "valid-access"
	account.Credentials["expires_at"] = time.Now().Add(2 * time.Hour).UTC().Format(time.RFC3339)
	proxyID := int64(44)
	account.ProxyID = &proxyID
	account.Proxy = nil
	baseRepo := &tokenRefreshAccountRepo{}
	baseRepo.accountsByID = map[int64]*Account{account.ID: account}
	repo := &grokCredentialPersistingRepo{tokenRefreshAccountRepo: baseRepo}
	cache := &grokTokenCacheForProviderTest{lockResult: true, token: "valid-access"}
	refresher := &grokCredentialCountingRefresher{}
	provider := NewGrokTokenProvider(repo, cache)
	provider.SetRefreshAPI(NewOAuthRefreshAPI(repo, cache), refresher)
	svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: provider}
	c, _ := gin.CreateTestContext(httptest.NewRecorder())

	_, _, err := svc.getRequestCredential(context.Background(), c, account)

	var failoverErr *UpstreamFailoverError
	require.ErrorAs(t, err, &failoverErr)
	require.Equal(t, GrokCredentialReasonProxyInvalid, failoverErr.Reason)
	require.Equal(t, NextAccountRetry, failoverErr.NextAccountAction)
	require.Zero(t, refresher.refreshCalls)
	require.Equal(t, 1, baseRepo.setErrorCalls)
	require.Equal(t, []string{GrokTokenCacheKey(account)}, cache.deletedKeys)
	require.True(t, svc.isOpenAIAccountRuntimeBlocked(account))
}

func TestGetRequestCredentialCancellationAndBudgetDoNotMutateAccount(t *testing.T) {
	gin.SetMode(gin.TestMode)
	account := expiredGrokOAuthAccountForCredentialTest(704)
	repo := &tokenRefreshAccountRepo{}
	repo.accountsByID = map[int64]*Account{account.ID: account}
	provider := NewGrokTokenProvider(repo, nil)
	svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: provider}

	t.Run("parent cancellation is returned directly", func(t *testing.T) {
		ctx, cancel := context.WithCancel(context.Background())
		cancel()
		c, _ := gin.CreateTestContext(httptest.NewRecorder())

		_, _, err := svc.getRequestCredential(ctx, c, account)
		require.ErrorIs(t, err, context.Canceled)
		var failoverErr *UpstreamFailoverError
		require.False(t, errors.As(err, &failoverErr))
	})

	t.Run("request credential budget stops safely", func(t *testing.T) {
		c, _ := gin.CreateTestContext(httptest.NewRecorder())
		c.Set(grokCredentialFailoverDeadlineKey, time.Now().Add(-time.Second))

		_, _, err := svc.getRequestCredential(context.Background(), c, account)
		var failoverErr *UpstreamFailoverError
		require.ErrorAs(t, err, &failoverErr)
		require.Equal(t, GatewayFailureScopeRequest, failoverErr.Scope)
		require.Equal(t, GrokCredentialReasonFailoverTimeout, failoverErr.Reason)
		require.False(t, failoverErr.ShouldRetryNextAccount())
	})

	require.Zero(t, repo.setErrorCalls)
	require.Zero(t, repo.setTempUnschedCalls)
	require.False(t, svc.isOpenAIAccountRuntimeBlocked(account))
}

func TestGetRequestCredentialStateMutationFailureStopsAndKeepsRuntimeBlock(t *testing.T) {
	gin.SetMode(gin.TestMode)
	tests := []struct {
		name            string
		refreshErr      error
		configure       func(*tokenRefreshAccountRepo, *grokTokenCacheForProviderTest)
		wantSetError    int
		wantSetTemp     int
		wantCacheDelete int
	}{
		{
			name:       "permanent state persistence",
			refreshErr: infraerrors.New(http.StatusBadGateway, "GROK_OAUTH_TOKEN_REFRESH_FAILED", "invalid_grant"),
			configure: func(repo *tokenRefreshAccountRepo, _ *grokTokenCacheForProviderTest) {
				repo.setErrorErr = errors.New("database write failed")
			},
			wantSetError: 1,
		},
		{
			name:       "transient state persistence",
			refreshErr: errors.New("temporary refresh transport failure"),
			configure: func(repo *tokenRefreshAccountRepo, _ *grokTokenCacheForProviderTest) {
				repo.setTempUnschedErr = errors.New("database write failed")
			},
			wantSetTemp: 1,
		},
		{
			name:       "permanent token cache invalidation",
			refreshErr: infraerrors.New(http.StatusBadGateway, "GROK_OAUTH_TOKEN_REFRESH_FAILED", "invalid_grant"),
			configure: func(_ *tokenRefreshAccountRepo, cache *grokTokenCacheForProviderTest) {
				cache.deleteErr = errors.New("cache delete failed")
			},
			wantSetError:    1,
			wantCacheDelete: 1,
		},
	}

	for index, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			account := expiredGrokOAuthAccountForCredentialTest(int64(740 + index))
			repo := &tokenRefreshAccountRepo{}
			repo.accountsByID = map[int64]*Account{account.ID: account}
			cache := &grokTokenCacheForProviderTest{lockResult: true}
			tt.configure(repo, cache)
			provider := NewGrokTokenProvider(repo, cache)
			provider.SetRefreshAPI(NewOAuthRefreshAPI(repo, cache), &tokenRefresherStub{err: tt.refreshErr})
			svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: provider}
			c, _ := gin.CreateTestContext(httptest.NewRecorder())

			_, _, err := svc.getRequestCredential(context.Background(), c, account)
			var failoverErr *UpstreamFailoverError
			require.ErrorAs(t, err, &failoverErr)
			require.Equal(t, GatewayFailureScopeProvider, failoverErr.Scope)
			require.Equal(t, GrokCredentialReasonStateUpdate, failoverErr.Reason)
			require.Equal(t, NextAccountStop, failoverErr.NextAccountAction)
			require.Equal(t, tt.wantSetError, repo.setErrorCalls)
			require.Equal(t, tt.wantSetTemp, repo.setTempUnschedCalls)
			require.Len(t, cache.deletedKeys, tt.wantCacheDelete)
			require.True(t, svc.isOpenAIAccountRuntimeBlocked(account), "failed mutation must retain the immediate local block")
		})
	}
}

func TestGrokCredentialMutationBoundariesHonorParentCancellation(t *testing.T) {
	t.Run("blocked SetError cancellation prevents cache and runtime mutation", func(t *testing.T) {
		account := expiredGrokOAuthAccountForCredentialTest(730)
		baseRepo := &tokenRefreshAccountRepo{}
		baseRepo.accountsByID = map[int64]*Account{account.ID: account}
		repo := &grokCredentialBlockingRepo{
			tokenRefreshAccountRepo: baseRepo,
			setErrorStarted:         make(chan struct{}),
			setTempStarted:          make(chan struct{}),
		}
		cache := &grokTokenCacheForProviderTest{}
		svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: NewGrokTokenProvider(repo, cache)}
		ctx, cancel := context.WithCancel(context.Background())
		result := make(chan error, 1)
		go func() {
			_, err := svc.applyGrokCredentialAccountFailure(ctx, account, grokCredentialFailureClass{
				reason: GrokCredentialReasonRevoked, permanent: true,
			})
			result <- err
		}()
		<-repo.setErrorStarted
		require.True(t, svc.isOpenAIAccountRuntimeBlocked(account), "runtime block must precede persistent SetError")
		cancel()

		require.ErrorIs(t, <-result, context.Canceled)
		require.Zero(t, baseRepo.setErrorCalls)
		require.Empty(t, cache.deletedKeys)
		require.False(t, svc.isOpenAIAccountRuntimeBlocked(account))
	})

	t.Run("blocked temporary unschedule cancellation prevents runtime mutation", func(t *testing.T) {
		account := expiredGrokOAuthAccountForCredentialTest(731)
		baseRepo := &tokenRefreshAccountRepo{}
		baseRepo.accountsByID = map[int64]*Account{account.ID: account}
		repo := &grokCredentialBlockingRepo{
			tokenRefreshAccountRepo: baseRepo,
			setErrorStarted:         make(chan struct{}),
			setTempStarted:          make(chan struct{}),
		}
		svc := &OpenAIGatewayService{accountRepo: repo}
		ctx, cancel := context.WithCancel(context.Background())
		result := make(chan error, 1)
		go func() {
			_, err := svc.applyGrokCredentialAccountFailure(ctx, account, grokCredentialFailureClass{
				reason: GrokCredentialReasonRefreshTransient, transient: true,
			})
			result <- err
		}()
		<-repo.setTempStarted
		require.True(t, svc.isOpenAIAccountRuntimeBlocked(account), "runtime block must precede temporary unscheduling")
		cancel()

		require.ErrorIs(t, <-result, context.Canceled)
		require.Zero(t, baseRepo.setTempUnschedCalls)
		require.False(t, svc.isOpenAIAccountRuntimeBlocked(account))
	})

	t.Run("post-commit cancellation finishes cache cleanup and retains quarantine", func(t *testing.T) {
		account := expiredGrokOAuthAccountForCredentialTest(732)
		repo := &tokenRefreshAccountRepo{}
		repo.accountsByID = map[int64]*Account{account.ID: account}
		cache := &grokCredentialBlockingCache{deleteStarted: make(chan struct{}), releaseDelete: make(chan struct{})}
		svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: NewGrokTokenProvider(repo, cache)}
		ctx, cancel := context.WithCancel(context.Background())
		result := make(chan error, 1)
		go func() {
			_, err := svc.applyGrokCredentialAccountFailure(ctx, account, grokCredentialFailureClass{
				reason: GrokCredentialReasonRevoked, permanent: true,
			})
			result <- err
		}()
		<-cache.deleteStarted
		require.True(t, svc.isOpenAIAccountRuntimeBlocked(account), "runtime block must precede cache invalidation")
		cancel()
		close(cache.releaseDelete)

		require.ErrorIs(t, <-result, context.Canceled)
		require.Equal(t, 1, repo.setErrorCalls)
		require.True(t, cache.wasDeleted())
		require.True(t, svc.isOpenAIAccountRuntimeBlocked(account))
	})
}

func TestGrokCredentialMutationLockWaitHonorsCredentialBudget(t *testing.T) {
	account := expiredGrokOAuthAccountForCredentialTest(735)
	repo := &tokenRefreshAccountRepo{}
	repo.accountsByID = map[int64]*Account{account.ID: account}
	svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: NewGrokTokenProvider(repo, &grokTokenCacheForProviderTest{})}
	mutationLock := svc.grokCredentialMutationLock(account.ID)
	require.NoError(t, mutationLock.Lock(context.Background()))
	defer mutationLock.Unlock()
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Millisecond)
	defer cancel()

	startedAt := time.Now()
	token, err := svc.applyGrokCredentialAccountFailure(ctx, account, grokCredentialFailureClass{
		reason: GrokCredentialReasonRevoked, permanent: true,
	})

	require.ErrorIs(t, err, context.DeadlineExceeded)
	require.Empty(t, token)
	require.Less(t, time.Since(startedAt), 500*time.Millisecond)
	require.Zero(t, repo.setErrorCalls)
	require.Zero(t, repo.setTempUnschedCalls)
	require.False(t, svc.isOpenAIAccountRuntimeBlocked(account))
}

func TestGetRequestCredentialBudgetBoundsBlockedConditionalMutation(t *testing.T) {
	gin.SetMode(gin.TestMode)
	account := expiredGrokOAuthAccountForCredentialTest(736)
	baseRepo := &tokenRefreshAccountRepo{}
	baseRepo.accountsByID = map[int64]*Account{account.ID: account}
	repo := &grokCredentialBlockingRepo{
		tokenRefreshAccountRepo: baseRepo,
		setErrorStarted:         make(chan struct{}),
		setTempStarted:          make(chan struct{}),
	}
	cache := &grokTokenCacheForProviderTest{lockResult: true}
	provider := NewGrokTokenProvider(repo, cache)
	provider.SetRefreshAPI(NewOAuthRefreshAPI(repo, cache), &tokenRefresherStub{
		err: infraerrors.New(http.StatusBadGateway, "GROK_OAUTH_TOKEN_REFRESH_FAILED", "invalid_grant"),
	})
	svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: provider}
	c, _ := gin.CreateTestContext(httptest.NewRecorder())
	c.Set(grokCredentialFailoverDeadlineKey, time.Now().Add(40*time.Millisecond))

	startedAt := time.Now()
	token, kind, err := svc.getRequestCredential(context.Background(), c, account)

	var failoverErr *UpstreamFailoverError
	require.ErrorAs(t, err, &failoverErr)
	require.Equal(t, GatewayFailureScopeRequest, failoverErr.Scope)
	require.Equal(t, GrokCredentialReasonFailoverTimeout, failoverErr.Reason)
	require.Equal(t, NextAccountStop, failoverErr.NextAccountAction)
	require.Empty(t, token)
	require.Empty(t, kind)
	require.Less(t, time.Since(startedAt), 500*time.Millisecond)
	require.Zero(t, baseRepo.setErrorCalls)
	require.Zero(t, baseRepo.setTempUnschedCalls)
	require.Empty(t, cache.deletedKeys)
	require.False(t, svc.isOpenAIAccountRuntimeBlocked(account))
}

func TestGetRequestCredentialLockHeldTimeoutDoesNotQuarantineAccount(t *testing.T) {
	gin.SetMode(gin.TestMode)
	tests := []struct {
		name       string
		buildRepo  func(*Account) AccountRepository
		wantScope  GatewayFailureScope
		wantReason GatewayFailureReason
		wantAction NextAccountAction
	}{
		{
			name: "authoritative row unchanged",
			buildRepo: func(account *Account) AccountRepository {
				repo := &tokenRefreshAccountRepo{}
				repo.accountsByID = map[int64]*Account{account.ID: account}
				return repo
			},
			wantScope:  GatewayFailureScopeAccount,
			wantReason: GrokCredentialReasonAccountChanged,
			wantAction: NextAccountRetry,
		},
		{
			name: "selected account was deleted",
			buildRepo: func(account *Account) AccountRepository {
				base := &tokenRefreshAccountRepo{}
				base.accountsByID = map[int64]*Account{account.ID: account}
				return &grokCredentialRereadFailureRepo{tokenRefreshAccountRepo: base}
			},
			wantScope:  GatewayFailureScopeAccount,
			wantReason: GrokCredentialReasonAccountChanged,
			wantAction: NextAccountRetry,
		},
		{
			name: "shared account store unavailable",
			buildRepo: func(account *Account) AccountRepository {
				base := &tokenRefreshAccountRepo{}
				base.accountsByID = map[int64]*Account{account.ID: account}
				return &grokCredentialRereadFailureRepo{tokenRefreshAccountRepo: base, err: errors.New("database unavailable")}
			},
			wantScope:  GatewayFailureScopeProvider,
			wantReason: GrokCredentialReasonProviderDown,
			wantAction: NextAccountStop,
		},
	}

	for index, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			account := expiredGrokOAuthAccountForCredentialTest(int64(7400 + index))
			repo := tt.buildRepo(account)
			cache := &grokTokenCacheForProviderTest{lockResult: false}
			provider := NewGrokTokenProvider(repo, cache)
			provider.SetRefreshAPI(NewOAuthRefreshAPI(repo, cache), &tokenRefresherStub{})
			svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: provider}
			c, _ := gin.CreateTestContext(httptest.NewRecorder())

			startedAt := time.Now()
			_, _, err := svc.getRequestCredential(context.Background(), c, account)

			var failoverErr *UpstreamFailoverError
			require.ErrorAs(t, err, &failoverErr)
			require.Equal(t, tt.wantScope, failoverErr.Scope)
			require.Equal(t, tt.wantReason, failoverErr.Reason)
			require.Equal(t, tt.wantAction, failoverErr.NextAccountAction)
			require.Less(t, time.Since(startedAt), 3*time.Second)
			switch countingRepo := repo.(type) {
			case *tokenRefreshAccountRepo:
				require.Zero(t, countingRepo.setErrorCalls)
				require.Zero(t, countingRepo.setTempUnschedCalls)
			case *grokCredentialRereadFailureRepo:
				require.Zero(t, countingRepo.tokenRefreshAccountRepo.setErrorCalls)
				require.Zero(t, countingRepo.tokenRefreshAccountRepo.setTempUnschedCalls)
			}
			require.Empty(t, cache.deletedKeys)
			require.False(t, svc.isOpenAIAccountRuntimeBlocked(account))
		})
	}
}

func TestGrokCredentialMutationCancellationAmbiguityConfirmsDurableCommit(t *testing.T) {
	tests := []struct {
		name      string
		class     grokCredentialFailureClass
		committed func(*Account) bool
	}{
		{
			name:  "permanent quarantine",
			class: grokCredentialFailureClass{reason: GrokCredentialReasonRevoked, permanent: true},
			committed: func(account *Account) bool {
				return account.Status == StatusError && !account.Schedulable && account.ErrorMessage == string(GrokCredentialReasonRevoked)
			},
		},
		{
			name:  "temporary quarantine",
			class: grokCredentialFailureClass{reason: GrokCredentialReasonRefreshTransient, transient: true},
			committed: func(account *Account) bool {
				return account.TempUnschedulableUntil != nil && account.TempUnschedulableReason == string(GrokCredentialReasonRefreshTransient)
			},
		},
	}

	for index, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			account := expiredGrokOAuthAccountForCredentialTest(int64(737 + index))
			baseRepo := &tokenRefreshAccountRepo{}
			baseRepo.accountsByID = map[int64]*Account{account.ID: account}
			repo := &grokCredentialCommitThenCancelRepo{tokenRefreshAccountRepo: baseRepo}
			cache := &grokTokenCacheForProviderTest{}
			svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: NewGrokTokenProvider(repo, cache)}
			ctx, cancel := context.WithTimeout(context.Background(), 30*time.Millisecond)
			defer cancel()

			token, err := svc.applyGrokCredentialAccountFailure(ctx, account, tt.class)

			require.ErrorIs(t, err, context.DeadlineExceeded)
			require.Empty(t, token)
			require.True(t, tt.committed(account), "the detached confirmation must recognize the durable mutation")
			require.True(t, svc.isOpenAIAccountRuntimeBlocked(account), "a confirmed durable quarantine must retain its runtime block")
			if tt.class.permanent {
				require.Equal(t, []string{GrokTokenCacheKey(account)}, cache.deletedKeys)
			} else {
				require.Empty(t, cache.deletedKeys)
			}
		})
	}
}

func TestGrokCredentialInnerStateDeadlineAmbiguityConfirmsDurableCommit(t *testing.T) {
	tests := []struct {
		name  string
		class grokCredentialFailureClass
	}{
		{name: "permanent quarantine", class: grokCredentialFailureClass{reason: GrokCredentialReasonRevoked, permanent: true}},
		{name: "temporary quarantine", class: grokCredentialFailureClass{reason: GrokCredentialReasonRefreshTransient, transient: true}},
	}

	for index, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			account := expiredGrokOAuthAccountForCredentialTest(int64(7500 + index))
			baseRepo := &tokenRefreshAccountRepo{}
			baseRepo.accountsByID = map[int64]*Account{account.ID: account}
			repo := &grokCredentialCommitThenCancelRepo{
				tokenRefreshAccountRepo: baseRepo,
				returnErr:               context.DeadlineExceeded,
			}
			cache := &grokTokenCacheForProviderTest{}
			svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: NewGrokTokenProvider(repo, cache)}

			token, err := svc.applyGrokCredentialAccountFailure(context.Background(), account, tt.class)

			require.NoError(t, err, "the detached readback must resolve the inner timeout's commit ambiguity")
			require.Empty(t, token)
			require.True(t, svc.isOpenAIAccountRuntimeBlocked(account))
			if tt.class.permanent {
				require.Equal(t, StatusError, account.Status)
				require.False(t, account.Schedulable)
				require.Equal(t, []string{GrokTokenCacheKey(account)}, cache.deletedKeys)
			} else {
				require.NotNil(t, account.TempUnschedulableUntil)
				require.Equal(t, string(GrokCredentialReasonRefreshTransient), account.TempUnschedulableReason)
				require.Empty(t, cache.deletedKeys)
			}
		})
	}
}

func TestGrokCredentialUnconfirmedInnerStateDeadlineStopsAndRetainsSafetyBlock(t *testing.T) {
	tests := []struct {
		name  string
		class grokCredentialFailureClass
	}{
		{name: "permanent quarantine", class: grokCredentialFailureClass{reason: GrokCredentialReasonRevoked, permanent: true}},
		{name: "temporary quarantine", class: grokCredentialFailureClass{reason: GrokCredentialReasonRefreshTransient, transient: true}},
	}

	for index, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			account := expiredGrokOAuthAccountForCredentialTest(int64(7600 + index))
			baseRepo := &tokenRefreshAccountRepo{}
			baseRepo.accountsByID = map[int64]*Account{account.ID: account}
			repo := &grokCredentialUncommittedDeadlineRepo{tokenRefreshAccountRepo: baseRepo}
			cache := &grokTokenCacheForProviderTest{}
			svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: NewGrokTokenProvider(repo, cache)}

			token, err := svc.applyGrokCredentialAccountFailure(context.Background(), account, tt.class)

			require.ErrorIs(t, err, errGrokCredentialStateUpdateFailed)
			require.Empty(t, token)
			require.True(t, svc.isOpenAIAccountRuntimeBlocked(account), "an unknown commit outcome must retain the local safety block")
			require.Equal(t, StatusActive, account.Status)
			require.True(t, account.Schedulable)
			require.Nil(t, account.TempUnschedulableUntil)
			require.Empty(t, cache.deletedKeys)
		})
	}
}

func TestGrokCredentialRuntimeRollbackOwnership(t *testing.T) {
	account := expiredGrokOAuthAccountForCredentialTest(734)
	t.Run("later extending block survives", func(t *testing.T) {
		svc := &OpenAIGatewayService{}
		until := time.Now().Add(time.Minute)
		rollbackFirst := svc.blockGrokCredentialRuntime(account, until, "first")

		secondInstalled := make(chan struct{})
		go func() {
			svc.BlockAccountScheduling(account, until.Add(time.Minute), "independent")
			close(secondInstalled)
		}()
		<-secondInstalled
		rollbackFirst()

		require.True(t, svc.isOpenAIAccountRuntimeBlocked(account),
			"rollback owned by the first invocation must not remove a later extending block")
	})

	t.Run("independent shorter block steals rollback ownership", func(t *testing.T) {
		svc := &OpenAIGatewayService{}
		until := time.Now().Add(2 * time.Minute)
		rollbackFirst := svc.blockGrokCredentialRuntime(account, until, "first")
		svc.BlockAccountScheduling(account, until.Add(-time.Minute), "shorter-no-op")

		rollbackFirst()

		require.True(t, svc.isOpenAIAccountRuntimeBlocked(account))
	})

	t.Run("serialized tentative rollbacks leave no block", func(t *testing.T) {
		svc := &OpenAIGatewayService{}
		for i := 0; i < 2; i++ {
			mu := svc.grokCredentialMutationLock(account.ID)
			require.NoError(t, mu.Lock(context.Background()))
			rollback := svc.blockGrokCredentialRuntime(account, time.Now().Add(time.Minute), "tentative")
			rollback()
			mu.Unlock()
		}
		require.False(t, svc.isOpenAIAccountRuntimeBlocked(account))
	})
}

func TestGetRequestCredentialAPIKeyBypassesOAuthFailureMapping(t *testing.T) {
	gin.SetMode(gin.TestMode)
	account := &Account{
		ID:       705,
		Platform: PlatformGrok,
		Type:     AccountTypeAPIKey,
		Credentials: map[string]any{
			"api_key":  "third-party-key",
			"base_url": "https://grok.example.test/v1",
		},
	}
	c, _ := gin.CreateTestContext(httptest.NewRecorder())
	svc := &OpenAIGatewayService{}

	token, kind, err := svc.getRequestCredential(context.Background(), c, account)
	require.NoError(t, err)
	require.Equal(t, "third-party-key", token)
	require.Equal(t, "apikey", kind)
	_, hasEvents := c.Get(OpsUpstreamErrorsKey)
	require.False(t, hasEvents)
}

func TestPermanentCredentialFailureDoesNotDisableConcurrentlyRefreshedAccount(t *testing.T) {
	account := expiredGrokOAuthAccountForCredentialTest(707)
	latest := *account
	latest.Credentials = shallowCopyMap(account.Credentials)
	latest.Credentials["access_token"] = "fresh-access-token"
	latest.Credentials["refresh_token"] = "rotated-refresh-token"
	latest.Credentials["expires_at"] = time.Now().Add(time.Hour).UTC().Format(time.RFC3339)
	latest.Credentials["_token_version"] = time.Now().UnixMilli()
	repo := &tokenRefreshAccountRepo{}
	repo.accountsByID = map[int64]*Account{account.ID: &latest}
	cache := &grokTokenCacheForProviderTest{}
	svc := &OpenAIGatewayService{
		accountRepo:       repo,
		grokTokenProvider: NewGrokTokenProvider(repo, cache),
	}

	_, mutationErr := svc.applyGrokCredentialAccountFailure(context.Background(), account, grokCredentialFailureClass{
		scope:     GatewayFailureScopeAccount,
		reason:    GrokCredentialReasonRevoked,
		action:    NextAccountRetry,
		permanent: true,
	})

	require.NoError(t, mutationErr)
	require.Zero(t, repo.setErrorCalls)
	require.Empty(t, cache.deletedKeys)
	require.False(t, svc.isOpenAIAccountRuntimeBlocked(account))
}

func TestCredentialFailureConditionalMutationLosesToConcurrentRefresh(t *testing.T) {
	for index, tt := range []struct {
		name       string
		refreshErr error
	}{
		{name: "permanent", refreshErr: infraerrors.New(http.StatusBadGateway, "GROK_OAUTH_TOKEN_REFRESH_FAILED", "invalid_grant")},
		{name: "transient", refreshErr: errors.New("temporary refresh transport failure")},
	} {
		t.Run(tt.name, func(t *testing.T) {
			account := expiredGrokOAuthAccountForCredentialTest(int64(770 + index))
			repo := &tokenRefreshAccountRepo{}
			repo.accountsByID = map[int64]*Account{account.ID: account}
			repo.beforeConditionalState = func() {
				fresh := *account
				fresh.Credentials = shallowCopyMap(account.Credentials)
				fresh.Credentials["access_token"] = "refresh-won-token"
				fresh.Credentials["refresh_token"] = "refresh-won-refresh"
				fresh.Credentials["expires_at"] = time.Now().Add(2 * time.Hour).UTC().Format(time.RFC3339)
				fresh.Credentials["_token_version"] = time.Now().UnixMilli()
				repo.accountsByID[account.ID] = &fresh
			}
			cache := &grokTokenCacheForProviderTest{lockResult: true}
			provider := NewGrokTokenProvider(repo, cache)
			provider.SetRefreshAPI(NewOAuthRefreshAPI(repo, cache), &tokenRefresherStub{err: tt.refreshErr})
			svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: provider}
			c, _ := gin.CreateTestContext(httptest.NewRecorder())

			token, kind, err := svc.getRequestCredential(context.Background(), c, account)

			require.NoError(t, err)
			require.Equal(t, "refresh-won-token", token)
			require.Equal(t, "oauth", kind)
			require.Zero(t, repo.setErrorCalls)
			require.Zero(t, repo.setTempUnschedCalls)
			require.Empty(t, cache.deletedKeys)
			require.False(t, svc.isOpenAIAccountRuntimeBlocked(account))
		})
	}
}

func TestCredentialFailureConditionalMutationLosesToConcurrentProxyRepair(t *testing.T) {
	for index, tt := range []struct {
		name       string
		refreshErr error
	}{
		{name: "permanent", refreshErr: infraerrors.New(http.StatusBadGateway, "GROK_OAUTH_TOKEN_REFRESH_FAILED", "invalid_grant")},
		{name: "transient", refreshErr: errors.New("temporary refresh transport failure")},
	} {
		t.Run(tt.name, func(t *testing.T) {
			account := expiredGrokOAuthAccountForCredentialTest(int64(780 + index))
			oldProxyID := int64(10)
			account.ProxyID = &oldProxyID
			account.Proxy = &Proxy{}
			repo := &tokenRefreshAccountRepo{}
			repo.accountsByID = map[int64]*Account{account.ID: account}
			repo.beforeConditionalState = func() {
				fresh := *account
				fresh.Credentials = shallowCopyMap(account.Credentials)
				repairedProxyID := int64(11)
				fresh.ProxyID = &repairedProxyID
				repo.accountsByID[account.ID] = &fresh
			}
			cache := &grokTokenCacheForProviderTest{lockResult: true}
			provider := NewGrokTokenProvider(repo, cache)
			provider.SetRefreshAPI(NewOAuthRefreshAPI(repo, cache), &tokenRefresherStub{err: tt.refreshErr})
			svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: provider}
			c, _ := gin.CreateTestContext(httptest.NewRecorder())

			_, _, err := svc.getRequestCredential(context.Background(), c, account)

			var failoverErr *UpstreamFailoverError
			require.ErrorAs(t, err, &failoverErr)
			require.Equal(t, GrokCredentialReasonAccountChanged, failoverErr.Reason)
			require.Equal(t, NextAccountRetry, failoverErr.NextAccountAction)
			require.Zero(t, repo.setErrorCalls)
			require.Zero(t, repo.setTempUnschedCalls)
			require.Empty(t, cache.deletedKeys)
			require.False(t, svc.isOpenAIAccountRuntimeBlocked(account))
		})
	}
}

func TestCredentialFailureConditionalMutationLosesToSameIDProxyRestoration(t *testing.T) {
	account := expiredGrokOAuthAccountForCredentialTest(790)
	proxyID := int64(10)
	account.ProxyID = &proxyID
	account.Proxy = nil
	repo := &tokenRefreshAccountRepo{}
	repo.accountsByID = map[int64]*Account{account.ID: account}
	repo.beforeConditionalState = func() {
		account.Proxy = &Proxy{ID: proxyID}
	}
	cache := &grokTokenCacheForProviderTest{lockResult: true}
	provider := NewGrokTokenProvider(repo, cache)
	svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: provider}
	c, _ := gin.CreateTestContext(httptest.NewRecorder())

	_, _, err := svc.getRequestCredential(context.Background(), c, account)

	var failoverErr *UpstreamFailoverError
	require.ErrorAs(t, err, &failoverErr)
	require.Equal(t, GrokCredentialReasonAccountChanged, failoverErr.Reason)
	require.Equal(t, NextAccountRetry, failoverErr.NextAccountAction)
	require.Zero(t, repo.setErrorCalls)
	require.Zero(t, repo.setTempUnschedCalls)
	require.Empty(t, cache.deletedKeys)
	require.False(t, svc.isOpenAIAccountRuntimeBlocked(account))
}

func TestCredentialFailureConditionalMutationLosesToConcurrentUnschedulableState(t *testing.T) {
	future := time.Now().Add(time.Hour)
	states := []struct {
		name   string
		mutate func(*Account)
	}{
		{name: "admin schedulable false", mutate: func(account *Account) { account.Schedulable = false }},
		{name: "temporary cooldown", mutate: func(account *Account) { account.TempUnschedulableUntil = &future }},
		{name: "rate limit cooldown", mutate: func(account *Account) { account.RateLimitResetAt = &future }},
		{name: "overload cooldown", mutate: func(account *Account) { account.OverloadUntil = &future }},
	}
	classes := []struct {
		name  string
		class grokCredentialFailureClass
	}{
		{name: "permanent", class: grokCredentialFailureClass{reason: GrokCredentialReasonRevoked, permanent: true}},
		{name: "transient", class: grokCredentialFailureClass{reason: GrokCredentialReasonRefreshTransient, transient: true}},
	}

	for classIndex, classCase := range classes {
		for stateIndex, stateCase := range states {
			t.Run(classCase.name+"/"+stateCase.name, func(t *testing.T) {
				account := expiredGrokOAuthAccountForCredentialTest(int64(791 + classIndex*10 + stateIndex))
				repo := &tokenRefreshAccountRepo{}
				repo.accountsByID = map[int64]*Account{account.ID: account}
				repo.beforeConditionalState = func() { stateCase.mutate(account) }
				svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: NewGrokTokenProvider(repo, &grokTokenCacheForProviderTest{})}

				token, err := svc.applyGrokCredentialAccountFailure(context.Background(), account, classCase.class)

				require.ErrorIs(t, err, errOAuthRefreshAccountStateChanged)
				require.Empty(t, token)
				require.Zero(t, repo.setErrorCalls)
				require.Zero(t, repo.setTempUnschedCalls)
				require.False(t, svc.isOpenAIAccountRuntimeBlocked(account))
			})
		}
	}
}

func TestCredentialFailureCASMissDoesNotRecoverIneligibleLatestCredential(t *testing.T) {
	future := time.Now().Add(time.Hour)
	states := []struct {
		name               string
		mutate             func(*OpenAIGatewayService, *Account)
		wantRuntimeBlocked bool
	}{
		{name: "disabled", mutate: func(_ *OpenAIGatewayService, account *Account) { account.Status = StatusDisabled }},
		{name: "not schedulable", mutate: func(_ *OpenAIGatewayService, account *Account) { account.Schedulable = false }},
		{name: "temporarily unschedulable", mutate: func(_ *OpenAIGatewayService, account *Account) { account.TempUnschedulableUntil = &future }},
		{name: "rate limited", mutate: func(_ *OpenAIGatewayService, account *Account) { account.RateLimitResetAt = &future }},
		{name: "overloaded", mutate: func(_ *OpenAIGatewayService, account *Account) { account.OverloadUntil = &future }},
		{
			name: "independently runtime blocked",
			mutate: func(svc *OpenAIGatewayService, account *Account) {
				svc.BlockAccountScheduling(account, time.Now().Add(24*time.Hour), "independent")
			},
			wantRuntimeBlocked: true,
		},
	}
	classes := []struct {
		name  string
		class grokCredentialFailureClass
	}{
		{name: "permanent", class: grokCredentialFailureClass{reason: GrokCredentialReasonRevoked, permanent: true}},
		{name: "transient", class: grokCredentialFailureClass{reason: GrokCredentialReasonRefreshTransient, transient: true}},
	}

	for classIndex, classCase := range classes {
		for stateIndex, stateCase := range states {
			t.Run(classCase.name+"/"+stateCase.name, func(t *testing.T) {
				account := expiredGrokOAuthAccountForCredentialTest(int64(800 + classIndex*20 + stateIndex))
				repo := &tokenRefreshAccountRepo{}
				repo.accountsByID = map[int64]*Account{account.ID: account}
				svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: NewGrokTokenProvider(repo, &grokTokenCacheForProviderTest{})}
				repo.beforeConditionalState = func() {
					latest := *account
					latest.Credentials = shallowCopyMap(account.Credentials)
					latest.Credentials["access_token"] = "fresh-but-ineligible-token"
					latest.Credentials["refresh_token"] = "fresh-but-ineligible-refresh"
					latest.Credentials["expires_at"] = time.Now().Add(2 * time.Hour).UTC().Format(time.RFC3339)
					latest.Credentials["_token_version"] = time.Now().UnixMilli()
					stateCase.mutate(svc, &latest)
					repo.accountsByID[account.ID] = &latest
				}

				token, err := svc.applyGrokCredentialAccountFailure(context.Background(), account, classCase.class)

				require.ErrorIs(t, err, errOAuthRefreshAccountStateChanged)
				require.Empty(t, token)
				require.Zero(t, repo.setErrorCalls)
				require.Zero(t, repo.setTempUnschedCalls)
				require.Equal(t, stateCase.wantRuntimeBlocked, svc.isOpenAIAccountRuntimeBlocked(account))
			})
		}
	}
}

func TestGetRequestCredentialSharedCredentialPersistenceFailureStopsWithoutAccountMutation(t *testing.T) {
	account := expiredGrokOAuthAccountForCredentialTest(782)
	repo := &tokenRefreshAccountRepo{conditionalSuccessErr: errors.New("database unavailable")}
	repo.accountsByID = map[int64]*Account{account.ID: account}
	cache := &grokTokenCacheForProviderTest{lockResult: true}
	provider := NewGrokTokenProvider(repo, cache)
	provider.SetRefreshAPI(NewOAuthRefreshAPI(repo, cache), &tokenRefresherStub{credentials: map[string]any{
		"access_token":  "new-access-token",
		"refresh_token": "new-refresh-token",
		"expires_at":    time.Now().Add(time.Hour).UTC().Format(time.RFC3339),
	}})
	svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: provider}
	c, _ := gin.CreateTestContext(httptest.NewRecorder())

	_, _, err := svc.getRequestCredential(context.Background(), c, account)

	var failoverErr *UpstreamFailoverError
	require.ErrorAs(t, err, &failoverErr)
	require.Equal(t, GatewayFailureScopeProvider, failoverErr.Scope)
	require.Equal(t, GrokCredentialReasonProviderDown, failoverErr.Reason)
	require.Equal(t, NextAccountStop, failoverErr.NextAccountAction)
	require.Equal(t, 1, repo.conditionalSuccessCalls)
	require.Zero(t, repo.updateCredentialsCalls)
	require.Zero(t, repo.setErrorCalls)
	require.Zero(t, repo.setTempUnschedCalls)
	require.Empty(t, cache.deletedKeys)
	require.False(t, svc.isOpenAIAccountRuntimeBlocked(account))
}

func TestGetRequestCredentialRecoversConcurrentRefreshWithoutFailover(t *testing.T) {
	gin.SetMode(gin.TestMode)
	account := expiredGrokOAuthAccountForCredentialTest(733)
	latest := *account
	latest.Credentials = shallowCopyMap(account.Credentials)
	latest.Credentials["access_token"] = "fresh-concurrent-access"
	latest.Credentials["refresh_token"] = "fresh-concurrent-refresh"
	latest.Credentials["expires_at"] = time.Now().Add(2 * time.Hour).UTC().Format(time.RFC3339)
	latest.Credentials["_token_version"] = time.Now().UnixMilli()
	baseRepo := &tokenRefreshAccountRepo{}
	baseRepo.accountsByID = map[int64]*Account{account.ID: account}
	repo := &grokCredentialSequencedRepo{tokenRefreshAccountRepo: baseRepo, latest: &latest}
	cache := &grokTokenCacheForProviderTest{lockResult: true}
	provider := NewGrokTokenProvider(repo, cache)
	provider.SetRefreshAPI(NewOAuthRefreshAPI(repo, cache), &tokenRefresherStub{
		err: infraerrors.New(http.StatusForbidden, "GROK_OAUTH_ENTITLEMENT_DENIED", "access_denied"),
	})
	svc := &OpenAIGatewayService{accountRepo: repo, grokTokenProvider: provider}
	c, _ := gin.CreateTestContext(httptest.NewRecorder())

	token, kind, err := svc.getRequestCredential(context.Background(), c, account)

	require.NoError(t, err)
	require.Equal(t, "fresh-concurrent-access", token)
	require.Equal(t, "oauth", kind)
	require.Zero(t, baseRepo.setErrorCalls)
	require.Zero(t, baseRepo.setTempUnschedCalls)
	require.Empty(t, cache.deletedKeys)
	require.False(t, svc.isOpenAIAccountRuntimeBlocked(account))
	_, hasEvents := c.Get(OpsUpstreamErrorsKey)
	require.False(t, hasEvents)
}

func expiredGrokOAuthAccountForCredentialTest(id int64) *Account {
	return &Account{
		ID:          id,
		Platform:    PlatformGrok,
		Type:        AccountTypeOAuth,
		Status:      StatusActive,
		Schedulable: true,
		Credentials: map[string]any{
			"access_token":  "expired-access-token",
			"refresh_token": "refresh-token",
			"expires_at":    time.Now().Add(-time.Minute).UTC().Format(time.RFC3339),
			"base_url":      xai.DefaultCLIBaseURL,
		},
	}
}
