/**
 * @license
 * Copyright 2025 Vybestack LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { BucketFailoverHandlerImpl } from './BucketFailoverHandlerImpl.js';
import { OAuthManager } from './oauth-manager.js';
class MemoryTokenStore {
    tokens = new Map();
    toKey(provider, bucket) {
        return `${provider}:${bucket ?? 'default'}`;
    }
    async saveToken(provider, token, bucket) {
        this.tokens.set(this.toKey(provider, bucket), token);
    }
    async getToken(provider, bucket) {
        return this.tokens.get(this.toKey(provider, bucket)) ?? null;
    }
    async removeToken(provider, bucket) {
        this.tokens.delete(this.toKey(provider, bucket));
    }
    async listProviders() {
        return [];
    }
    async listBuckets() {
        return [];
    }
    async getBucketStats() {
        return null;
    }
}
function makeToken(accessToken) {
    return {
        access_token: accessToken,
        refresh_token: `refresh-${accessToken}`,
        expiry: Math.floor(Date.now() / 1000) + 3600,
        token_type: 'Bearer',
        scope: '',
    };
}
describe('BucketFailoverHandlerImpl', () => {
    let tokenStore;
    let oauthManager;
    beforeEach(() => {
        tokenStore = new MemoryTokenStore();
        oauthManager = new OAuthManager(tokenStore);
        const provider = {
            name: 'anthropic',
            initiateAuth: vi.fn(async () => undefined),
            getToken: vi.fn(async () => null),
            refreshIfNeeded: vi.fn(async () => null),
        };
        oauthManager.registerProvider(provider);
    });
    it('sets the session bucket to the first bucket when none is set', async () => {
        await tokenStore.saveToken('anthropic', makeToken('t1'), 'bucket-a');
        expect(oauthManager.getSessionBucket('anthropic')).toBeUndefined();
        const handler = new BucketFailoverHandlerImpl(['bucket-a', 'bucket-b'], 'anthropic', oauthManager);
        expect(oauthManager.getSessionBucket('anthropic')).toBe('bucket-a');
        expect(handler.getCurrentBucket()).toBe('bucket-a');
    });
    it('aligns the handler index with an existing session bucket', async () => {
        await tokenStore.saveToken('anthropic', makeToken('t1'), 'bucket-a');
        await tokenStore.saveToken('anthropic', makeToken('t2'), 'bucket-b');
        oauthManager.setSessionBucket('anthropic', 'bucket-b');
        const handler = new BucketFailoverHandlerImpl(['bucket-a', 'bucket-b'], 'anthropic', oauthManager);
        expect(handler.getCurrentBucket()).toBe('bucket-b');
    });
    it('skips buckets with missing tokens and updates session bucket on success', async () => {
        await tokenStore.saveToken('anthropic', makeToken('t1'), 'bucket-a');
        await tokenStore.saveToken('anthropic', makeToken('t3'), 'bucket-c');
        oauthManager.setSessionBucket('anthropic', 'bucket-a');
        const handler = new BucketFailoverHandlerImpl(['bucket-a', 'bucket-b', 'bucket-c'], 'anthropic', oauthManager);
        const result = await handler.tryFailover();
        expect(result).toBe(true);
        expect(handler.getCurrentBucket()).toBe('bucket-c');
        expect(oauthManager.getSessionBucket('anthropic')).toBe('bucket-c');
    });
    it('returns false when no further buckets are usable', async () => {
        await tokenStore.saveToken('anthropic', makeToken('t1'), 'bucket-a');
        oauthManager.setSessionBucket('anthropic', 'bucket-a');
        const handler = new BucketFailoverHandlerImpl(['bucket-a', 'bucket-b'], 'anthropic', oauthManager);
        const result = await handler.tryFailover();
        expect(result).toBe(false);
        expect(handler.getCurrentBucket()).toBe('bucket-a');
        expect(oauthManager.getSessionBucket('anthropic')).toBe('bucket-a');
    });
});
//# sourceMappingURL=BucketFailoverHandlerImpl.spec.js.map