/**
 * @license
 * Copyright 2025 Vybestack LLC
 * SPDX-License-Identifier: Apache-2.0
 */
/**
 * Tests for Phase 33: Factory Function + Detection Wiring
 *
 * @plan:PLAN-20250214-CREDPROXY.P33
 *
 * Verifies that consumer code uses the credential store factory functions
 * instead of directly instantiating KeyringTokenStore or calling getProviderKeyStorage().
 */
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { createTokenStore, createProviderKeyStorage, resetFactorySingletons, } from '../credential-store-factory.js';
import { OAuthManager } from '../../oauth-manager.js';
describe('Factory Detection Wiring (P33)', () => {
    let originalSocketEnv;
    beforeEach(() => {
        originalSocketEnv = process.env.LLXPRT_CREDENTIAL_SOCKET;
        resetFactorySingletons();
    });
    afterEach(() => {
        if (originalSocketEnv !== undefined) {
            process.env.LLXPRT_CREDENTIAL_SOCKET = originalSocketEnv;
        }
        else {
            delete process.env.LLXPRT_CREDENTIAL_SOCKET;
        }
        resetFactorySingletons();
    });
    describe('createTokenStore factory', () => {
        it('returns KeyringTokenStore when LLXPRT_CREDENTIAL_SOCKET is not set', () => {
            delete process.env.LLXPRT_CREDENTIAL_SOCKET;
            const store = createTokenStore();
            // KeyringTokenStore has specific methods
            expect(store).toBeDefined();
            expect(typeof store.getToken).toBe('function');
            expect(typeof store.saveToken).toBe('function');
            expect(typeof store.removeToken).toBe('function');
            expect(typeof store.listBuckets).toBe('function');
        });
        it('returns ProxyTokenStore when LLXPRT_CREDENTIAL_SOCKET is set', () => {
            process.env.LLXPRT_CREDENTIAL_SOCKET = '/tmp/test-socket.sock';
            const store = createTokenStore();
            // ProxyTokenStore has the same interface but different implementation
            expect(store).toBeDefined();
            expect(typeof store.getToken).toBe('function');
            expect(typeof store.saveToken).toBe('function');
            expect(typeof store.removeToken).toBe('function');
            expect(typeof store.listBuckets).toBe('function');
        });
        it('returns singleton instances (caches per mode)', () => {
            delete process.env.LLXPRT_CREDENTIAL_SOCKET;
            const store1 = createTokenStore();
            const store2 = createTokenStore();
            expect(store1).toBe(store2);
        });
        it('returns different singletons for different modes', () => {
            delete process.env.LLXPRT_CREDENTIAL_SOCKET;
            const directStore = createTokenStore();
            process.env.LLXPRT_CREDENTIAL_SOCKET = '/tmp/test-socket.sock';
            const proxyStore = createTokenStore();
            expect(directStore).not.toBe(proxyStore);
        });
    });
    describe('createProviderKeyStorage factory', () => {
        it('returns direct storage when LLXPRT_CREDENTIAL_SOCKET is not set', () => {
            delete process.env.LLXPRT_CREDENTIAL_SOCKET;
            const storage = createProviderKeyStorage();
            expect(storage).toBeDefined();
            expect(typeof storage.getKey).toBe('function');
            expect(typeof storage.saveKey).toBe('function');
            expect(typeof storage.deleteKey).toBe('function');
            expect(typeof storage.listKeys).toBe('function');
        });
        it('returns ProxyProviderKeyStorage when LLXPRT_CREDENTIAL_SOCKET is set', () => {
            process.env.LLXPRT_CREDENTIAL_SOCKET = '/tmp/test-socket.sock';
            const storage = createProviderKeyStorage();
            expect(storage).toBeDefined();
            expect(typeof storage.getKey).toBe('function');
            expect(typeof storage.listKeys).toBe('function');
            // ProxyProviderKeyStorage may have read-only behavior
        });
        it('returns singleton instances (caches per mode)', () => {
            delete process.env.LLXPRT_CREDENTIAL_SOCKET;
            const storage1 = createProviderKeyStorage();
            const storage2 = createProviderKeyStorage();
            expect(storage1).toBe(storage2);
        });
    });
    describe('OAuthManager proactive renewal (R16.8)', () => {
        it('OAuthManager skips proactive renewal scheduling in proxy mode', async () => {
            // Set proxy mode
            process.env.LLXPRT_CREDENTIAL_SOCKET = '/tmp/test-socket.sock';
            const tokenStore = createTokenStore();
            const oauthManager = new OAuthManager(tokenStore);
            // Access the private proactiveRenewals map to verify no timers are set
            const proactiveRenewals = oauthManager.proactiveRenewals;
            // Initially empty
            expect(proactiveRenewals.size).toBe(0);
            // After getting a token (if we could mock it), it should still be empty in proxy mode
            // The actual scheduling is internal, but we can verify the guard condition exists
            // by checking that no renewals are scheduled even after token operations
        });
        it('OAuthManager schedules proactive renewal in direct mode', () => {
            // Unset proxy mode
            delete process.env.LLXPRT_CREDENTIAL_SOCKET;
            const tokenStore = createTokenStore();
            const oauthManager = new OAuthManager(tokenStore);
            // Access the private proactiveRenewals map
            const proactiveRenewals = oauthManager.proactiveRenewals;
            // Initially empty (no tokens to renew)
            expect(proactiveRenewals.size).toBe(0);
            // In direct mode, renewals would be scheduled when tokens are obtained
            // This test confirms the OAuthManager is configured for direct mode
        });
    });
    describe('resetFactorySingletons', () => {
        it('clears cached TokenStore instances', () => {
            delete process.env.LLXPRT_CREDENTIAL_SOCKET;
            const store1 = createTokenStore();
            resetFactorySingletons();
            const store2 = createTokenStore();
            // After reset, a new KeyringTokenStore instance should be created
            expect(store1).not.toBe(store2);
        });
        it('clears cached proxy instances when in proxy mode', () => {
            process.env.LLXPRT_CREDENTIAL_SOCKET = '/tmp/test-socket.sock';
            const store1 = createTokenStore();
            const storage1 = createProviderKeyStorage();
            resetFactorySingletons();
            const store2 = createTokenStore();
            const storage2 = createProviderKeyStorage();
            // After reset, new proxy instances should be created
            expect(store1).not.toBe(store2);
            expect(storage1).not.toBe(storage2);
        });
        it('factory internal cache is cleared for direct key storage', () => {
            delete process.env.LLXPRT_CREDENTIAL_SOCKET;
            const storage1 = createProviderKeyStorage();
            resetFactorySingletons();
            const storage2 = createProviderKeyStorage();
            // Note: In direct mode, createProviderKeyStorage() uses getProviderKeyStorage()
            // which is itself a singleton from core. The factory resets its internal reference,
            // but getProviderKeyStorage() always returns the same singleton.
            // This test verifies the factory's caching behavior is reset.
            expect(storage1).toBe(storage2); // Same singleton from core
        });
    });
    describe('Consumer code wiring verification', () => {
        /**
         * These tests verify that the consumer modules have been correctly updated
         * to use the factory functions. We check this by verifying that:
         * 1. The factory functions exist and work correctly
         * 2. The factory returns appropriate types based on environment
         *
         * The actual consumer code changes are verified by the TypeScript compiler
         * since the imports will fail if the factory functions don't exist.
         */
        it('verifies factory functions are importable', async () => {
            // This test verifies the factory functions can be imported
            // If the module structure is wrong, this import will fail
            const factory = await import('../credential-store-factory.js');
            expect(typeof factory.createTokenStore).toBe('function');
            expect(typeof factory.createProviderKeyStorage).toBe('function');
            expect(typeof factory.resetFactorySingletons).toBe('function');
        });
        it('verifies token store factory returns TokenStore interface', () => {
            delete process.env.LLXPRT_CREDENTIAL_SOCKET;
            const store = createTokenStore();
            // TokenStore interface methods
            expect(typeof store.getToken).toBe('function');
            expect(typeof store.saveToken).toBe('function');
            expect(typeof store.removeToken).toBe('function');
            expect(typeof store.listProviders).toBe('function');
            expect(typeof store.listBuckets).toBe('function');
        });
        it('verifies provider key storage factory returns ProviderKeyStorage interface', () => {
            delete process.env.LLXPRT_CREDENTIAL_SOCKET;
            const storage = createProviderKeyStorage();
            // ProviderKeyStorage interface methods
            expect(typeof storage.getKey).toBe('function');
            expect(typeof storage.saveKey).toBe('function');
            expect(typeof storage.deleteKey).toBe('function');
            expect(typeof storage.hasKey).toBe('function');
            expect(typeof storage.listKeys).toBe('function');
        });
    });
});
//# sourceMappingURL=factory-detection-wiring.test.js.map