/**
 * @license
 * Copyright 2025 Vybestack LLC
 * SPDX-License-Identifier: Apache-2.0
 */
/* eslint-disable @typescript-eslint/no-explicit-any */
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { renderHook, act, waitFor } from '@testing-library/react';
import React from 'react';
import * as ReactDOM from 'react-dom';
import { useGeminiStream } from './useGeminiStream.js';
import { useReactToolScheduler, } from './useReactToolScheduler.js';
import { AuthType, } from '@vybestack/llxprt-code-core';
const inkMock = vi.hoisted(() => {
    const noop = vi.fn(() => null);
    const write = vi.fn();
    const exit = vi.fn();
    const setRawMode = vi.fn();
    const module = {
        Box: noop,
        Text: noop,
        Newline: noop,
        useStdout: vi.fn(() => ({
            stdout: { write, columns: 80, rows: 24 },
            write,
        })),
        useApp: vi.fn(() => ({ exit })),
        useInput: vi.fn(),
        useStdin: vi.fn(() => ({
            stdin: {
                setRawMode,
                resume: vi.fn(),
                pause: vi.fn(),
                removeListener: vi.fn(),
                off: vi.fn(),
            },
            setRawMode,
            isRawModeSupported: true,
        })),
        useIsScreenReaderEnabled: vi.fn(() => false),
        measureElement: vi.fn(() => ({ width: 0, height: 0 })),
        DOMElement: class {
        },
    };
    module.default = module;
    return module;
});
vi.mock('ink', () => inkMock);
const mockStartNewPrompt = vi.fn();
const mockAddUsage = vi.fn();
vi.mock('../contexts/SessionContext.js', () => ({
    useSessionStats: vi.fn(() => ({
        startNewPrompt: mockStartNewPrompt,
        addUsage: mockAddUsage,
        getPromptCount: vi.fn(() => 5),
    })),
}));
vi.mock('./slashCommandProcessor.js', () => ({
    handleSlashCommand: vi.fn().mockReturnValue(false),
}));
vi.mock('./useKeypress.js', () => ({
    useKeypress: vi.fn(),
}));
const ensureReactSharedInternals = () => {
    const reactInternals = React
        .__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
    const domInternals = ReactDOM
        .__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
    const shared = reactInternals ??
        domInternals ?? {
        S: null,
        T: null,
        H: null,
    };
    if (shared.S === undefined)
        shared.S = null;
    if (shared.T === undefined)
        shared.T = null;
    if (shared.H === undefined)
        shared.H = null;
    if (typeof globalThis !== 'undefined') {
        globalThis.ReactSharedInternals = shared;
    }
};
ensureReactSharedInternals();
const mockSendMessageStream = vi
    .fn()
    .mockReturnValue((async function* () { })());
const mockStartChat = vi.fn();
const MockedGeminiClientClass = vi.hoisted(() => vi.fn().mockImplementation(function (_config) {
    this.startChat = mockStartChat;
    this.sendMessageStream = mockSendMessageStream;
    this.addHistory = vi.fn();
}));
vi.mock('./useReactToolScheduler.js', async (importOriginal) => {
    const original = await importOriginal();
    return {
        ...original,
        useReactToolScheduler: vi.fn(),
    };
});
const mockUseReactToolScheduler = useReactToolScheduler;
describe('useGeminiStream subagent isolation', () => {
    let mockConfig;
    let mockSettings;
    let mockAddItem;
    let mockOnDebugMessage;
    let mockHandleSlashCommand;
    let mockScheduleToolCalls;
    let mockMarkToolsAsSubmitted;
    beforeEach(() => {
        vi.clearAllMocks();
        mockAddItem = vi.fn();
        mockOnDebugMessage = vi.fn();
        mockHandleSlashCommand = vi.fn().mockResolvedValue(false);
        const contentGeneratorConfig = {
            model: 'test-model',
            apiKey: 'test-key',
            vertexai: false,
            authType: AuthType.USE_GEMINI,
        };
        const mockGetGeminiClient = vi.fn().mockImplementation(() => {
            const clientInstance = new MockedGeminiClientClass(mockConfig);
            return clientInstance;
        });
        mockConfig = {
            apiKey: 'test-api-key',
            model: 'gemini-pro',
            sandbox: false,
            targetDir: '/tmp/project',
            debugMode: false,
            question: undefined,
            fullContext: false,
            coreTools: [],
            toolDiscoveryCommand: undefined,
            toolCallCommand: undefined,
            mcpServerCommand: undefined,
            mcpServers: undefined,
            userAgent: 'test-agent',
            userMemory: '',
            geminiMdFileCount: 0,
            alwaysSkipModificationConfirmation: false,
            vertexai: false,
            showMemoryUsage: false,
            contextFileName: undefined,
            getToolRegistry: vi.fn(() => ({ getToolSchemaList: vi.fn(() => []) })),
            getProjectRoot: vi.fn(() => '/tmp/project'),
            getCheckpointingEnabled: vi.fn(() => false),
            getGeminiClient: mockGetGeminiClient,
            getUsageStatisticsEnabled: () => true,
            getDebugMode: () => false,
            addHistory: vi.fn(),
            getSessionId() {
                return 'session-123';
            },
            getModel: vi.fn(() => 'gemini-2.5-pro'),
            getContentGeneratorConfig: vi
                .fn()
                .mockReturnValue(contentGeneratorConfig),
        };
        mockSettings = {
            merged: {
                ui: {
                    showCitations: false,
                },
            },
        };
        mockScheduleToolCalls = vi.fn();
        mockMarkToolsAsSubmitted = vi.fn();
        const mockCancelAllToolCalls = vi.fn();
        mockUseReactToolScheduler.mockReturnValue([
            [],
            mockScheduleToolCalls,
            mockMarkToolsAsSubmitted,
            mockCancelAllToolCalls,
        ]);
        mockStartChat.mockClear().mockResolvedValue({
            sendMessageStream: mockSendMessageStream,
        });
        mockSendMessageStream
            .mockClear()
            .mockReturnValue((async function* () { })());
    });
    it('subagent completions should not reach Gemini submission pipeline', async () => {
        const client = new MockedGeminiClientClass(mockConfig);
        let capturedOnComplete = null;
        mockUseReactToolScheduler.mockImplementation((onComplete) => {
            capturedOnComplete = onComplete;
            return [[], mockScheduleToolCalls, mockMarkToolsAsSubmitted, vi.fn()];
        });
        renderHook(() => useGeminiStream(client, [], mockAddItem, mockConfig, mockSettings, mockOnDebugMessage, mockHandleSlashCommand, false, () => 'vscode', () => { }, () => Promise.resolve(), () => { }, () => { }, () => { }));
        const subagentToolCall = {
            request: {
                callId: 'subagent-call',
                name: 'task',
                args: {},
                isClientInitiated: false,
                prompt_id: 'prompt-id-sub',
                agentId: 'agent-sub',
            },
            status: 'success',
            responseSubmittedToGemini: false,
            response: {
                callId: 'subagent-call',
                responseParts: [{ text: 'subagent output' }],
                resultDisplay: undefined,
                error: undefined,
                errorType: undefined,
            },
            invocation: {
                getDescription: () => `Mock description`,
            },
            tool: {
                name: 'task',
                displayName: 'Task',
                description: 'Launch subagent',
                build: vi.fn(),
            },
        };
        await act(async () => {
            if (capturedOnComplete) {
                await capturedOnComplete(Symbol('scheduler'), [subagentToolCall], {
                    isPrimary: true,
                });
            }
        });
        await waitFor(() => {
            expect(mockMarkToolsAsSubmitted).toHaveBeenCalledWith(['subagent-call']);
            expect(mockSendMessageStream).not.toHaveBeenCalled();
            expect(client.addHistory).not.toHaveBeenCalled();
        });
    });
});
//# sourceMappingURL=useGeminiStream.subagent.spec.js.map