import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent, waitFor } from '@testing-library/svelte';
import AssistantChatPanel from '../AssistantChatPanel.svelte';
import * as api from '$lib/api/assistant';
import { assistantChatStore } from '$lib/stores/assistantChat';

// Mock dependencies
vi.mock('$lib/api/assistant', () => ({
  getAssistantHistory: vi.fn(),
  confirmAssistantOperation: vi.fn(),
  cancelAssistantOperation: vi.fn(),
  getAssistantConversations: vi.fn(() => Promise.resolve({ items: [], total: 0 })),
  sendAssistantMessage: vi.fn()
}));

vi.mock('$lib/api', () => ({
  api: {
    getLlmStatus: vi.fn(() => Promise.resolve({ configured: true }))
  }
}));

vi.mock('$lib/toasts', () => ({
  addToast: vi.fn()
}));

vi.mock('$lib/stores/assistantChat', () => ({
  assistantChatStore: {
    subscribe: (fn) => {
      fn({ isOpen: true, conversationId: 'conv-1' });
      return () => { };
    }
  },
  closeAssistantChat: vi.fn(),
  setAssistantConversationId: vi.fn()
}));

vi.mock('$app/navigation', () => ({
  goto: vi.fn()
}));

vi.mock('$lib/i18n', () => ({
  t: {
    subscribe: (fn) => {
      fn({
        assistant: {
          action_failed: 'Action failed',
          confirm: 'Confirm',
          cancel: 'Cancel'
        }
      });
      return () => { };
    }
  }
}));

describe('AssistantChatPanel confirmation functional tests', () => {
  const mockMessage = {
    message_id: 'msg-123',
    role: 'assistant',
    text: 'Confirm migration?',
    created_at: new Date().toISOString(),
    conversation_id: 'conv-1',
    confirmation_id: 'conf-123',
    actions: [
      { type: 'confirm', label: 'Confirm' },
      { type: 'cancel', label: 'Cancel' }
    ]
  };

  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('renders action buttons and triggers confirm API call', async () => {
    // Mock getAssistantHistory to return our message
    api.getAssistantHistory.mockImplementation(async () => ({
      items: [mockMessage],
      total: 1,
      has_next: false
    }));

    render(AssistantChatPanel);

    // Wait for message to render
    const confirmBtn = await screen.findByText('Confirm', {}, { timeout: 3000 });
    expect(confirmBtn).toBeTruthy();

    await fireEvent.click(confirmBtn);

    expect(api.confirmAssistantOperation).toHaveBeenCalledWith('conf-123');
  });

  it('triggers cancel API call when cancel button is clicked', async () => {
    api.getAssistantHistory.mockImplementation(async () => ({
      items: [mockMessage],
      total: 1,
      has_next: false
    }));

    render(AssistantChatPanel);

    const cancelBtn = await screen.findByText('Cancel', {}, { timeout: 3000 });
    await fireEvent.click(cancelBtn);

    expect(api.cancelAssistantOperation).toHaveBeenCalledWith('conf-123');
  });

  it('shows toast error when action fails', async () => {
    api.getAssistantHistory.mockImplementation(async () => ({
      items: [mockMessage],
      total: 1,
      has_next: false
    }));
    api.confirmAssistantOperation.mockImplementation(async () => {
      throw new Error('Network error');
    });

    render(AssistantChatPanel);

    const confirmBtn = await screen.findByText('Confirm', {}, { timeout: 3000 });
    await fireEvent.click(confirmBtn);

    await waitFor(() => {
      // The component appends a failed message to the chat
      expect(screen.getAllByText(/Network error/)).toBeTruthy();
    }, { timeout: 3000 });
  });
});
