import { beforeEach, describe, expect, it, vi } from 'vitest';
const { mockGetCurrentGeminiUrl, mockReadGeminiSnapshot, mockSelectGeminiTool, mockSendGeminiMessage, mockStartNewGeminiChat, mockWaitForGeminiSubmission, mockWaitForGeminiConfirmButton, mockGetLatestGeminiAssistantResponse, } = vi.hoisted(() => ({
    mockGetCurrentGeminiUrl: vi.fn(),
    mockReadGeminiSnapshot: vi.fn(),
    mockSelectGeminiTool: vi.fn(),
    mockSendGeminiMessage: vi.fn(),
    mockStartNewGeminiChat: vi.fn(),
    mockWaitForGeminiSubmission: vi.fn(),
    mockWaitForGeminiConfirmButton: vi.fn(),
    mockGetLatestGeminiAssistantResponse: vi.fn(),
}));
vi.mock('./utils.js', () => ({
    GEMINI_DOMAIN: 'gemini.google.com',
    GEMINI_APP_URL: 'https://gemini.google.com/app',
    GEMINI_DEEP_RESEARCH_DEFAULT_TOOL_LABELS: ['Deep Research', 'Deep research', '\u6df1\u5ea6\u7814\u7a76'],
    GEMINI_DEEP_RESEARCH_DEFAULT_CONFIRM_LABELS: [
        'Start research',
        'Start Research',
        'Start deep research',
        'Start Deep Research',
        'Generate research plan',
        'Generate Research Plan',
        'Generate deep research plan',
        'Generate Deep Research Plan',
        '\u5f00\u59cb\u7814\u7a76',
        '\u5f00\u59cb\u6df1\u5ea6\u7814\u7a76',
        '\u5f00\u59cb\u8c03\u7814',
        '\u751f\u6210\u7814\u7a76\u8ba1\u5212',
        '\u751f\u6210\u8c03\u7814\u8ba1\u5212',
    ],
    resolveGeminiLabels: (value, fallback) => {
        const label = String(value ?? '').trim();
        return label ? [label] : fallback;
    },
    getCurrentGeminiUrl: mockGetCurrentGeminiUrl,
    getLatestGeminiAssistantResponse: mockGetLatestGeminiAssistantResponse,
    readGeminiSnapshot: mockReadGeminiSnapshot,
    selectGeminiTool: mockSelectGeminiTool,
    sendGeminiMessage: mockSendGeminiMessage,
    startNewGeminiChat: mockStartNewGeminiChat,
    waitForGeminiSubmission: mockWaitForGeminiSubmission,
    waitForGeminiConfirmButton: mockWaitForGeminiConfirmButton,
}));
import { deepResearchCommand } from './deep-research.js';
describe('gemini/deep-research', () => {
    const page = {};
    const runCommand = (kwargs) => deepResearchCommand.func(page, { timeout: 180, ...kwargs });
    beforeEach(() => {
        vi.clearAllMocks();
        mockGetCurrentGeminiUrl.mockResolvedValue('https://gemini.google.com/app/chat');
        mockReadGeminiSnapshot.mockResolvedValue({
            turns: [],
            transcriptLines: [],
            composerHasText: false,
            isGenerating: false,
            structuredTurnsTrusted: true,
        });
        mockSelectGeminiTool.mockResolvedValue('Deep Research');
        mockSendGeminiMessage.mockResolvedValue();
        mockStartNewGeminiChat.mockResolvedValue();
        mockWaitForGeminiSubmission.mockResolvedValue({
            snapshot: { turns: [], transcriptLines: [], composerHasText: false, isGenerating: false, structuredTurnsTrusted: true },
            preSendAssistantCount: 0,
            userAnchorTurn: null,
            reason: 'user_turn',
        });
        mockWaitForGeminiConfirmButton.mockResolvedValue('Start research');
        mockGetLatestGeminiAssistantResponse.mockResolvedValue('');
    });
    it('starts a new chat by default, then sends prompt and confirms deep research', async () => {
        const result = await runCommand({ prompt: 'research this topic' });
        expect(mockStartNewGeminiChat).toHaveBeenCalledTimes(1);
        expect(mockSelectGeminiTool).toHaveBeenCalledTimes(1);
        expect(mockSendGeminiMessage).toHaveBeenCalledWith(page, 'research this topic');
        expect(mockWaitForGeminiSubmission).toHaveBeenCalledTimes(1);
        expect(mockWaitForGeminiConfirmButton).toHaveBeenCalledWith(page, expect.arrayContaining(['Start research', 'Start deep research', 'Generate research plan', '\u751f\u6210\u7814\u7a76\u8ba1\u5212']), 180);
        expect(result).toEqual([{ status: 'started', url: 'https://gemini.google.com/app/chat' }]);
    });
    it('returns tool-not-found when the tool cannot be selected', async () => {
        mockSelectGeminiTool.mockResolvedValue('');
        const result = await runCommand({ prompt: 'research this topic' });
        expect(result).toEqual([{ status: 'tool-not-found', url: 'https://gemini.google.com/app/chat' }]);
        expect(mockSendGeminiMessage).not.toHaveBeenCalled();
        expect(mockWaitForGeminiSubmission).not.toHaveBeenCalled();
        expect(mockWaitForGeminiConfirmButton).not.toHaveBeenCalled();
    });
    it('retries send once when first submission cannot be confirmed', async () => {
        mockWaitForGeminiSubmission.mockResolvedValueOnce(null).mockResolvedValueOnce({
            snapshot: { turns: [], transcriptLines: [], composerHasText: false, isGenerating: false, structuredTurnsTrusted: true },
            preSendAssistantCount: 0,
            userAnchorTurn: null,
            reason: 'user_turn',
        });
        const result = await runCommand({ prompt: 'research this topic' });
        expect(mockSelectGeminiTool).toHaveBeenCalledTimes(2);
        expect(mockReadGeminiSnapshot).toHaveBeenCalledTimes(2);
        expect(mockSendGeminiMessage).toHaveBeenCalledTimes(2);
        expect(mockWaitForGeminiSubmission).toHaveBeenCalledTimes(2);
        expect(result).toEqual([{ status: 'started', url: 'https://gemini.google.com/app/chat' }]);
    });
    it('returns submit-not-found when submission cannot be confirmed after retry', async () => {
        mockWaitForGeminiSubmission.mockResolvedValue(null);
        const result = await runCommand({ prompt: 'research this topic' });
        expect(mockSelectGeminiTool).toHaveBeenCalledTimes(2);
        expect(mockSendGeminiMessage).toHaveBeenCalledTimes(2);
        expect(mockWaitForGeminiConfirmButton).not.toHaveBeenCalled();
        expect(result).toEqual([{ status: 'submit-not-found', url: 'https://gemini.google.com/app/chat' }]);
    });
    it('returns confirm-not-found when no confirm button is found', async () => {
        mockWaitForGeminiConfirmButton.mockResolvedValue('');
        const result = await runCommand({ prompt: 'research this topic' });
        expect(result).toEqual([{ status: 'confirm-not-found', url: 'https://gemini.google.com/app/chat' }]);
    });
    it('returns started when confirm is missing but research appears to be running', async () => {
        mockWaitForGeminiConfirmButton.mockResolvedValue('');
        mockGetCurrentGeminiUrl.mockResolvedValue('https://gemini.google.com/app/abc123');
        mockGetLatestGeminiAssistantResponse.mockResolvedValue('Researching websites now');
        const result = await runCommand({ prompt: 'research this topic' });
        expect(result).toEqual([{ status: 'started', url: 'https://gemini.google.com/app/abc123' }]);
    });
    it('does not treat conversation url alone as started when confirm is missing', async () => {
        mockWaitForGeminiConfirmButton.mockResolvedValue('');
        mockGetCurrentGeminiUrl.mockResolvedValue('https://gemini.google.com/app/abc999');
        mockGetLatestGeminiAssistantResponse.mockResolvedValue('I drafted a plan. Start research');
        const result = await runCommand({ prompt: 'research this topic' });
        expect(result).toEqual([{ status: 'confirm-not-found', url: 'https://gemini.google.com/app/abc999' }]);
    });
    it('retries once when stuck on root app URL and starts successfully on second confirm', async () => {
        mockWaitForGeminiConfirmButton.mockResolvedValueOnce('').mockResolvedValueOnce('Start research');
        mockGetCurrentGeminiUrl.mockResolvedValueOnce('https://gemini.google.com/app').mockResolvedValueOnce('https://gemini.google.com/app/retry123');
        const result = await runCommand({ prompt: 'research this topic', timeout: 20 });
        expect(mockSelectGeminiTool).toHaveBeenCalledTimes(2);
        expect(mockSendGeminiMessage).toHaveBeenCalledTimes(1);
        expect(mockWaitForGeminiConfirmButton).toHaveBeenCalledTimes(2);
        expect(result).toEqual([{ status: 'started', url: 'https://gemini.google.com/app/retry123' }]);
    });
    it('treats root-url confirm as false-positive and retries', async () => {
        mockWaitForGeminiConfirmButton.mockResolvedValueOnce('Start research').mockResolvedValueOnce('Start research');
        mockGetCurrentGeminiUrl.mockResolvedValueOnce('https://gemini.google.com/app').mockResolvedValueOnce('https://gemini.google.com/app/retry456');
        const result = await runCommand({ prompt: 'research this topic', timeout: 20 });
        expect(mockSelectGeminiTool).toHaveBeenCalledTimes(2);
        expect(mockSendGeminiMessage).toHaveBeenCalledTimes(1);
        expect(result).toEqual([{ status: 'started', url: 'https://gemini.google.com/app/retry456' }]);
    });
    it('does not resend prompt during root-url retry to avoid duplicate chats', async () => {
        mockWaitForGeminiConfirmButton.mockResolvedValueOnce('Start research').mockResolvedValueOnce('');
        mockGetCurrentGeminiUrl.mockResolvedValueOnce('https://gemini.google.com/app').mockResolvedValueOnce('https://gemini.google.com/app');
        mockGetLatestGeminiAssistantResponse.mockResolvedValue('');
        const result = await runCommand({ prompt: 'research this topic', timeout: 20 });
        expect(mockSelectGeminiTool).toHaveBeenCalledTimes(2);
        expect(mockSendGeminiMessage).toHaveBeenCalledTimes(1);
        expect(mockWaitForGeminiConfirmButton).toHaveBeenCalledTimes(2);
        expect(result).toEqual([{ status: 'confirm-not-found', url: 'https://gemini.google.com/app' }]);
    });
    it('attempts one more confirm click when still waiting for start research', async () => {
        mockWaitForGeminiConfirmButton
            .mockResolvedValueOnce('')
            .mockResolvedValueOnce('Start research');
        mockGetCurrentGeminiUrl
            .mockResolvedValueOnce('https://gemini.google.com/app/xyz123')
            .mockResolvedValueOnce('https://gemini.google.com/app/xyz123');
        mockGetLatestGeminiAssistantResponse
            .mockResolvedValueOnce('I drafted a plan. Start research')
            .mockResolvedValueOnce('Researching websites now');
        const result = await runCommand({ prompt: 'research this topic', timeout: 20 });
        expect(mockWaitForGeminiConfirmButton).toHaveBeenCalledTimes(2);
        expect(mockWaitForGeminiConfirmButton).toHaveBeenNthCalledWith(2, page, expect.arrayContaining(['Start research', 'Start deep research', '开始研究', '开始深度研究']), 8);
        expect(mockSendGeminiMessage).toHaveBeenCalledTimes(1);
        expect(result).toEqual([{ status: 'started', url: 'https://gemini.google.com/app/xyz123' }]);
    });
    it('uses custom tool/confirm labels when provided', async () => {
        await runCommand({
            prompt: 'research this topic',
            tool: 'Custom Tool',
            confirm: 'Custom Confirm',
            timeout: 42,
        });
        expect(mockSelectGeminiTool).toHaveBeenCalledWith(page, ['Custom Tool']);
        expect(mockWaitForGeminiConfirmButton).toHaveBeenCalledWith(page, ['Custom Confirm'], 42);
    });
});
