/**
 * @license
 * Copyright 2025 Vybestack LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import { OAuthManager } from '../oauth-manager.js';
import { MessageBus, PolicyEngine } from '@vybestack/llxprt-code-core';
/**
 * Issue #828: User Declined Auth Prompt Tracking
 *
 * When the user cancels the BucketAuthConfirmation dialog,
 * subsequent auth attempts in the same session should skip the dialog
 * and proceed directly.
 */
const mockEphemeralSettings = new Map();
function setMockEphemeralSetting(key, value) {
    mockEphemeralSettings.set(key, value);
}
function clearMockEphemeralSettings() {
    mockEphemeralSettings.clear();
}
// Mock the runtime settings module
vi.mock('../../runtime/runtimeSettings.js', () => ({
    getEphemeralSetting: (key) => mockEphemeralSettings.get(key),
    getCliRuntimeServices: () => ({
        settingsService: {
            getCurrentProfileName: () => null,
            get: () => null,
        },
    }),
    getCliProviderManager: () => ({
        getProviderByName: () => null,
    }),
    getCliRuntimeContext: () => ({
        runtimeId: 'test-runtime',
    }),
}));
function createMockTokenStore() {
    const tokens = new Map();
    return {
        saveToken: vi.fn(async (provider, token, bucket) => {
            const key = `${provider}:${bucket ?? 'default'}`;
            tokens.set(key, token);
        }),
        getToken: vi.fn(async (provider, bucket) => {
            const key = `${provider}:${bucket ?? 'default'}`;
            return tokens.get(key) ?? null;
        }),
        removeToken: vi.fn(async () => { }),
        listProviders: vi.fn(async () => []),
        listBuckets: vi.fn(async () => []),
        getBucketStats: vi.fn(async (_provider, bucket) => ({
            bucket,
            requestCount: 0,
            percentage: 0,
            lastUsed: undefined,
        })),
        acquireRefreshLock: vi.fn(async () => true),
        releaseRefreshLock: vi.fn(async () => { }),
        acquireAuthLock: vi.fn(async () => true),
        releaseAuthLock: vi.fn(async () => undefined),
    };
}
function createMockProvider(name) {
    return {
        name,
        initiateAuth: vi.fn(async () => ({
            access_token: 'mock-token-from-initiate',
            refresh_token: 'mock-refresh',
            expiry: Math.floor(Date.now() / 1000) + 3600,
            token_type: 'Bearer',
        })),
        getToken: vi.fn(async () => ({
            access_token: 'mock-token',
            refresh_token: 'mock-refresh',
            expiry: Math.floor(Date.now() / 1000) + 3600,
            token_type: 'Bearer',
        })),
        refreshToken: vi.fn(async () => null),
    };
}
describe('Issue #828: User Declined Auth Prompt Tracking', () => {
    let tokenStore;
    let manager;
    let mockProvider;
    beforeEach(() => {
        vi.clearAllMocks();
        clearMockEphemeralSettings();
        tokenStore = createMockTokenStore();
        manager = new OAuthManager(tokenStore);
        mockProvider = createMockProvider('anthropic');
        manager.registerProvider(mockProvider);
    });
    afterEach(() => {
        vi.restoreAllMocks();
    });
    it('should still show confirmation on first attempt', async () => {
        setMockEphemeralSetting('auth-bucket-prompt', true);
        let confirmationRequested = false;
        const policyEngine = new PolicyEngine();
        const messageBus = new MessageBus(policyEngine);
        messageBus.requestBucketAuthConfirmation = vi.fn(async () => {
            confirmationRequested = true;
            return true; // User approves
        });
        manager.setMessageBus(() => messageBus);
        await manager.toggleOAuthEnabled('anthropic');
        await manager.getToken('anthropic');
        // First attempt should show the confirmation dialog
        expect(confirmationRequested).toBe(true);
        expect(messageBus.requestBucketAuthConfirmation).toHaveBeenCalled();
    });
    it('should skip BucketAuthConfirmation after user cancels once in session', async () => {
        setMockEphemeralSetting('auth-bucket-prompt', true);
        let confirmationCount = 0;
        const policyEngine = new PolicyEngine();
        const messageBus = new MessageBus(policyEngine);
        messageBus.requestBucketAuthConfirmation = vi.fn(async () => {
            confirmationCount++;
            if (confirmationCount === 1) {
                return false; // User declines on first attempt
            }
            return true;
        });
        manager.setMessageBus(() => messageBus);
        await manager.toggleOAuthEnabled('anthropic');
        // First attempt - user declines
        try {
            await manager.getToken('anthropic');
        }
        catch {
            // Expected: multi-bucket auth cancelled
        }
        // Second attempt - should skip the dialog and proceed directly
        try {
            await manager.getToken('anthropic');
        }
        catch {
            // May throw if auth fails
        }
        // The confirmation dialog should NOT have been shown again
        // (confirmationCount should still be 1 from the first attempt)
        expect(confirmationCount).toBe(1);
    });
    it('should reset declined state on new OAuthManager instance', async () => {
        setMockEphemeralSetting('auth-bucket-prompt', true);
        const policyEngine = new PolicyEngine();
        const messageBus = new MessageBus(policyEngine);
        let firstManagerConfirmationCount = 0;
        messageBus.requestBucketAuthConfirmation = vi.fn(async () => {
            firstManagerConfirmationCount++;
            return false; // User declines
        });
        manager.setMessageBus(() => messageBus);
        await manager.toggleOAuthEnabled('anthropic');
        // First manager, first attempt - user declines
        try {
            await manager.getToken('anthropic');
        }
        catch {
            // Expected
        }
        expect(firstManagerConfirmationCount).toBe(1);
        // Create a new OAuthManager (new session)
        const newManager = new OAuthManager(tokenStore);
        const newMockProvider = createMockProvider('anthropic');
        newManager.registerProvider(newMockProvider);
        let secondManagerConfirmationCount = 0;
        const newMessageBus = new MessageBus(policyEngine);
        newMessageBus.requestBucketAuthConfirmation = vi.fn(async () => {
            secondManagerConfirmationCount++;
            return true; // User approves
        });
        newManager.setMessageBus(() => newMessageBus);
        await newManager.toggleOAuthEnabled('anthropic');
        // New manager should show dialog again (fresh session)
        await newManager.getToken('anthropic');
        expect(secondManagerConfirmationCount).toBe(1);
    });
});
//# sourceMappingURL=oauth-manager.user-declined.spec.js.map