/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import { act } from 'react';
import { renderHook } from '../../test-utils/render.js';
import { waitFor } from '../../test-utils/async.js';
import { useSessionResume } from './useSessionResume.js';
describe('useSessionResume', () => {
    // Mock dependencies
    const mockGeminiClient = {
        resumeChat: vi.fn(),
    };
    const mockConfig = {
        getGeminiClient: vi.fn().mockReturnValue(mockGeminiClient),
    };
    const createMockHistoryManager = () => ({
        history: [],
        addItem: vi.fn(),
        updateItem: vi.fn(),
        clearItems: vi.fn(),
        loadHistory: vi.fn(),
    });
    let mockHistoryManager;
    const mockRefreshStatic = vi.fn();
    const mockSetQuittingMessages = vi.fn();
    const getDefaultProps = () => ({
        config: mockConfig,
        historyManager: mockHistoryManager,
        refreshStatic: mockRefreshStatic,
        isGeminiClientInitialized: true,
        setQuittingMessages: mockSetQuittingMessages,
        resumedSessionData: undefined,
        isAuthenticating: false,
    });
    beforeEach(() => {
        vi.clearAllMocks();
        mockHistoryManager = createMockHistoryManager();
    });
    describe('loadHistoryForResume', () => {
        it('should return a loadHistoryForResume callback', () => {
            const { result } = renderHook(() => useSessionResume(getDefaultProps()));
            expect(result.current.loadHistoryForResume).toBeInstanceOf(Function);
        });
        it('should clear history and add items when loading history', async () => {
            const { result } = renderHook(() => useSessionResume(getDefaultProps()));
            const uiHistory = [
                { type: 'user', text: 'Hello' },
                { type: 'gemini', text: 'Hi there!' },
            ];
            const clientHistory = [
                { role: 'user', parts: [{ text: 'Hello' }] },
                { role: 'model', parts: [{ text: 'Hi there!' }] },
            ];
            const resumedData = {
                conversation: {
                    sessionId: 'test-123',
                    projectHash: 'project-123',
                    startTime: '2025-01-01T00:00:00Z',
                    lastUpdated: '2025-01-01T01:00:00Z',
                    messages: [],
                },
                filePath: '/path/to/session.json',
            };
            await act(async () => {
                await result.current.loadHistoryForResume(uiHistory, clientHistory, resumedData);
            });
            expect(mockSetQuittingMessages).toHaveBeenCalledWith(null);
            expect(mockHistoryManager.clearItems).toHaveBeenCalled();
            expect(mockHistoryManager.addItem).toHaveBeenCalledTimes(2);
            expect(mockHistoryManager.addItem).toHaveBeenNthCalledWith(1, { type: 'user', text: 'Hello' }, 0, true);
            expect(mockHistoryManager.addItem).toHaveBeenNthCalledWith(2, { type: 'gemini', text: 'Hi there!' }, 1, true);
            expect(mockRefreshStatic).toHaveBeenCalledTimes(1);
            expect(mockGeminiClient.resumeChat).toHaveBeenCalledWith(clientHistory, resumedData);
        });
        it('should not load history if Gemini client is not initialized', async () => {
            const { result } = renderHook(() => useSessionResume({
                ...getDefaultProps(),
                isGeminiClientInitialized: false,
            }));
            const uiHistory = [
                { type: 'user', text: 'Hello' },
            ];
            const clientHistory = [
                { role: 'user', parts: [{ text: 'Hello' }] },
            ];
            const resumedData = {
                conversation: {
                    sessionId: 'test-123',
                    projectHash: 'project-123',
                    startTime: '2025-01-01T00:00:00Z',
                    lastUpdated: '2025-01-01T01:00:00Z',
                    messages: [],
                },
                filePath: '/path/to/session.json',
            };
            await act(async () => {
                await result.current.loadHistoryForResume(uiHistory, clientHistory, resumedData);
            });
            expect(mockHistoryManager.clearItems).not.toHaveBeenCalled();
            expect(mockHistoryManager.addItem).not.toHaveBeenCalled();
            expect(mockGeminiClient.resumeChat).not.toHaveBeenCalled();
        });
        it('should handle empty history arrays', async () => {
            const { result } = renderHook(() => useSessionResume(getDefaultProps()));
            const resumedData = {
                conversation: {
                    sessionId: 'test-123',
                    projectHash: 'project-123',
                    startTime: '2025-01-01T00:00:00Z',
                    lastUpdated: '2025-01-01T01:00:00Z',
                    messages: [],
                },
                filePath: '/path/to/session.json',
            };
            await act(async () => {
                await result.current.loadHistoryForResume([], [], resumedData);
            });
            expect(mockHistoryManager.clearItems).toHaveBeenCalled();
            expect(mockHistoryManager.addItem).not.toHaveBeenCalled();
            expect(mockRefreshStatic).toHaveBeenCalledTimes(1);
            expect(mockGeminiClient.resumeChat).toHaveBeenCalledWith([], resumedData);
        });
        it('should restore directories from resumed session data', async () => {
            const mockAddDirectories = vi
                .fn()
                .mockReturnValue({ added: [], failed: [] });
            const mockWorkspaceContext = {
                addDirectories: mockAddDirectories,
            };
            const configWithWorkspace = {
                ...mockConfig,
                getWorkspaceContext: vi.fn().mockReturnValue(mockWorkspaceContext),
            };
            const { result } = renderHook(() => useSessionResume({
                ...getDefaultProps(),
                config: configWithWorkspace,
            }));
            const resumedData = {
                conversation: {
                    sessionId: 'test-123',
                    projectHash: 'project-123',
                    startTime: '2025-01-01T00:00:00Z',
                    lastUpdated: '2025-01-01T01:00:00Z',
                    messages: [],
                    directories: ['/restored/dir1', '/restored/dir2'],
                },
                filePath: '/path/to/session.json',
            };
            await act(async () => {
                await result.current.loadHistoryForResume([], [], resumedData);
            });
            expect(configWithWorkspace.getWorkspaceContext).toHaveBeenCalled();
            expect(mockAddDirectories).toHaveBeenCalledWith([
                '/restored/dir1',
                '/restored/dir2',
            ]);
        });
        it('should not call addDirectories when no directories in resumed session', async () => {
            const mockAddDirectories = vi.fn();
            const mockWorkspaceContext = {
                addDirectories: mockAddDirectories,
            };
            const configWithWorkspace = {
                ...mockConfig,
                getWorkspaceContext: vi.fn().mockReturnValue(mockWorkspaceContext),
            };
            const { result } = renderHook(() => useSessionResume({
                ...getDefaultProps(),
                config: configWithWorkspace,
            }));
            const resumedData = {
                conversation: {
                    sessionId: 'test-123',
                    projectHash: 'project-123',
                    startTime: '2025-01-01T00:00:00Z',
                    lastUpdated: '2025-01-01T01:00:00Z',
                    messages: [],
                    // No directories field
                },
                filePath: '/path/to/session.json',
            };
            await act(async () => {
                await result.current.loadHistoryForResume([], [], resumedData);
            });
            expect(mockAddDirectories).not.toHaveBeenCalled();
        });
    });
    describe('callback stability', () => {
        it('should maintain stable loadHistoryForResume reference across renders', () => {
            const { result, rerender } = renderHook(() => useSessionResume(getDefaultProps()));
            const initialCallback = result.current.loadHistoryForResume;
            rerender();
            expect(result.current.loadHistoryForResume).toBe(initialCallback);
        });
        it('should update callback when config changes', () => {
            const { result, rerender } = renderHook(({ config }) => useSessionResume({
                ...getDefaultProps(),
                config,
            }), {
                initialProps: { config: mockConfig },
            });
            const initialCallback = result.current.loadHistoryForResume;
            const newMockConfig = {
                getGeminiClient: vi.fn().mockReturnValue(mockGeminiClient),
            };
            rerender({ config: newMockConfig });
            expect(result.current.loadHistoryForResume).not.toBe(initialCallback);
        });
    });
    describe('automatic resume on mount', () => {
        it('should not resume when resumedSessionData is not provided', () => {
            renderHook(() => useSessionResume(getDefaultProps()));
            expect(mockHistoryManager.clearItems).not.toHaveBeenCalled();
            expect(mockHistoryManager.addItem).not.toHaveBeenCalled();
            expect(mockGeminiClient.resumeChat).not.toHaveBeenCalled();
        });
        it('should not resume when user is authenticating', () => {
            const conversation = {
                sessionId: 'auto-resume-123',
                projectHash: 'project-123',
                startTime: '2025-01-01T00:00:00Z',
                lastUpdated: '2025-01-01T01:00:00Z',
                messages: [
                    {
                        id: 'msg-1',
                        timestamp: '2025-01-01T00:01:00Z',
                        content: 'Test message',
                        type: 'user',
                    },
                ],
            };
            renderHook(() => useSessionResume({
                ...getDefaultProps(),
                resumedSessionData: {
                    conversation,
                    filePath: '/path/to/session.json',
                },
                isAuthenticating: true,
            }));
            expect(mockHistoryManager.clearItems).not.toHaveBeenCalled();
            expect(mockHistoryManager.addItem).not.toHaveBeenCalled();
            expect(mockGeminiClient.resumeChat).not.toHaveBeenCalled();
        });
        it('should not resume when Gemini client is not initialized', () => {
            const conversation = {
                sessionId: 'auto-resume-123',
                projectHash: 'project-123',
                startTime: '2025-01-01T00:00:00Z',
                lastUpdated: '2025-01-01T01:00:00Z',
                messages: [
                    {
                        id: 'msg-1',
                        timestamp: '2025-01-01T00:01:00Z',
                        content: 'Test message',
                        type: 'user',
                    },
                ],
            };
            renderHook(() => useSessionResume({
                ...getDefaultProps(),
                resumedSessionData: {
                    conversation,
                    filePath: '/path/to/session.json',
                },
                isGeminiClientInitialized: false,
            }));
            expect(mockHistoryManager.clearItems).not.toHaveBeenCalled();
            expect(mockHistoryManager.addItem).not.toHaveBeenCalled();
            expect(mockGeminiClient.resumeChat).not.toHaveBeenCalled();
        });
        it('should automatically resume session when resumedSessionData is provided', async () => {
            const conversation = {
                sessionId: 'auto-resume-123',
                projectHash: 'project-123',
                startTime: '2025-01-01T00:00:00Z',
                lastUpdated: '2025-01-01T01:00:00Z',
                messages: [
                    {
                        id: 'msg-1',
                        timestamp: '2025-01-01T00:01:00Z',
                        content: 'Hello from resumed session',
                        type: 'user',
                    },
                    {
                        id: 'msg-2',
                        timestamp: '2025-01-01T00:02:00Z',
                        content: 'Welcome back!',
                        type: 'gemini',
                    },
                ],
            };
            await act(async () => {
                renderHook(() => useSessionResume({
                    ...getDefaultProps(),
                    resumedSessionData: {
                        conversation,
                        filePath: '/path/to/session.json',
                    },
                }));
            });
            await waitFor(() => {
                expect(mockHistoryManager.clearItems).toHaveBeenCalled();
            });
            expect(mockHistoryManager.addItem).toHaveBeenCalledTimes(2);
            expect(mockHistoryManager.addItem).toHaveBeenNthCalledWith(1, { type: 'user', text: 'Hello from resumed session' }, 0, true);
            expect(mockHistoryManager.addItem).toHaveBeenNthCalledWith(2, { type: 'gemini', text: 'Welcome back!' }, 1, true);
            expect(mockRefreshStatic).toHaveBeenCalledTimes(1);
            expect(mockGeminiClient.resumeChat).toHaveBeenCalled();
        });
        it('should only resume once even if props change', async () => {
            const conversation = {
                sessionId: 'auto-resume-123',
                projectHash: 'project-123',
                startTime: '2025-01-01T00:00:00Z',
                lastUpdated: '2025-01-01T01:00:00Z',
                messages: [
                    {
                        id: 'msg-1',
                        timestamp: '2025-01-01T00:01:00Z',
                        content: 'Test message',
                        type: 'user',
                    },
                ],
            };
            let rerenderFunc;
            await act(async () => {
                const { rerender } = renderHook(({ refreshStatic }) => useSessionResume({
                    ...getDefaultProps(),
                    refreshStatic,
                    resumedSessionData: {
                        conversation,
                        filePath: '/path/to/session.json',
                    },
                }), {
                    initialProps: { refreshStatic: mockRefreshStatic },
                });
                rerenderFunc = rerender;
            });
            await waitFor(() => {
                expect(mockHistoryManager.clearItems).toHaveBeenCalled();
            });
            const clearItemsCallCount = mockHistoryManager.clearItems.mock.calls.length;
            // Rerender with different refreshStatic
            const newRefreshStatic = vi.fn();
            await act(async () => {
                rerenderFunc({ refreshStatic: newRefreshStatic });
            });
            // Should not resume again
            expect(mockHistoryManager.clearItems).toHaveBeenCalledTimes(clearItemsCallCount);
        });
        it('should convert session messages correctly during auto-resume', async () => {
            const conversation = {
                sessionId: 'auto-resume-with-tools',
                projectHash: 'project-123',
                startTime: '2025-01-01T00:00:00Z',
                lastUpdated: '2025-01-01T01:00:00Z',
                messages: [
                    {
                        id: 'msg-1',
                        timestamp: '2025-01-01T00:01:00Z',
                        content: '/help',
                        type: 'user',
                    },
                    {
                        id: 'msg-2',
                        timestamp: '2025-01-01T00:02:00Z',
                        content: 'Regular message',
                        type: 'user',
                    },
                ],
            };
            await act(async () => {
                renderHook(() => useSessionResume({
                    ...getDefaultProps(),
                    resumedSessionData: {
                        conversation,
                        filePath: '/path/to/session.json',
                    },
                }));
            });
            await waitFor(() => {
                expect(mockGeminiClient.resumeChat).toHaveBeenCalled();
            });
            // Check that the client history was called with filtered messages
            // (slash commands should be filtered out)
            const clientHistory = mockGeminiClient.resumeChat.mock.calls[0][0];
            // Should only have the non-slash-command message
            expect(clientHistory).toHaveLength(1);
            expect(clientHistory[0]).toEqual({
                role: 'user',
                parts: [{ text: 'Regular message' }],
            });
            // But UI history should have both
            expect(mockHistoryManager.addItem).toHaveBeenCalledTimes(2);
        });
    });
});
//# sourceMappingURL=useSessionResume.test.js.map