/**
 * @license
 * Copyright 2026 HopCode Team
 * SPDX-License-Identifier: Apache-2.0
 */
import { renderHook } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { StreamingState } from '../types.js';
import { LONG_TASK_NOTIFICATION_THRESHOLD_SECONDS, useAttentionNotifications, } from './useAttentionNotifications.js';
vi.mock('../../services/notificationService.js', () => ({
    sendNotification: vi.fn(),
}));
const { sendNotification: mockedSendNotification } = await import('../../services/notificationService.js');
const mockTerminal = {
    notifyITerm2: vi.fn(),
    notifyKitty: vi.fn(),
    notifyGhostty: vi.fn(),
    notifyBell: vi.fn(),
};
const mockSettings = {
    merged: {
        general: {
            terminalBell: true,
        },
    },
};
const mockSettingsDisabled = {
    merged: {
        general: {
            terminalBell: false,
        },
    },
};
describe('useAttentionNotifications', () => {
    beforeEach(() => {
        vi.mocked(mockedSendNotification).mockReset();
    });
    const render = (props) => renderHook(({ hookProps }) => useAttentionNotifications(hookProps), {
        initialProps: {
            hookProps: {
                isFocused: true,
                streamingState: StreamingState.Idle,
                elapsedTime: 0,
                settings: mockSettings,
                terminal: mockTerminal,
                ...props,
            },
        },
    });
    it('notifies when tool approval is required while unfocused', () => {
        const { rerender } = render();
        rerender({
            hookProps: {
                isFocused: false,
                streamingState: StreamingState.WaitingForConfirmation,
                elapsedTime: 0,
                settings: mockSettings,
                terminal: mockTerminal,
            },
        });
        expect(mockedSendNotification).toHaveBeenCalledTimes(1);
        expect(mockedSendNotification).toHaveBeenCalledWith(expect.objectContaining({ title: 'HopCode' }), mockTerminal, true);
    });
    it('notifies when focus is lost after entering approval wait state', () => {
        const { rerender } = render({
            isFocused: true,
            streamingState: StreamingState.WaitingForConfirmation,
        });
        rerender({
            hookProps: {
                isFocused: false,
                streamingState: StreamingState.WaitingForConfirmation,
                elapsedTime: 0,
                settings: mockSettings,
                terminal: mockTerminal,
            },
        });
        expect(mockedSendNotification).toHaveBeenCalledTimes(1);
    });
    it('sends a notification when a long task finishes while unfocused', () => {
        const { rerender } = render();
        rerender({
            hookProps: {
                isFocused: false,
                streamingState: StreamingState.Responding,
                elapsedTime: LONG_TASK_NOTIFICATION_THRESHOLD_SECONDS + 5,
                settings: mockSettings,
                terminal: mockTerminal,
            },
        });
        rerender({
            hookProps: {
                isFocused: false,
                streamingState: StreamingState.Idle,
                elapsedTime: 0,
                settings: mockSettings,
                terminal: mockTerminal,
            },
        });
        expect(mockedSendNotification).toHaveBeenCalledTimes(1);
    });
    it('does not notify about long tasks when the CLI is focused', () => {
        const { rerender } = render();
        rerender({
            hookProps: {
                isFocused: true,
                streamingState: StreamingState.Responding,
                elapsedTime: LONG_TASK_NOTIFICATION_THRESHOLD_SECONDS + 2,
                settings: mockSettings,
                terminal: mockTerminal,
            },
        });
        rerender({
            hookProps: {
                isFocused: true,
                streamingState: StreamingState.Idle,
                elapsedTime: 0,
                settings: mockSettings,
                terminal: mockTerminal,
            },
        });
        expect(mockedSendNotification).not.toHaveBeenCalled();
    });
    it('does not treat short responses as long tasks', () => {
        const { rerender } = render();
        rerender({
            hookProps: {
                isFocused: false,
                streamingState: StreamingState.Responding,
                elapsedTime: 5,
                settings: mockSettings,
                terminal: mockTerminal,
            },
        });
        rerender({
            hookProps: {
                isFocused: false,
                streamingState: StreamingState.Idle,
                elapsedTime: 0,
                settings: mockSettings,
                terminal: mockTerminal,
            },
        });
        expect(mockedSendNotification).not.toHaveBeenCalled();
    });
    it('includes tool name in approval notification message', () => {
        const { rerender } = render();
        rerender({
            hookProps: {
                isFocused: false,
                streamingState: StreamingState.WaitingForConfirmation,
                elapsedTime: 0,
                settings: mockSettings,
                terminal: mockTerminal,
                pendingToolCalls: [
                    { status: 'awaiting_approval', request: { name: 'Bash' } },
                ],
            },
        });
        expect(mockedSendNotification).toHaveBeenCalledTimes(1);
        expect(mockedSendNotification).toHaveBeenCalledWith(expect.objectContaining({
            message: 'HopCode needs your permission to use Bash',
        }), mockTerminal, true);
    });
    it('uses fallback message when no pending tool call is found', () => {
        const { rerender } = render();
        rerender({
            hookProps: {
                isFocused: false,
                streamingState: StreamingState.WaitingForConfirmation,
                elapsedTime: 0,
                settings: mockSettings,
                terminal: mockTerminal,
                pendingToolCalls: [],
            },
        });
        expect(mockedSendNotification).toHaveBeenCalledWith(expect.objectContaining({
            message: 'HopCode is waiting for your input',
        }), mockTerminal, true);
    });
    it('sends "waiting for input" message for long task completion', () => {
        const { rerender } = render();
        rerender({
            hookProps: {
                isFocused: false,
                streamingState: StreamingState.Responding,
                elapsedTime: LONG_TASK_NOTIFICATION_THRESHOLD_SECONDS + 5,
                settings: mockSettings,
                terminal: mockTerminal,
            },
        });
        rerender({
            hookProps: {
                isFocused: false,
                streamingState: StreamingState.Idle,
                elapsedTime: 0,
                settings: mockSettings,
                terminal: mockTerminal,
            },
        });
        expect(mockedSendNotification).toHaveBeenCalledWith(expect.objectContaining({
            message: 'HopCode is waiting for your input',
        }), mockTerminal, true);
    });
    it('does not notify when terminalBell is disabled', () => {
        const { rerender } = render({
            settings: mockSettingsDisabled,
        });
        rerender({
            hookProps: {
                isFocused: false,
                streamingState: StreamingState.WaitingForConfirmation,
                elapsedTime: 0,
                settings: mockSettingsDisabled,
                terminal: mockTerminal,
            },
        });
        expect(mockedSendNotification).not.toHaveBeenCalled();
    });
});
//# sourceMappingURL=useAttentionNotifications.test.js.map