/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import * as path from 'node:path';
import { loadConfig } from './config.js';
import { FileDiscoveryService, getCodeAssistServer, Config, ExperimentFlags, fetchAdminControlsOnce, } from '@google/gemini-cli-core';
// Mock dependencies
vi.mock('@google/gemini-cli-core', async (importOriginal) => {
    const actual = await importOriginal();
    return {
        ...actual,
        Config: vi.fn().mockImplementation((params) => {
            const mockConfig = {
                ...params,
                initialize: vi.fn(),
                refreshAuth: vi.fn(),
                getExperiments: vi.fn().mockReturnValue({
                    flags: {
                        [actual.ExperimentFlags.ENABLE_ADMIN_CONTROLS]: {
                            boolValue: false,
                        },
                    },
                }),
                getRemoteAdminSettings: vi.fn(),
                setRemoteAdminSettings: vi.fn(),
            };
            return mockConfig;
        }),
        loadServerHierarchicalMemory: vi.fn().mockResolvedValue({
            memoryContent: { global: '', extension: '', project: '' },
            fileCount: 0,
            filePaths: [],
        }),
        startupProfiler: {
            flush: vi.fn(),
        },
        FileDiscoveryService: vi.fn(),
        getCodeAssistServer: vi.fn(),
        fetchAdminControlsOnce: vi.fn(),
        coreEvents: {
            emitAdminSettingsChanged: vi.fn(),
        },
    };
});
vi.mock('../utils/logger.js', () => ({
    logger: {
        info: vi.fn(),
        error: vi.fn(),
    },
}));
describe('loadConfig', () => {
    const mockSettings = {};
    const mockExtensionLoader = {};
    const taskId = 'test-task-id';
    beforeEach(() => {
        vi.clearAllMocks();
        process.env['GEMINI_API_KEY'] = 'test-key';
    });
    afterEach(() => {
        delete process.env['CUSTOM_IGNORE_FILE_PATHS'];
        delete process.env['GEMINI_API_KEY'];
    });
    describe('admin settings overrides', () => {
        it('should not fetch admin controls if experiment is disabled', async () => {
            await loadConfig(mockSettings, mockExtensionLoader, taskId);
            expect(fetchAdminControlsOnce).not.toHaveBeenCalled();
        });
        describe('when admin controls experiment is enabled', () => {
            beforeEach(() => {
                // We need to cast to any here to modify the mock implementation
                // eslint-disable-next-line @typescript-eslint/no-explicit-any
                Config.mockImplementation((params) => {
                    const mockConfig = {
                        ...params,
                        initialize: vi.fn(),
                        refreshAuth: vi.fn(),
                        getExperiments: vi.fn().mockReturnValue({
                            flags: {
                                [ExperimentFlags.ENABLE_ADMIN_CONTROLS]: {
                                    boolValue: true,
                                },
                            },
                        }),
                        getRemoteAdminSettings: vi.fn().mockReturnValue({}),
                        setRemoteAdminSettings: vi.fn(),
                    };
                    return mockConfig;
                });
            });
            it('should fetch admin controls and apply them', async () => {
                const mockAdminSettings = {
                    mcpSetting: {
                        mcpEnabled: false,
                    },
                    cliFeatureSetting: {
                        extensionsSetting: {
                            extensionsEnabled: false,
                        },
                    },
                    strictModeDisabled: false,
                };
                vi.mocked(fetchAdminControlsOnce).mockResolvedValue(mockAdminSettings);
                await loadConfig(mockSettings, mockExtensionLoader, taskId);
                expect(Config).toHaveBeenLastCalledWith(expect.objectContaining({
                    disableYoloMode: !mockAdminSettings.strictModeDisabled,
                    mcpEnabled: mockAdminSettings.mcpSetting?.mcpEnabled,
                    extensionsEnabled: mockAdminSettings.cliFeatureSetting?.extensionsSetting
                        ?.extensionsEnabled,
                }));
            });
            it('should treat unset admin settings as false when admin settings are passed', async () => {
                const mockAdminSettings = {
                    mcpSetting: {
                        mcpEnabled: true,
                    },
                };
                vi.mocked(fetchAdminControlsOnce).mockResolvedValue(mockAdminSettings);
                await loadConfig(mockSettings, mockExtensionLoader, taskId);
                expect(Config).toHaveBeenLastCalledWith(expect.objectContaining({
                    disableYoloMode: !false,
                    mcpEnabled: mockAdminSettings.mcpSetting?.mcpEnabled,
                    extensionsEnabled: undefined,
                }));
            });
            it('should not pass default unset admin settings when no admin settings are present', async () => {
                const mockAdminSettings = {};
                vi.mocked(fetchAdminControlsOnce).mockResolvedValue(mockAdminSettings);
                await loadConfig(mockSettings, mockExtensionLoader, taskId);
                expect(Config).toHaveBeenLastCalledWith(expect.objectContaining({}));
            });
            it('should fetch admin controls using the code assist server when available', async () => {
                const mockAdminSettings = {
                    mcpSetting: {
                        mcpEnabled: true,
                    },
                    strictModeDisabled: true,
                };
                const mockCodeAssistServer = { projectId: 'test-project' };
                vi.mocked(getCodeAssistServer).mockReturnValue(
                // eslint-disable-next-line @typescript-eslint/no-explicit-any
                mockCodeAssistServer);
                vi.mocked(fetchAdminControlsOnce).mockResolvedValue(mockAdminSettings);
                await loadConfig(mockSettings, mockExtensionLoader, taskId);
                expect(fetchAdminControlsOnce).toHaveBeenCalledWith(mockCodeAssistServer, true);
                expect(Config).toHaveBeenLastCalledWith(expect.objectContaining({
                    disableYoloMode: !mockAdminSettings.strictModeDisabled,
                    mcpEnabled: mockAdminSettings.mcpSetting?.mcpEnabled,
                    extensionsEnabled: undefined,
                }));
            });
        });
    });
    it('should set customIgnoreFilePaths when CUSTOM_IGNORE_FILE_PATHS env var is present', async () => {
        const testPath = '/tmp/ignore';
        process.env['CUSTOM_IGNORE_FILE_PATHS'] = testPath;
        const config = await loadConfig(mockSettings, mockExtensionLoader, taskId);
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        expect(config.fileFiltering.customIgnoreFilePaths).toEqual([
            testPath,
        ]);
    });
    it('should set customIgnoreFilePaths when settings.fileFiltering.customIgnoreFilePaths is present', async () => {
        const testPath = '/settings/ignore';
        const settings = {
            fileFiltering: {
                customIgnoreFilePaths: [testPath],
            },
        };
        const config = await loadConfig(settings, mockExtensionLoader, taskId);
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        expect(config.fileFiltering.customIgnoreFilePaths).toEqual([
            testPath,
        ]);
    });
    it('should merge customIgnoreFilePaths from settings and env var', async () => {
        const envPath = '/env/ignore';
        const settingsPath = '/settings/ignore';
        process.env['CUSTOM_IGNORE_FILE_PATHS'] = envPath;
        const settings = {
            fileFiltering: {
                customIgnoreFilePaths: [settingsPath],
            },
        };
        const config = await loadConfig(settings, mockExtensionLoader, taskId);
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        expect(config.fileFiltering.customIgnoreFilePaths).toEqual([
            settingsPath,
            envPath,
        ]);
    });
    it('should split CUSTOM_IGNORE_FILE_PATHS using system delimiter', async () => {
        const paths = ['/path/one', '/path/two'];
        process.env['CUSTOM_IGNORE_FILE_PATHS'] = paths.join(path.delimiter);
        const config = await loadConfig(mockSettings, mockExtensionLoader, taskId);
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        expect(config.fileFiltering.customIgnoreFilePaths).toEqual(paths);
    });
    it('should have empty customIgnoreFilePaths when both are missing', async () => {
        const config = await loadConfig(mockSettings, mockExtensionLoader, taskId);
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        expect(config.fileFiltering.customIgnoreFilePaths).toEqual([]);
    });
    it('should initialize FileDiscoveryService with correct options', async () => {
        const testPath = '/tmp/ignore';
        process.env['CUSTOM_IGNORE_FILE_PATHS'] = testPath;
        const settings = {
            fileFiltering: {
                respectGitIgnore: false,
            },
        };
        await loadConfig(settings, mockExtensionLoader, taskId);
        expect(FileDiscoveryService).toHaveBeenCalledWith(expect.any(String), {
            respectGitIgnore: false,
            respectGeminiIgnore: undefined,
            customIgnoreFilePaths: [testPath],
        });
    });
});
//# sourceMappingURL=config.test.js.map