/**
 * Tests for ProjectSwitcher Component
 * Verifies project selection, navigation, and accessibility
 */

import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { ProjectSwitcher, ProjectSelect } from '@/components/layout/ProjectSwitcher';
import { mockUseRouter } from 'next-intl/navigation';

// Mock useRouter
const mockPush = jest.fn();

describe('ProjectSwitcher', () => {
  const mockProjects = [
    { id: '1', slug: 'project-one', name: 'Project One' },
    { id: '2', slug: 'project-two', name: 'Project Two' },
    { id: '3', slug: 'project-three', name: 'Project Three' },
  ];

  beforeEach(() => {
    jest.clearAllMocks();
    mockUseRouter.mockReturnValue({
      push: mockPush,
      replace: jest.fn(),
      prefetch: jest.fn(),
      back: jest.fn(),
      forward: jest.fn(),
      refresh: jest.fn(),
    });
  });

  describe('Rendering', () => {
    it('renders create project button when no projects', () => {
      render(<ProjectSwitcher projects={[]} />);

      expect(screen.getByTestId('create-project-button')).toBeInTheDocument();
      expect(screen.getByText('Create Project')).toBeInTheDocument();
    });

    it('renders project switcher trigger when projects exist', () => {
      render(<ProjectSwitcher projects={mockProjects} />);

      expect(screen.getByTestId('project-switcher-trigger')).toBeInTheDocument();
    });

    it('displays current project name', () => {
      render(
        <ProjectSwitcher
          projects={mockProjects}
          currentProject={mockProjects[0]}
        />
      );

      expect(screen.getByText('Project One')).toBeInTheDocument();
    });

    it('displays placeholder when no current project', () => {
      render(<ProjectSwitcher projects={mockProjects} />);

      expect(screen.getByText('Select Project')).toBeInTheDocument();
    });
  });

  describe('Dropdown Menu', () => {
    it('opens dropdown when trigger is clicked', async () => {
      const user = userEvent.setup();

      render(<ProjectSwitcher projects={mockProjects} />);

      const trigger = screen.getByTestId('project-switcher-trigger');
      await user.click(trigger);

      await waitFor(() => {
        expect(screen.getByTestId('project-switcher-menu')).toBeInTheDocument();
      });
    });

    it('displays all projects in dropdown', async () => {
      const user = userEvent.setup();

      render(<ProjectSwitcher projects={mockProjects} />);

      const trigger = screen.getByTestId('project-switcher-trigger');
      await user.click(trigger);

      await waitFor(() => {
        expect(screen.getByTestId('project-option-project-one')).toBeInTheDocument();
        expect(screen.getByTestId('project-option-project-two')).toBeInTheDocument();
        expect(screen.getByTestId('project-option-project-three')).toBeInTheDocument();
      });
    });

    it('shows current indicator on selected project', async () => {
      const user = userEvent.setup();

      render(
        <ProjectSwitcher
          projects={mockProjects}
          currentProject={mockProjects[0]}
        />
      );

      const trigger = screen.getByTestId('project-switcher-trigger');
      await user.click(trigger);

      await waitFor(() => {
        const currentOption = screen.getByTestId('project-option-project-one');
        expect(currentOption).toHaveTextContent('Current');
      });
    });

    it('includes create new project option', async () => {
      const user = userEvent.setup();

      render(<ProjectSwitcher projects={mockProjects} />);

      const trigger = screen.getByTestId('project-switcher-trigger');
      await user.click(trigger);

      await waitFor(() => {
        expect(screen.getByTestId('create-project-option')).toBeInTheDocument();
        expect(screen.getByText('Create New Project')).toBeInTheDocument();
      });
    });
  });

  describe('Navigation', () => {
    it('navigates to project when option is selected', async () => {
      const user = userEvent.setup();

      render(<ProjectSwitcher projects={mockProjects} />);

      const trigger = screen.getByTestId('project-switcher-trigger');
      await user.click(trigger);

      const projectOption = await screen.findByTestId('project-option-project-two');
      await user.click(projectOption);

      expect(mockPush).toHaveBeenCalledWith('/projects/project-two');
    });

    it('calls onProjectChange callback when provided', async () => {
      const user = userEvent.setup();
      const mockOnChange = jest.fn();

      render(
        <ProjectSwitcher
          projects={mockProjects}
          onProjectChange={mockOnChange}
        />
      );

      const trigger = screen.getByTestId('project-switcher-trigger');
      await user.click(trigger);

      const projectOption = await screen.findByTestId('project-option-project-two');
      await user.click(projectOption);

      expect(mockOnChange).toHaveBeenCalledWith('project-two');
      expect(mockPush).not.toHaveBeenCalled();
    });

    it('navigates to create project page', async () => {
      const user = userEvent.setup();

      render(<ProjectSwitcher projects={mockProjects} />);

      const trigger = screen.getByTestId('project-switcher-trigger');
      await user.click(trigger);

      const createOption = await screen.findByTestId('create-project-option');
      await user.click(createOption);

      expect(mockPush).toHaveBeenCalledWith('/projects/new');
    });

    it('navigates from empty state button', async () => {
      const user = userEvent.setup();

      render(<ProjectSwitcher projects={[]} />);

      const createButton = screen.getByTestId('create-project-button');
      await user.click(createButton);

      expect(mockPush).toHaveBeenCalledWith('/projects/new');
    });
  });

  describe('Accessibility', () => {
    it('has accessible label on trigger', () => {
      render(
        <ProjectSwitcher
          projects={mockProjects}
          currentProject={mockProjects[0]}
        />
      );

      const trigger = screen.getByTestId('project-switcher-trigger');
      expect(trigger).toHaveAttribute(
        'aria-label',
        'Switch project, current: Project One'
      );
    });

    it('has accessible label when no current project', () => {
      render(<ProjectSwitcher projects={mockProjects} />);

      const trigger = screen.getByTestId('project-switcher-trigger');
      expect(trigger).toHaveAttribute('aria-label', 'Select project');
    });
  });
});

describe('ProjectSelect', () => {
  const mockProjects = [
    { id: '1', slug: 'project-one', name: 'Project One' },
    { id: '2', slug: 'project-two', name: 'Project Two' },
  ];

  describe('Rendering', () => {
    it('renders select component', () => {
      render(
        <ProjectSelect
          projects={mockProjects}
          onValueChange={jest.fn()}
        />
      );

      expect(screen.getByTestId('project-select')).toBeInTheDocument();
    });

    it('displays placeholder', () => {
      render(
        <ProjectSelect
          projects={mockProjects}
          onValueChange={jest.fn()}
          placeholder="Choose a project"
        />
      );

      expect(screen.getByText('Choose a project')).toBeInTheDocument();
    });

    it('has combobox role', () => {
      render(
        <ProjectSelect
          projects={mockProjects}
          onValueChange={jest.fn()}
        />
      );

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

    it('applies custom className', () => {
      render(
        <ProjectSelect
          projects={mockProjects}
          onValueChange={jest.fn()}
          className="custom-class"
        />
      );

      const select = screen.getByTestId('project-select');
      expect(select).toHaveClass('custom-class');
    });
  });

  // Note: Selection interaction tests are skipped because Radix UI Select
  // doesn't properly open in JSDOM environment. The component is tested
  // through E2E tests instead.
});
