/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { renderHook } from '../../test-utils/render.js';
import { act } from 'react';
import { useSessionBrowser, convertSessionToHistoryFormats, } from './useSessionBrowser.js';
import * as fs from 'node:fs/promises';
import path from 'node:path';
import { getSessionFiles } from '../../utils/sessionUtils.js';
import { CoreToolCallStatus, } from '@google/gemini-cli-core';
import { coreEvents, convertSessionToClientHistory, } from '@google/gemini-cli-core';
// Mock modules
vi.mock('fs/promises');
vi.mock('path');
vi.mock('../../utils/sessionUtils.js', async (importOriginal) => {
    const actual = await importOriginal();
    return {
        ...actual,
        getSessionFiles: vi.fn(),
    };
});
const MOCKED_PROJECT_TEMP_DIR = '/test/project/temp';
const MOCKED_CHATS_DIR = '/test/project/temp/chats';
const MOCKED_SESSION_ID = 'test-session-123';
const MOCKED_CURRENT_SESSION_ID = 'current-session-id';
describe('useSessionBrowser', () => {
    const mockedFs = vi.mocked(fs);
    const mockedPath = vi.mocked(path);
    const mockedGetSessionFiles = vi.mocked(getSessionFiles);
    const mockConfig = {
        storage: {
            getProjectTempDir: vi.fn(),
        },
        setSessionId: vi.fn(),
        getSessionId: vi.fn(),
        getGeminiClient: vi.fn().mockReturnValue({
            getChatRecordingService: vi.fn().mockReturnValue({
                deleteSession: vi.fn(),
            }),
        }),
    };
    const mockOnLoadHistory = vi.fn();
    beforeEach(() => {
        vi.resetAllMocks();
        vi.spyOn(coreEvents, 'emitFeedback').mockImplementation(() => { });
        mockedPath.join.mockImplementation((...args) => args.join('/'));
        vi.mocked(mockConfig.storage.getProjectTempDir).mockReturnValue(MOCKED_PROJECT_TEMP_DIR);
        vi.mocked(mockConfig.getSessionId).mockReturnValue(MOCKED_CURRENT_SESSION_ID);
    });
    it('should successfully resume a session', async () => {
        const MOCKED_FILENAME = 'session-2025-01-01-test-session-123.json';
        const mockConversation = {
            sessionId: 'existing-session-456',
            messages: [{ type: 'user', content: 'Hello' }],
        };
        const mockSession = {
            id: MOCKED_SESSION_ID,
            fileName: MOCKED_FILENAME,
        };
        mockedGetSessionFiles.mockResolvedValue([mockSession]);
        mockedFs.readFile.mockResolvedValue(JSON.stringify(mockConversation));
        const { result } = renderHook(() => useSessionBrowser(mockConfig, mockOnLoadHistory));
        await act(async () => {
            await result.current.handleResumeSession(mockSession);
        });
        expect(mockedFs.readFile).toHaveBeenCalledWith(`${MOCKED_CHATS_DIR}/${MOCKED_FILENAME}`, 'utf8');
        expect(mockConfig.setSessionId).toHaveBeenCalledWith('existing-session-456');
        expect(result.current.isSessionBrowserOpen).toBe(false);
        expect(mockOnLoadHistory).toHaveBeenCalled();
    });
    it('should handle file read error', async () => {
        const MOCKED_FILENAME = 'session-2025-01-01-test-session-123.json';
        const mockSession = {
            id: MOCKED_SESSION_ID,
            fileName: MOCKED_FILENAME,
        };
        mockedFs.readFile.mockRejectedValue(new Error('File not found'));
        const { result } = renderHook(() => useSessionBrowser(mockConfig, mockOnLoadHistory));
        await act(async () => {
            await result.current.handleResumeSession(mockSession);
        });
        expect(coreEvents.emitFeedback).toHaveBeenCalledWith('error', 'Error resuming session:', expect.any(Error));
        expect(result.current.isSessionBrowserOpen).toBe(false);
    });
    it('should handle JSON parse error', async () => {
        const MOCKED_FILENAME = 'invalid.json';
        const mockSession = {
            id: MOCKED_SESSION_ID,
            fileName: MOCKED_FILENAME,
        };
        mockedFs.readFile.mockResolvedValue('invalid json');
        const { result } = renderHook(() => useSessionBrowser(mockConfig, mockOnLoadHistory));
        await act(async () => {
            await result.current.handleResumeSession(mockSession);
        });
        expect(coreEvents.emitFeedback).toHaveBeenCalledWith('error', 'Error resuming session:', expect.any(Error));
        expect(result.current.isSessionBrowserOpen).toBe(false);
    });
});
// The convertSessionToHistoryFormats tests are self-contained and do not need changes.
describe('convertSessionToHistoryFormats', () => {
    it('should convert empty messages array', () => {
        const result = convertSessionToHistoryFormats([]);
        expect(result.uiHistory).toEqual([]);
        expect(convertSessionToClientHistory([])).toEqual([]);
    });
    it('should convert basic user and model messages', () => {
        const messages = [
            { type: 'user', content: 'Hello' },
            { type: 'gemini', content: 'Hi there' },
        ];
        const result = convertSessionToHistoryFormats(messages);
        expect(result.uiHistory).toHaveLength(2);
        expect(result.uiHistory[0]).toMatchObject({ type: 'user', text: 'Hello' });
        expect(result.uiHistory[1]).toMatchObject({
            type: 'gemini',
            text: 'Hi there',
        });
        const clientHistory = convertSessionToClientHistory(messages);
        expect(clientHistory).toHaveLength(2);
        expect(clientHistory[0]).toEqual({
            role: 'user',
            parts: [{ text: 'Hello' }],
        });
        expect(clientHistory[1]).toEqual({
            role: 'model',
            parts: [{ text: 'Hi there' }],
        });
    });
    it('should prioritize displayContent for UI history but use content for client history', () => {
        const messages = [
            {
                type: 'user',
                content: [{ text: 'Expanded content' }],
                displayContent: [{ text: 'User input' }],
            },
        ];
        const result = convertSessionToHistoryFormats(messages);
        expect(result.uiHistory).toHaveLength(1);
        expect(result.uiHistory[0]).toMatchObject({
            type: 'user',
            text: 'User input',
        });
        const clientHistory = convertSessionToClientHistory(messages);
        expect(clientHistory).toHaveLength(1);
        expect(clientHistory[0]).toEqual({
            role: 'user',
            parts: [{ text: 'Expanded content' }],
        });
    });
    it('should filter out slash commands from client history but keep in UI', () => {
        const messages = [
            { type: 'user', content: '/help' },
            { type: 'info', content: 'Help text' },
        ];
        const result = convertSessionToHistoryFormats(messages);
        expect(result.uiHistory).toHaveLength(2);
        expect(result.uiHistory[0]).toMatchObject({ type: 'user', text: '/help' });
        expect(result.uiHistory[1]).toMatchObject({
            type: 'info',
            text: 'Help text',
        });
        expect(convertSessionToClientHistory(messages)).toHaveLength(0);
    });
    it('should handle tool calls and responses', () => {
        const messages = [
            { type: 'user', content: 'What time is it?' },
            {
                type: 'gemini',
                content: '',
                toolCalls: [
                    {
                        id: 'call_1',
                        name: 'get_time',
                        args: {},
                        status: CoreToolCallStatus.Success,
                        result: '12:00',
                    },
                ],
            },
        ];
        const result = convertSessionToHistoryFormats(messages);
        expect(result.uiHistory).toHaveLength(2);
        expect(result.uiHistory[0]).toMatchObject({
            type: 'user',
            text: 'What time is it?',
        });
        expect(result.uiHistory[1]).toMatchObject({
            type: 'tool_group',
            tools: [
                expect.objectContaining({
                    callId: 'call_1',
                    name: 'get_time',
                    status: CoreToolCallStatus.Success,
                }),
            ],
        });
        const clientHistory = convertSessionToClientHistory(messages);
        expect(clientHistory).toHaveLength(3); // User, Model (call), User (response)
        expect(clientHistory[0]).toEqual({
            role: 'user',
            parts: [{ text: 'What time is it?' }],
        });
        expect(clientHistory[1]).toEqual({
            role: 'model',
            parts: [
                {
                    functionCall: {
                        name: 'get_time',
                        args: {},
                        id: 'call_1',
                    },
                },
            ],
        });
        expect(clientHistory[2]).toEqual({
            role: 'user',
            parts: [
                {
                    functionResponse: {
                        id: 'call_1',
                        name: 'get_time',
                        response: { output: '12:00' },
                    },
                },
            ],
        });
    });
});
//# sourceMappingURL=useSessionBrowser.test.js.map