/**
 * Unit tests for TopBar component
 *
 * Tests the top navigation bar that appears at the top of the application.
 * Covers:
 * - Rendering of all UI elements (search, theme toggle, notifications, etc.)
 * - Menu button for mobile view
 * - Theme toggle functionality
 * - User profile dropdown integration
 * - Language selector integration
 * - Notification dropdown integration
 * - Sandbox toggle integration
 * - Search input
 */

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import TopBar from '../TopBar';
import { User } from '../../types';

// Mock child components
vi.mock('../UserProfileDropdown', () => ({
  default: ({ user }: { user: User }) => (
    <div data-testid="user-profile-dropdown">User: {user.email}</div>
  ),
}));

vi.mock('../LanguageSelector', () => ({
  default: () => <div data-testid="language-selector">Language Selector</div>,
}));

vi.mock('../NotificationDropdown', () => ({
  default: ({ onTicketClick }: { onTicketClick?: (id: string) => void }) => (
    <div data-testid="notification-dropdown">Notifications</div>
  ),
}));

vi.mock('../SandboxToggle', () => ({
  default: ({ isSandbox, sandboxEnabled, onToggle, isToggling }: any) => (
    <div data-testid="sandbox-toggle">
      Sandbox: {isSandbox ? 'On' : 'Off'}
      <button onClick={onToggle} disabled={isToggling}>
        Toggle Sandbox
      </button>
    </div>
  ),
}));

// Mock SandboxContext
const mockUseSandbox = vi.fn();
vi.mock('../../contexts/SandboxContext', () => ({
  useSandbox: () => mockUseSandbox(),
}));

// Mock react-i18next
vi.mock('react-i18next', () => ({
  useTranslation: () => ({
    t: (key: string) => {
      const translations: Record<string, string> = {
        'common.search': 'Search...',
      };
      return translations[key] || key;
    },
  }),
}));

// Test data factory for User objects
const createMockUser = (overrides?: Partial<User>): User => ({
  id: '1',
  email: 'test@example.com',
  firstName: 'Test',
  lastName: 'User',
  role: 'owner',
  phone: '+1234567890',
  preferences: {
    email: true,
    sms: false,
    in_app: true,
  },
  twoFactorEnabled: false,
  profilePictureUrl: undefined,
  ...overrides,
});

// Wrapper component that provides router context
const renderWithRouter = (ui: React.ReactElement) => {
  return render(<BrowserRouter>{ui}</BrowserRouter>);
};

describe('TopBar', () => {
  const mockToggleTheme = vi.fn();
  const mockOnMenuClick = vi.fn();
  const mockOnTicketClick = vi.fn();

  beforeEach(() => {
    vi.clearAllMocks();
    mockUseSandbox.mockReturnValue({
      isSandbox: false,
      sandboxEnabled: true,
      toggleSandbox: vi.fn(),
      isToggling: false,
    });
  });

  describe('Rendering', () => {
    it('should render the top bar with all main elements', () => {
      const user = createMockUser();

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      expect(screen.getByTestId('user-profile-dropdown')).toBeInTheDocument();
      expect(screen.getByTestId('language-selector')).toBeInTheDocument();
      expect(screen.getByTestId('notification-dropdown')).toBeInTheDocument();
      expect(screen.getByTestId('sandbox-toggle')).toBeInTheDocument();
    });

    it('should render search input on desktop', () => {
      const user = createMockUser();

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      const searchInput = screen.getByPlaceholderText('Search...');
      expect(searchInput).toBeInTheDocument();
      expect(searchInput).toHaveClass('w-full');
    });

    it('should render mobile menu button', () => {
      const user = createMockUser();

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      const menuButton = screen.getByLabelText('Open sidebar');
      expect(menuButton).toBeInTheDocument();
    });

    it('should pass user to UserProfileDropdown', () => {
      const user = createMockUser({ email: 'john@example.com' });

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      expect(screen.getByText('User: john@example.com')).toBeInTheDocument();
    });

    it('should render with dark mode styles when isDarkMode is true', () => {
      const user = createMockUser();

      const { container } = renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={true}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      const header = container.querySelector('header');
      expect(header).toHaveClass('dark:bg-gray-800', 'dark:border-gray-700');
    });
  });

  describe('Theme Toggle', () => {
    it('should render moon icon when in light mode', () => {
      const user = createMockUser();

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      // The button should exist
      const buttons = screen.getAllByRole('button');
      const themeButton = buttons.find(btn =>
        btn.className.includes('text-gray-400')
      );
      expect(themeButton).toBeInTheDocument();
    });

    it('should render sun icon when in dark mode', () => {
      const user = createMockUser();

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={true}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      // The button should exist
      const buttons = screen.getAllByRole('button');
      const themeButton = buttons.find(btn =>
        btn.className.includes('text-gray-400')
      );
      expect(themeButton).toBeInTheDocument();
    });

    it('should call toggleTheme when theme button is clicked', () => {
      const user = createMockUser();

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      // Find the theme toggle button by finding buttons, then clicking the one with the theme classes
      const buttons = screen.getAllByRole('button');
      // The theme button is the one with the hover styles and not the menu button
      const themeButton = buttons.find(btn =>
        btn.className.includes('text-gray-400') &&
        btn.className.includes('hover:text-gray-600') &&
        !btn.getAttribute('aria-label')
      );

      expect(themeButton).toBeTruthy();
      if (themeButton) {
        fireEvent.click(themeButton);
        expect(mockToggleTheme).toHaveBeenCalledTimes(1);
      }
    });
  });

  describe('Mobile Menu Button', () => {
    it('should render menu button with correct aria-label', () => {
      const user = createMockUser();

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      const menuButton = screen.getByLabelText('Open sidebar');
      expect(menuButton).toHaveAttribute('aria-label', 'Open sidebar');
    });

    it('should call onMenuClick when menu button is clicked', () => {
      const user = createMockUser();

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      const menuButton = screen.getByLabelText('Open sidebar');
      fireEvent.click(menuButton);

      expect(mockOnMenuClick).toHaveBeenCalledTimes(1);
    });

    it('should have mobile-only classes on menu button', () => {
      const user = createMockUser();

      const { container } = renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      const menuButton = screen.getByLabelText('Open sidebar');
      expect(menuButton).toHaveClass('md:hidden');
    });
  });

  describe('Search Input', () => {
    it('should render search input with correct placeholder', () => {
      const user = createMockUser();

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      const searchInput = screen.getByPlaceholderText('Search...');
      expect(searchInput).toHaveAttribute('type', 'text');
    });

    it('should have search icon', () => {
      const user = createMockUser();

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      // Search icon should be present
      const searchInput = screen.getByPlaceholderText('Search...');
      expect(searchInput.parentElement?.querySelector('span')).toBeInTheDocument();
    });

    it('should allow typing in search input', () => {
      const user = createMockUser();

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      const searchInput = screen.getByPlaceholderText('Search...') as HTMLInputElement;
      fireEvent.change(searchInput, { target: { value: 'test query' } });

      expect(searchInput.value).toBe('test query');
    });

    it('should have focus styles on search input', () => {
      const user = createMockUser();

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      const searchInput = screen.getByPlaceholderText('Search...');
      expect(searchInput).toHaveClass('focus:outline-none', 'focus:border-brand-500');
    });
  });

  describe('Sandbox Integration', () => {
    it('should render SandboxToggle component', () => {
      const user = createMockUser();

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      expect(screen.getByTestId('sandbox-toggle')).toBeInTheDocument();
    });

    it('should pass sandbox state to SandboxToggle', () => {
      const user = createMockUser();
      mockUseSandbox.mockReturnValue({
        isSandbox: true,
        sandboxEnabled: true,
        toggleSandbox: vi.fn(),
        isToggling: false,
      });

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      expect(screen.getByText(/Sandbox: On/i)).toBeInTheDocument();
    });

    it('should handle sandbox toggle being disabled', () => {
      const user = createMockUser();
      mockUseSandbox.mockReturnValue({
        isSandbox: false,
        sandboxEnabled: false,
        toggleSandbox: vi.fn(),
        isToggling: false,
      });

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      expect(screen.getByTestId('sandbox-toggle')).toBeInTheDocument();
    });
  });

  describe('Notification Integration', () => {
    it('should render NotificationDropdown', () => {
      const user = createMockUser();

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      expect(screen.getByTestId('notification-dropdown')).toBeInTheDocument();
    });

    it('should pass onTicketClick to NotificationDropdown when provided', () => {
      const user = createMockUser();

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
          onTicketClick={mockOnTicketClick}
        />
      );

      expect(screen.getByTestId('notification-dropdown')).toBeInTheDocument();
    });

    it('should work without onTicketClick prop', () => {
      const user = createMockUser();

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      expect(screen.getByTestId('notification-dropdown')).toBeInTheDocument();
    });
  });

  describe('Language Selector Integration', () => {
    it('should render LanguageSelector', () => {
      const user = createMockUser();

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      expect(screen.getByTestId('language-selector')).toBeInTheDocument();
    });
  });

  describe('Different User Roles', () => {
    it('should render for owner role', () => {
      const user = createMockUser({ role: 'owner' });

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      expect(screen.getByTestId('user-profile-dropdown')).toBeInTheDocument();
    });

    it('should render for manager role', () => {
      const user = createMockUser({ role: 'manager' });

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      expect(screen.getByTestId('user-profile-dropdown')).toBeInTheDocument();
    });

    it('should render for staff role', () => {
      const user = createMockUser({ role: 'staff' });

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      expect(screen.getByTestId('user-profile-dropdown')).toBeInTheDocument();
    });

    it('should render for platform roles', () => {
      const user = createMockUser({ role: 'platform_manager' });

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      expect(screen.getByTestId('user-profile-dropdown')).toBeInTheDocument();
    });
  });

  describe('Layout and Styling', () => {
    it('should have fixed height', () => {
      const user = createMockUser();

      const { container } = renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      const header = container.querySelector('header');
      expect(header).toHaveClass('h-16');
    });

    it('should have border at bottom', () => {
      const user = createMockUser();

      const { container } = renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      const header = container.querySelector('header');
      expect(header).toHaveClass('border-b');
    });

    it('should use flexbox layout', () => {
      const user = createMockUser();

      const { container } = renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      const header = container.querySelector('header');
      expect(header).toHaveClass('flex', 'items-center', 'justify-between');
    });

    it('should have responsive padding', () => {
      const user = createMockUser();

      const { container } = renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      const header = container.querySelector('header');
      expect(header).toHaveClass('px-4', 'sm:px-8');
    });
  });

  describe('Accessibility', () => {
    it('should have semantic header element', () => {
      const user = createMockUser();

      const { container } = renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      expect(container.querySelector('header')).toBeInTheDocument();
    });

    it('should have proper button roles', () => {
      const user = createMockUser();

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      const buttons = screen.getAllByRole('button');
      expect(buttons.length).toBeGreaterThan(0);
    });

    it('should have focus styles on interactive elements', () => {
      const user = createMockUser();

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      const menuButton = screen.getByLabelText('Open sidebar');
      expect(menuButton).toHaveClass('focus:outline-none', 'focus:ring-2');
    });
  });

  describe('Responsive Behavior', () => {
    it('should hide search on mobile', () => {
      const user = createMockUser();

      const { container } = renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      // Search container is a relative div with hidden md:block classes
      const searchContainer = container.querySelector('.hidden.md\\:block');
      expect(searchContainer).toBeInTheDocument();
    });

    it('should show menu button only on mobile', () => {
      const user = createMockUser();

      renderWithRouter(
        <TopBar
          user={user}
          isDarkMode={false}
          toggleTheme={mockToggleTheme}
          onMenuClick={mockOnMenuClick}
        />
      );

      const menuButton = screen.getByLabelText('Open sidebar');
      expect(menuButton).toHaveClass('md:hidden');
    });
  });
});
