// src/features/voice-assistant/VoiceAssistant.test.tsx
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { VoiceAssistant } from './VoiceAssistant';
import * as aiApiClient from '../../services/aiApiClient';

// Mock dependencies to isolate the component
vi.mock('../../services/aiApiClient', () => ({
  startVoiceSession: vi.fn(),
}));
vi.mock('../../services/logger.client', () => ({
  logger: {
    info: vi.fn(),
    debug: vi.fn(),
    error: vi.fn(),
  },
}));
vi.mock('../../components/icons/MicrophoneIcon', () => ({
  MicrophoneIcon: () => <div data-testid="mic-icon" />,
}));
vi.mock('../../components/icons/XMarkIcon', () => ({
  XMarkIcon: () => <div data-testid="x-icon" />,
}));

// Mock browser APIs that are not available in JSDOM
Object.defineProperty(window, 'AudioContext', {
  writable: true,
  value: vi.fn().mockImplementation(() => ({
    createMediaStreamSource: vi.fn(() => ({
      connect: vi.fn(),
    })),
    createScriptProcessor: vi.fn(() => ({
      connect: vi.fn(),
      disconnect: vi.fn(),
    })),
    close: vi.fn(),
  })),
});

Object.defineProperty(navigator, 'mediaDevices', {
  writable: true,
  value: {
    getUserMedia: vi.fn(),
  },
});

describe('VoiceAssistant Component', () => {
  const mockOnClose = vi.fn();

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

  it('should not render when isOpen is false', () => {
    const { container } = render(<VoiceAssistant isOpen={false} onClose={mockOnClose} />);
    expect(container.firstChild).toBeNull();
  });

  it('should render correctly when isOpen is true', () => {
    render(<VoiceAssistant isOpen={true} onClose={mockOnClose} />);

    expect(screen.getByRole('heading', { name: /voice assistant/i })).toBeInTheDocument();
    expect(screen.getByText('Click the mic to start')).toBeInTheDocument();
    expect(screen.getByRole('button', { name: /close/i })).toBeInTheDocument();
    expect(screen.getByTestId('mic-icon')).toBeInTheDocument();
  });

  it('should call onClose when the close button is clicked', () => {
    render(<VoiceAssistant isOpen={true} onClose={mockOnClose} />);
    fireEvent.click(screen.getByRole('button', { name: /close/i }));
    expect(mockOnClose).toHaveBeenCalledTimes(1);
  });

  it('should call onClose when the overlay is clicked', () => {
    render(<VoiceAssistant isOpen={true} onClose={mockOnClose} />);
    // The overlay is the root div of the modal
    fireEvent.click(screen.getByRole('dialog').parentElement!);
    expect(mockOnClose).toHaveBeenCalledTimes(1);
  });

  it('should not call onClose when the modal content is clicked', () => {
    render(<VoiceAssistant isOpen={true} onClose={mockOnClose} />);
    fireEvent.click(screen.getByRole('heading', { name: /voice assistant/i }));
    expect(mockOnClose).not.toHaveBeenCalled();
  });

  it('should call startVoiceSession when the microphone button is clicked in idle state', () => {
    render(<VoiceAssistant isOpen={true} onClose={mockOnClose} />);
    const micButton = screen.getByRole('button', { name: /start voice session/i });
    fireEvent.click(micButton);
    expect(aiApiClient.startVoiceSession).toHaveBeenCalledTimes(1);
  });

  it('should display history and current transcripts', () => {
    render(<VoiceAssistant isOpen={true} onClose={mockOnClose} />);

    // This test is a bit more involved as it requires manipulating internal state.
    // For a simple test, we can check that the container for history exists.
    // A more advanced test would involve mocking the `startVoiceSession` callbacks.
    const historyContainer = screen.getByRole('heading', { name: /voice assistant/i }).parentElement?.nextElementSibling;
    expect(historyContainer).toBeInTheDocument();
    expect(historyContainer).toBeEmptyDOMElement(); // Initially empty
  });
});
