/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import { renderHook } from '../../test-utils/render.js';
import { describe, it, expect, vi, afterEach, beforeEach } from 'vitest';
import { useHookDisplayState } from './useHookDisplayState.js';
import { coreEvents, CoreEvent, } from '@google/gemini-cli-core';
import { act } from 'react';
describe('useHookDisplayState', () => {
    beforeEach(() => {
        vi.useFakeTimers();
    });
    afterEach(() => {
        vi.restoreAllMocks();
        vi.useRealTimers();
        coreEvents.removeAllListeners(CoreEvent.HookStart);
        coreEvents.removeAllListeners(CoreEvent.HookEnd);
    });
    it('should initialize with empty hooks', () => {
        const { result } = renderHook(() => useHookDisplayState());
        expect(result.current).toEqual([]);
    });
    it('should add a hook when HookStart event is emitted', () => {
        const { result } = renderHook(() => useHookDisplayState());
        const payload = {
            hookName: 'test-hook',
            eventName: 'before-agent',
            hookIndex: 1,
            totalHooks: 1,
        };
        act(() => {
            coreEvents.emitHookStart(payload);
        });
        expect(result.current).toHaveLength(1);
        expect(result.current[0]).toMatchObject({
            name: 'test-hook',
            eventName: 'before-agent',
        });
    });
    it('should remove a hook immediately if duration > 1s', () => {
        const { result } = renderHook(() => useHookDisplayState());
        const startPayload = {
            hookName: 'test-hook',
            eventName: 'before-agent',
        };
        act(() => {
            coreEvents.emitHookStart(startPayload);
        });
        // Advance time by 1.1 seconds
        act(() => {
            vi.advanceTimersByTime(1100);
        });
        const endPayload = {
            hookName: 'test-hook',
            eventName: 'before-agent',
            success: true,
        };
        act(() => {
            coreEvents.emitHookEnd(endPayload);
        });
        expect(result.current).toHaveLength(0);
    });
    it('should delay removal if duration < 1s', () => {
        const { result } = renderHook(() => useHookDisplayState());
        const startPayload = {
            hookName: 'test-hook',
            eventName: 'before-agent',
        };
        act(() => {
            coreEvents.emitHookStart(startPayload);
        });
        // Advance time by only 100ms
        act(() => {
            vi.advanceTimersByTime(100);
        });
        const endPayload = {
            hookName: 'test-hook',
            eventName: 'before-agent',
            success: true,
        };
        act(() => {
            coreEvents.emitHookEnd(endPayload);
        });
        // Should still be present
        expect(result.current).toHaveLength(1);
        // Advance remaining time (900ms needed, let's go 950ms)
        act(() => {
            vi.advanceTimersByTime(950);
        });
        expect(result.current).toHaveLength(0);
    });
    it('should handle multiple hooks correctly', () => {
        const { result } = renderHook(() => useHookDisplayState());
        act(() => {
            coreEvents.emitHookStart({ hookName: 'h1', eventName: 'e1' });
        });
        act(() => {
            vi.advanceTimersByTime(500);
        });
        act(() => {
            coreEvents.emitHookStart({ hookName: 'h2', eventName: 'e1' });
        });
        expect(result.current).toHaveLength(2);
        // End h1 (total time 500ms -> needs 500ms delay)
        act(() => {
            coreEvents.emitHookEnd({
                hookName: 'h1',
                eventName: 'e1',
                success: true,
            });
        });
        // h1 still there
        expect(result.current).toHaveLength(2);
        // Advance 600ms. h1 should disappear. h2 has been running for 600ms.
        act(() => {
            vi.advanceTimersByTime(600);
        });
        expect(result.current).toHaveLength(1);
        expect(result.current[0].name).toBe('h2');
        // End h2 (total time 600ms -> needs 400ms delay)
        act(() => {
            coreEvents.emitHookEnd({
                hookName: 'h2',
                eventName: 'e1',
                success: true,
            });
        });
        expect(result.current).toHaveLength(1);
        act(() => {
            vi.advanceTimersByTime(500);
        });
        expect(result.current).toHaveLength(0);
    });
    it('should handle interleaved hooks with same name and event', () => {
        const { result } = renderHook(() => useHookDisplayState());
        const hook = { hookName: 'same-hook', eventName: 'same-event' };
        // Start Hook 1 at t=0
        act(() => {
            coreEvents.emitHookStart(hook);
        });
        // Advance to t=500
        act(() => {
            vi.advanceTimersByTime(500);
        });
        // Start Hook 2 at t=500
        act(() => {
            coreEvents.emitHookStart(hook);
        });
        expect(result.current).toHaveLength(2);
        expect(result.current[0].name).toBe('same-hook');
        expect(result.current[1].name).toBe('same-hook');
        // End Hook 1 at t=600 (Duration 600ms -> delay 400ms)
        act(() => {
            vi.advanceTimersByTime(100);
            coreEvents.emitHookEnd({ ...hook, success: true });
        });
        // Both still visible (Hook 1 pending removal in 400ms)
        expect(result.current).toHaveLength(2);
        // Advance 400ms (t=1000). Hook 1 should be removed.
        act(() => {
            vi.advanceTimersByTime(400);
        });
        expect(result.current).toHaveLength(1);
        // End Hook 2 at t=1100 (Duration: 1100 - 500 = 600ms -> delay 400ms)
        act(() => {
            vi.advanceTimersByTime(100);
            coreEvents.emitHookEnd({ ...hook, success: true });
        });
        // Hook 2 still visible (pending removal in 400ms)
        expect(result.current).toHaveLength(1);
        // Advance 400ms (t=1500). Hook 2 should be removed.
        act(() => {
            vi.advanceTimersByTime(400);
        });
        expect(result.current).toHaveLength(0);
    });
});
//# sourceMappingURL=useHookDisplayState.test.js.map