import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/react';
import LanguageSelector from '../LanguageSelector';

// Create mock function for changeLanguage
const mockChangeLanguage = vi.fn();

// Mock react-i18next
vi.mock('react-i18next', () => ({
  useTranslation: () => ({
    i18n: {
      language: 'en',
      changeLanguage: mockChangeLanguage,
    },
  }),
}));

// Mock i18n module
vi.mock('../../i18n', () => ({
  supportedLanguages: [
    { code: 'en', name: 'English', flag: '🇺🇸' },
    { code: 'es', name: 'Español', flag: '🇪🇸' },
    { code: 'fr', name: 'Français', flag: '🇫🇷' },
  ],
}));

describe('LanguageSelector', () => {
  beforeEach(() => {
    mockChangeLanguage.mockClear();
  });

  describe('dropdown variant', () => {
    it('renders dropdown button', () => {
      render(<LanguageSelector />);
      const button = screen.getByRole('button');
      expect(button).toBeInTheDocument();
    });

    it('shows current language flag by default', () => {
      render(<LanguageSelector />);
      expect(screen.getByText('🇺🇸')).toBeInTheDocument();
    });

    it('shows current language name on larger screens', () => {
      render(<LanguageSelector />);
      expect(screen.getByText('English')).toBeInTheDocument();
    });

    it('opens dropdown on click', () => {
      render(<LanguageSelector />);
      const button = screen.getByRole('button');
      fireEvent.click(button);
      expect(screen.getByRole('listbox')).toBeInTheDocument();
    });

    it('shows all languages when open', () => {
      render(<LanguageSelector />);
      const button = screen.getByRole('button');
      fireEvent.click(button);
      expect(screen.getByText('Español')).toBeInTheDocument();
      expect(screen.getByText('Français')).toBeInTheDocument();
    });

    it('hides flag when showFlag is false', () => {
      render(<LanguageSelector showFlag={false} />);
      expect(screen.queryByText('🇺🇸')).not.toBeInTheDocument();
    });

    it('applies custom className', () => {
      const { container } = render(<LanguageSelector className="custom-class" />);
      expect(container.firstChild).toHaveClass('custom-class');
    });

    it('changes language when clicking a language option in dropdown', () => {
      render(<LanguageSelector />);
      const button = screen.getByRole('button');
      fireEvent.click(button);

      const spanishOption = screen.getByText('Español').closest('button');
      expect(spanishOption).toBeInTheDocument();

      fireEvent.click(spanishOption!);

      expect(mockChangeLanguage).toHaveBeenCalledWith('es');
    });

    it('closes dropdown when language is selected', () => {
      render(<LanguageSelector />);
      const button = screen.getByRole('button');
      fireEvent.click(button);

      expect(screen.getByRole('listbox')).toBeInTheDocument();

      const frenchOption = screen.getByText('Français').closest('button');
      fireEvent.click(frenchOption!);

      expect(screen.queryByRole('listbox')).not.toBeInTheDocument();
    });

    it('closes dropdown when clicking outside', () => {
      render(<LanguageSelector />);
      const button = screen.getByRole('button');
      fireEvent.click(button);

      expect(screen.getByRole('listbox')).toBeInTheDocument();

      // Click outside the dropdown
      fireEvent.mouseDown(document.body);

      expect(screen.queryByRole('listbox')).not.toBeInTheDocument();
    });

    it('does not close dropdown when clicking inside dropdown', () => {
      render(<LanguageSelector />);
      const button = screen.getByRole('button');
      fireEvent.click(button);

      expect(screen.getByRole('listbox')).toBeInTheDocument();

      const listbox = screen.getByRole('listbox');
      fireEvent.mouseDown(listbox);

      expect(screen.getByRole('listbox')).toBeInTheDocument();
    });

    it('toggles dropdown open/closed on button clicks', () => {
      render(<LanguageSelector />);
      const button = screen.getByRole('button');

      // Open dropdown
      fireEvent.click(button);
      expect(screen.getByRole('listbox')).toBeInTheDocument();

      // Close dropdown
      fireEvent.click(button);
      expect(screen.queryByRole('listbox')).not.toBeInTheDocument();
    });
  });

  describe('inline variant', () => {
    it('renders all language buttons', () => {
      render(<LanguageSelector variant="inline" />);
      const buttons = screen.getAllByRole('button');
      expect(buttons.length).toBe(3);
    });

    it('renders language names', () => {
      render(<LanguageSelector variant="inline" />);
      expect(screen.getByText(/English/)).toBeInTheDocument();
      expect(screen.getByText(/Español/)).toBeInTheDocument();
      expect(screen.getByText(/Français/)).toBeInTheDocument();
    });

    it('highlights current language', () => {
      render(<LanguageSelector variant="inline" />);
      const englishButton = screen.getByText(/English/).closest('button');
      expect(englishButton).toHaveClass('bg-brand-600');
    });

    it('shows flags by default', () => {
      render(<LanguageSelector variant="inline" />);
      expect(screen.getByText(/🇺🇸/)).toBeInTheDocument();
    });

    it('changes language when clicking a language button', () => {
      render(<LanguageSelector variant="inline" />);

      const spanishButton = screen.getByText(/Español/).closest('button');
      expect(spanishButton).toBeInTheDocument();

      fireEvent.click(spanishButton!);

      expect(mockChangeLanguage).toHaveBeenCalledWith('es');
    });

    it('calls changeLanguage with correct code for each language', () => {
      render(<LanguageSelector variant="inline" />);

      // Test English
      const englishButton = screen.getByText(/English/).closest('button');
      fireEvent.click(englishButton!);
      expect(mockChangeLanguage).toHaveBeenCalledWith('en');

      mockChangeLanguage.mockClear();

      // Test French
      const frenchButton = screen.getByText(/Français/).closest('button');
      fireEvent.click(frenchButton!);
      expect(mockChangeLanguage).toHaveBeenCalledWith('fr');
    });

    it('hides flags when showFlag is false', () => {
      render(<LanguageSelector variant="inline" showFlag={false} />);

      // Flags should not be visible
      expect(screen.queryByText('🇺🇸')).not.toBeInTheDocument();
      expect(screen.queryByText('🇪🇸')).not.toBeInTheDocument();
      expect(screen.queryByText('🇫🇷')).not.toBeInTheDocument();

      // But names should still be there
      expect(screen.getByText('English')).toBeInTheDocument();
      expect(screen.getByText('Español')).toBeInTheDocument();
      expect(screen.getByText('Français')).toBeInTheDocument();
    });

    it('applies custom className', () => {
      const { container } = render(<LanguageSelector variant="inline" className="custom-inline-class" />);
      expect(container.firstChild).toHaveClass('custom-inline-class');
    });
  });
});
