/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest';
import { format } from 'node:util';
import { handleList, listCommand } from './list.js';
import { ExtensionManager } from '../../config/extension-manager.js';
import { loadSettings } from '../../config/settings.js';
import { getErrorMessage } from '../../utils/errors.js';
// Mock dependencies
const emitConsoleLog = vi.hoisted(() => vi.fn());
const debugLogger = vi.hoisted(() => ({
    log: vi.fn((message, ...args) => {
        emitConsoleLog('log', format(message, ...args));
    }),
    error: vi.fn((message, ...args) => {
        emitConsoleLog('error', format(message, ...args));
    }),
}));
vi.mock('@google/gemini-cli-core', async (importOriginal) => {
    const actual = await importOriginal();
    return {
        ...actual,
        coreEvents: {
            emitConsoleLog,
        },
        debugLogger,
    };
});
vi.mock('../../config/extension-manager.js');
vi.mock('../../config/settings.js');
vi.mock('../../utils/errors.js');
vi.mock('../../config/extensions/consent.js', () => ({
    requestConsentNonInteractive: vi.fn(),
}));
vi.mock('../../config/extensions/extensionSettings.js', () => ({
    promptForSetting: vi.fn(),
}));
vi.mock('../utils.js', () => ({
    exitCli: vi.fn(),
}));
describe('extensions list command', () => {
    const mockLoadSettings = vi.mocked(loadSettings);
    const mockGetErrorMessage = vi.mocked(getErrorMessage);
    const mockExtensionManager = vi.mocked(ExtensionManager);
    beforeEach(async () => {
        vi.clearAllMocks();
        mockLoadSettings.mockReturnValue({
            merged: {},
        });
    });
    afterEach(() => {
        vi.restoreAllMocks();
    });
    describe('handleList', () => {
        it('should log a message if no extensions are installed', async () => {
            const mockCwd = vi.spyOn(process, 'cwd').mockReturnValue('/test/dir');
            mockExtensionManager.prototype.loadExtensions = vi
                .fn()
                .mockResolvedValue([]);
            await handleList();
            expect(emitConsoleLog).toHaveBeenCalledWith('log', 'No extensions installed.');
            mockCwd.mockRestore();
        });
        it('should output empty JSON array if no extensions are installed and output-format is json', async () => {
            const mockCwd = vi.spyOn(process, 'cwd').mockReturnValue('/test/dir');
            mockExtensionManager.prototype.loadExtensions = vi
                .fn()
                .mockResolvedValue([]);
            await handleList({ outputFormat: 'json' });
            expect(emitConsoleLog).toHaveBeenCalledWith('log', '[]');
            mockCwd.mockRestore();
        });
        it('should list all installed extensions', async () => {
            const mockCwd = vi.spyOn(process, 'cwd').mockReturnValue('/test/dir');
            const extensions = [
                { name: 'ext1', version: '1.0.0' },
                { name: 'ext2', version: '2.0.0' },
            ];
            mockExtensionManager.prototype.loadExtensions = vi
                .fn()
                .mockResolvedValue(extensions);
            mockExtensionManager.prototype.toOutputString = vi.fn((ext) => `${ext.name}@${ext.version}`);
            await handleList();
            expect(emitConsoleLog).toHaveBeenCalledWith('log', 'ext1@1.0.0\n\next2@2.0.0');
            mockCwd.mockRestore();
        });
        it('should list all installed extensions in JSON format', async () => {
            const mockCwd = vi.spyOn(process, 'cwd').mockReturnValue('/test/dir');
            const extensions = [
                { name: 'ext1', version: '1.0.0' },
                { name: 'ext2', version: '2.0.0' },
            ];
            mockExtensionManager.prototype.loadExtensions = vi
                .fn()
                .mockResolvedValue(extensions);
            await handleList({ outputFormat: 'json' });
            expect(emitConsoleLog).toHaveBeenCalledWith('log', JSON.stringify(extensions, null, 2));
            mockCwd.mockRestore();
        });
        it('should log an error message and exit with code 1 when listing fails', async () => {
            const mockProcessExit = vi
                .spyOn(process, 'exit')
                .mockImplementation((() => { }));
            const error = new Error('List failed');
            mockExtensionManager.prototype.loadExtensions = vi
                .fn()
                .mockRejectedValue(error);
            mockGetErrorMessage.mockReturnValue('List failed message');
            await handleList();
            expect(emitConsoleLog).toHaveBeenCalledWith('error', 'List failed message');
            expect(mockProcessExit).toHaveBeenCalledWith(1);
            mockProcessExit.mockRestore();
        });
    });
    describe('listCommand', () => {
        const command = listCommand;
        it('should have correct command and describe', () => {
            expect(command.command).toBe('list');
            expect(command.describe).toBe('Lists installed extensions.');
        });
        it('builder should have output-format option', () => {
            const mockYargs = {
                option: vi.fn().mockReturnThis(),
            };
            command.builder(mockYargs);
            expect(mockYargs.option).toHaveBeenCalledWith('output-format', {
                alias: 'o',
                type: 'string',
                describe: 'The format of the CLI output.',
                choices: ['text', 'json'],
                default: 'text',
            });
        });
        it('handler should call handleList with parsed arguments', async () => {
            mockExtensionManager.prototype.loadExtensions = vi
                .fn()
                .mockResolvedValue([]);
            await command.handler({
                'output-format': 'json',
            });
            expect(mockExtensionManager.prototype.loadExtensions).toHaveBeenCalled();
        });
    });
});
//# sourceMappingURL=list.test.js.map