/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import { createProviderRuntimeContext, peekActiveProviderRuntimeContext, setActiveProviderRuntimeContext, } from '../runtime/providerRuntimeContext.js';
import { SettingsService } from '../settings/SettingsService.js';
function createSpy(impl) {
    const calls = [];
    let implementation = impl ?? (() => undefined);
    const spy = ((...args) => {
        calls.push(args);
        return implementation(...args);
    });
    spy.calls = calls;
    spy.mockImplementation = (fn) => {
        implementation = fn;
        return spy;
    };
    spy.mockReturnValue = (value) => {
        implementation = () => value;
        return spy;
    };
    spy.mockReturnValueOnce = (value) => {
        let called = false;
        implementation = (..._fnArgs) => {
            if (called) {
                return value;
            }
            called = true;
            return value;
        };
        return spy;
    };
    spy.mockClear = () => {
        calls.length = 0;
        implementation = impl ?? (() => undefined);
        return spy;
    };
    return spy;
}
/**
 * Creates a provider instance while binding it to a fresh runtime context.
 * The runtime is only active during instantiation so the provider captures
 * the injected settings service without polluting global state.
 */
export function createProviderWithRuntime(factory, options = {}) {
    const previousContext = peekActiveProviderRuntimeContext();
    const settingsService = options.settingsService ?? new SettingsService();
    const runtime = createProviderRuntimeContext({
        settingsService,
        config: options.config,
        runtimeId: options.runtimeId ?? 'test.provider.runtime',
        metadata: {
            source: 'test-utils#createProviderWithRuntime',
            ...(options.metadata ?? {}),
        },
    });
    setActiveProviderRuntimeContext(runtime);
    try {
        const provider = factory({ runtime, settingsService });
        return { provider, runtime, settingsService };
    }
    finally {
        setActiveProviderRuntimeContext(previousContext ?? null);
    }
}
/**
 * Produces a lightweight Config stub sufficient for provider runtime tests.
 */
export function createRuntimeConfigStub(settingsService, overrides = {}) {
    const noop = () => { };
    const base = {
        getConversationLoggingEnabled: () => false,
        setConversationLoggingEnabled: noop,
        getTelemetryLogPromptsEnabled: () => false,
        setTelemetryLogPromptsEnabled: noop,
        getUsageStatisticsEnabled: () => false,
        setUsageStatisticsEnabled: noop,
        getDebugMode: () => false,
        setDebugMode: noop,
        getSessionId: () => 'test-session',
        setSessionId: noop,
        getFlashFallbackMode: () => 'off',
        setFlashFallbackMode: noop,
        getProvider: () => 'test-provider',
        setProvider: noop,
        getSettingsService: () => settingsService,
        getProviderSettings: () => ({}),
        setProviderSettings: noop,
        getProviderConfig: () => ({}),
        setProviderConfig: noop,
        resetProvider: noop,
        resetProviderSettings: noop,
        resetProviderConfig: noop,
        getActiveWorkspace: () => undefined,
        setActiveWorkspace: noop,
        clearActiveWorkspace: noop,
        getExtensionConfig: () => ({}),
        setExtensionConfig: noop,
        getFeatures: () => ({}),
        setFeatures: noop,
        getRedactionConfig: () => ({ replacements: [] }),
        setProviderManager: noop,
        getProviderManager: () => undefined,
        getProviderSetting: () => undefined,
        getEphemeralSettings: () => ({ model: 'test-model' }),
        getEphemeralSetting: () => undefined,
        setEphemeralSetting: noop,
        getUserMemory: () => '',
        setUserMemory: noop,
        getModel: () => 'test-model',
        setModel: noop,
        getQuotaErrorOccurred: () => false,
        setQuotaErrorOccurred: noop,
    };
    return Object.assign(base, overrides);
}
/**
 * Initializes a lightweight provider runtime context for test environments.
 * Returns the created settings service, config stub, and runtime context.
 */
export function initializeTestProviderRuntime(options = {}) {
    const settingsService = new SettingsService();
    const config = createRuntimeConfigStub(settingsService, {
        ...(options.configOverrides ?? {}),
    });
    const runtime = createProviderRuntimeContext({
        settingsService,
        config,
        runtimeId: options.runtimeId ??
            `test.provider.runtime.${Math.random().toString(36).slice(2, 10)}`,
        metadata: {
            source: 'test-utils#initializeTestProviderRuntime',
            ...(options.metadata ?? {}),
        },
    });
    setActiveProviderRuntimeContext(runtime);
    return { settingsService, config, runtime };
}
function requireVi() {
    const viGlobal = globalThis.vi;
    if (viGlobal) {
        return viGlobal;
    }
    return {
        fn: (impl) => createSpy(impl),
    };
}
function createDefaultProvider() {
    const vi = requireVi();
    return {
        name: 'test-provider',
        isDefault: true,
        getModels: vi.fn(async () => []),
        getDefaultModel: () => 'test-model',
        generateChatCompletion: vi.fn(async function* () {
            yield { speaker: 'ai', blocks: [] };
        }),
        getServerTools: () => [],
        invokeServerTool: vi.fn(),
    };
}
/**
 * Creates a Config stub and associated runtime wiring for GeminiChat tests.
 * The returned config exposes the minimal surface required by the class while
 * guaranteeing that runtime-aware helpers (e.g. getSettingsService) exist.
 */
export function createGeminiChatRuntime(options = {}) {
    const vi = requireVi();
    const settingsService = options.settingsService ?? new SettingsService();
    const runtime = createProviderRuntimeContext({
        settingsService,
        runtimeId: options.runtimeId ?? 'test.geminiChat.runtime',
        metadata: {
            source: 'test-utils#createGeminiChatRuntime',
            ...(options.metadata ?? {}),
        },
    });
    const provider = options.provider ?? createDefaultProvider();
    const providerManager = options.providerManager ??
        {
            getActiveProvider: vi.fn().mockReturnValue(provider),
        };
    let currentProviderName = provider.name;
    const getProviderSpy = vi.fn().mockImplementation(() => currentProviderName);
    const setProviderSpy = vi.fn().mockImplementation((next) => {
        if (typeof next === 'string') {
            currentProviderName = next;
        }
    });
    const baseConfig = {
        getSessionId: () => 'test-session-id',
        getTelemetryLogPromptsEnabled: () => true,
        getUsageStatisticsEnabled: () => true,
        getDebugMode: () => false,
        getContentGeneratorConfig: () => ({
            authType: 'oauth-personal',
            model: 'test-model',
        }),
        getModel: vi.fn().mockReturnValue('gemini-pro'),
        setModel: vi.fn(),
        getQuotaErrorOccurred: vi.fn().mockReturnValue(false),
        setQuotaErrorOccurred: vi.fn(),
        flashFallbackHandler: undefined,
        getEphemeralSettings: vi.fn().mockReturnValue({}),
        getEphemeralSetting: vi.fn().mockReturnValue(undefined),
        getProvider: getProviderSpy,
        setProvider: setProviderSpy,
        getProviderManager: vi.fn().mockReturnValue(providerManager),
        getSettingsService: vi.fn().mockReturnValue(settingsService),
    };
    const config = {
        ...baseConfig,
        ...(options.configOverrides ?? {}),
    };
    Object.assign(runtime, { config: config });
    return {
        config: config,
        provider,
        providerManager,
        settingsService,
        runtime,
    };
}
//# sourceMappingURL=runtime.js.map