/**
 * MobileNav Component Tests
 *
 * Tests the hamburger menu navigation for mobile devices.
 * Covers: toggle interactions, dropdown behavior, accessibility,
 * and state management.
 */

import { render, screen, fireEvent } from '@testing-library/react';
import { MobileNav } from '../MobileNav';

// Mock lucide-react icons to avoid ESM issues
jest.mock('lucide-react', () => ({
  Menu: ({ size }: { size: number }) => (
    <svg data-testid="menu-icon" width={size} height={size} />
  ),
  X: ({ size }: { size: number }) => (
    <svg data-testid="close-icon" width={size} height={size} />
  ),
  ChevronDown: ({ size }: { size: number }) => (
    <svg data-testid="chevron-icon" width={size} height={size} />
  ),
}));

describe('MobileNav', () => {
  const basicNavigation = [
    { label: 'Products', href: 'https://www.amsoil.com/products', openInNewTab: true },
    { label: 'About', href: '/about', openInNewTab: false },
  ];

  const navigationWithDropdown = [
    {
      label: 'Products',
      href: null,
      children: [
        { label: 'Motor Oil', href: 'https://www.amsoil.com/motor-oil', openInNewTab: true },
        { label: 'Filters', href: 'https://www.amsoil.com/filters', openInNewTab: true },
      ],
    },
    { label: 'Contact', href: '/contact', openInNewTab: false },
  ];

  describe('Initial State', () => {
    it('starts with menu closed', () => {
      render(<MobileNav navigation={basicNavigation} />);

      // Use { hidden: true } because aria-hidden="true" when closed
      const menu = screen.getByRole('navigation', { hidden: true });
      expect(menu).toHaveAttribute('aria-hidden', 'true');
      expect(menu).not.toHaveClass('mobile-nav-menu--open');
    });

    it('shows hamburger icon when closed', () => {
      render(<MobileNav navigation={basicNavigation} />);

      expect(screen.getByTestId('menu-icon')).toBeInTheDocument();
      expect(screen.queryByTestId('close-icon')).not.toBeInTheDocument();
    });

    it('sets correct aria-label when closed', () => {
      render(<MobileNav navigation={basicNavigation} />);

      const toggle = screen.getByRole('button', { name: /open navigation menu/i });
      expect(toggle).toHaveAttribute('aria-expanded', 'false');
    });
  });

  describe('Toggle Behavior', () => {
    it('opens menu when hamburger clicked', () => {
      render(<MobileNav navigation={basicNavigation} />);

      const toggle = screen.getByRole('button', { name: /open navigation menu/i });
      fireEvent.click(toggle);

      const menu = screen.getByRole('navigation');
      expect(menu).toHaveAttribute('aria-hidden', 'false');
      expect(menu).toHaveClass('mobile-nav-menu--open');
    });

    it('shows close icon when open', () => {
      render(<MobileNav navigation={basicNavigation} />);

      const toggle = screen.getByRole('button', { name: /open navigation menu/i });
      fireEvent.click(toggle);

      expect(screen.getByTestId('close-icon')).toBeInTheDocument();
      expect(screen.queryByTestId('menu-icon')).not.toBeInTheDocument();
    });

    it('updates aria-label when open', () => {
      render(<MobileNav navigation={basicNavigation} />);

      const toggle = screen.getByRole('button', { name: /open navigation menu/i });
      fireEvent.click(toggle);

      expect(toggle).toHaveAttribute('aria-label', 'Close navigation menu');
      expect(toggle).toHaveAttribute('aria-expanded', 'true');
    });

    it('closes menu when toggle clicked again', () => {
      render(<MobileNav navigation={basicNavigation} />);

      const toggle = screen.getByRole('button', { name: /open navigation menu/i });
      fireEvent.click(toggle); // Open
      fireEvent.click(toggle); // Close

      const menu = screen.getByRole('navigation', { hidden: true });
      expect(menu).toHaveAttribute('aria-hidden', 'true');
      expect(menu).not.toHaveClass('mobile-nav-menu--open');
    });

    it('shows backdrop when menu is open', () => {
      const { container } = render(<MobileNav navigation={basicNavigation} />);

      // Initially no backdrop
      expect(container.querySelector('.mobile-nav-backdrop')).not.toBeInTheDocument();

      const toggle = screen.getByRole('button', { name: /open navigation menu/i });
      fireEvent.click(toggle);

      expect(container.querySelector('.mobile-nav-backdrop')).toBeInTheDocument();
    });

    it('closes menu when backdrop clicked', () => {
      const { container } = render(<MobileNav navigation={basicNavigation} />);

      const toggle = screen.getByRole('button', { name: /open navigation menu/i });
      fireEvent.click(toggle);

      const backdrop = container.querySelector('.mobile-nav-backdrop');
      fireEvent.click(backdrop!);

      // Use { hidden: true } because menu is now closed (aria-hidden="true")
      const menu = screen.getByRole('navigation', { hidden: true });
      expect(menu).toHaveAttribute('aria-hidden', 'true');
    });
  });

  describe('Navigation Items', () => {
    it('renders all navigation items', () => {
      render(<MobileNav navigation={basicNavigation} />);

      expect(screen.getByText('Products')).toBeInTheDocument();
      expect(screen.getByText('About')).toBeInTheDocument();
    });

    it('renders links with correct href', () => {
      render(<MobileNav navigation={basicNavigation} />);

      const productsLink = screen.getByText('Products').closest('a');
      expect(productsLink).toHaveAttribute('href', 'https://www.amsoil.com/products');

      const aboutLink = screen.getByText('About').closest('a');
      expect(aboutLink).toHaveAttribute('href', '/about');
    });

    it('applies target="_blank" for openInNewTab links', () => {
      render(<MobileNav navigation={basicNavigation} />);

      // AMSOIL links carry ZO attribution (compensated) -> rel="sponsored"
      const productsLink = screen.getByText('Products').closest('a');
      expect(productsLink).toHaveAttribute('target', '_blank');
      expect(productsLink).toHaveAttribute('rel', 'sponsored noopener noreferrer');

      // Internal links get no rel and no target
      const aboutLink = screen.getByText('About').closest('a');
      expect(aboutLink).not.toHaveAttribute('target');
      expect(aboutLink).not.toHaveAttribute('rel');
    });

    it('closes menu when nav link clicked', () => {
      render(<MobileNav navigation={basicNavigation} />);

      // Open menu
      const toggle = screen.getByRole('button', { name: /open navigation menu/i });
      fireEvent.click(toggle);

      // Click a nav link
      const aboutLink = screen.getByText('About');
      fireEvent.click(aboutLink);

      // Use { hidden: true } because menu is now closed (aria-hidden="true")
      const menu = screen.getByRole('navigation', { hidden: true });
      expect(menu).toHaveAttribute('aria-hidden', 'true');
    });

    it('renders items without href as spans', () => {
      render(<MobileNav navigation={navigationWithDropdown} />);

      const productsElement = screen.getByText('Products');
      expect(productsElement.tagName).toBe('SPAN');
      expect(productsElement).toHaveClass('mobile-nav-link--no-href');
    });
  });

  describe('Dropdown Behavior', () => {
    it('shows dropdown toggle for items with children', () => {
      render(<MobileNav navigation={navigationWithDropdown} />);

      // Products has children, should have a dropdown toggle
      // Use { hidden: true } because button is inside closed menu (aria-hidden="true")
      const dropdownToggle = screen.getByRole('button', { name: /expand products submenu/i, hidden: true });
      expect(dropdownToggle).toBeInTheDocument();
    });

    it('dropdown starts collapsed', () => {
      const { container } = render(<MobileNav navigation={navigationWithDropdown} />);

      const dropdown = container.querySelector('.mobile-nav-dropdown');
      expect(dropdown).not.toHaveClass('mobile-nav-dropdown--open');
      expect(dropdown).toHaveAttribute('aria-hidden', 'true');
    });

    it('expands dropdown when chevron clicked', () => {
      const { container } = render(<MobileNav navigation={navigationWithDropdown} />);

      // Use { hidden: true } because button is inside closed menu (aria-hidden="true")
      const dropdownToggle = screen.getByRole('button', { name: /expand products submenu/i, hidden: true });
      fireEvent.click(dropdownToggle);

      const dropdown = container.querySelector('.mobile-nav-dropdown');
      expect(dropdown).toHaveClass('mobile-nav-dropdown--open');
      expect(dropdown).toHaveAttribute('aria-hidden', 'false');
    });

    it('updates aria-label when dropdown expanded', () => {
      render(<MobileNav navigation={navigationWithDropdown} />);

      // Use { hidden: true } because button is inside closed menu (aria-hidden="true")
      const dropdownToggle = screen.getByRole('button', { name: /expand products submenu/i, hidden: true });
      fireEvent.click(dropdownToggle);

      expect(dropdownToggle).toHaveAttribute('aria-label', 'Collapse Products submenu');
      expect(dropdownToggle).toHaveAttribute('aria-expanded', 'true');
    });

    it('renders child items in dropdown', () => {
      render(<MobileNav navigation={navigationWithDropdown} />);

      expect(screen.getByText('Motor Oil')).toBeInTheDocument();
      expect(screen.getByText('Filters')).toBeInTheDocument();
    });

    it('closes menu when child link clicked', () => {
      render(<MobileNav navigation={navigationWithDropdown} />);

      // Open menu
      const toggle = screen.getByRole('button', { name: /open navigation menu/i });
      fireEvent.click(toggle);

      // Expand dropdown
      const dropdownToggle = screen.getByRole('button', { name: /expand products submenu/i });
      fireEvent.click(dropdownToggle);

      // Click child link
      const motorOilLink = screen.getByText('Motor Oil');
      fireEvent.click(motorOilLink);

      // Use { hidden: true } because menu is now closed (aria-hidden="true")
      const menu = screen.getByRole('navigation', { hidden: true });
      expect(menu).toHaveAttribute('aria-hidden', 'true');
    });

    it('collapses dropdown when clicked again', () => {
      const { container } = render(<MobileNav navigation={navigationWithDropdown} />);

      // Use { hidden: true } because button is inside closed menu (aria-hidden="true")
      const dropdownToggle = screen.getByRole('button', { name: /expand products submenu/i, hidden: true });
      fireEvent.click(dropdownToggle); // Expand
      fireEvent.click(dropdownToggle); // Collapse

      const dropdown = container.querySelector('.mobile-nav-dropdown');
      expect(dropdown).not.toHaveClass('mobile-nav-dropdown--open');
    });

    it('resets expanded items when menu closes', () => {
      const { container } = render(<MobileNav navigation={navigationWithDropdown} />);

      // Open menu
      const toggle = screen.getByRole('button', { name: /open navigation menu/i });
      fireEvent.click(toggle);

      // Expand dropdown
      const dropdownToggle = screen.getByRole('button', { name: /expand products submenu/i });
      fireEvent.click(dropdownToggle);

      // Close menu
      fireEvent.click(toggle);

      // Reopen menu
      fireEvent.click(toggle);

      // Dropdown should be collapsed
      const dropdown = container.querySelector('.mobile-nav-dropdown');
      expect(dropdown).not.toHaveClass('mobile-nav-dropdown--open');
    });
  });

  describe('Multiple Dropdowns', () => {
    const multipleDropdowns = [
      {
        label: 'Products',
        href: null,
        children: [{ label: 'Motor Oil', href: '/motor-oil' }],
      },
      {
        label: 'Services',
        href: null,
        children: [{ label: 'Oil Change', href: '/oil-change' }],
      },
    ];

    it('allows multiple dropdowns to be expanded', () => {
      const { container } = render(<MobileNav navigation={multipleDropdowns} />);

      // Use { hidden: true } because buttons are inside closed menu (aria-hidden="true")
      const toggles = screen.getAllByRole('button', { name: /expand.*submenu/i, hidden: true });

      // Expand both
      fireEvent.click(toggles[0]);
      fireEvent.click(toggles[1]);

      const dropdowns = container.querySelectorAll('.mobile-nav-dropdown');
      expect(dropdowns[0]).toHaveClass('mobile-nav-dropdown--open');
      expect(dropdowns[1]).toHaveClass('mobile-nav-dropdown--open');
    });
  });

  describe('Keyboard Accessibility', () => {
    it('closes menu when Escape key pressed', () => {
      render(<MobileNav navigation={basicNavigation} />);

      // Open menu
      const toggle = screen.getByRole('button', { name: /open navigation menu/i });
      fireEvent.click(toggle);

      expect(screen.getByRole('navigation')).toHaveClass('mobile-nav-menu--open');

      // Press Escape
      fireEvent.keyDown(document, { key: 'Escape' });

      // Use { hidden: true } because menu is now closed (aria-hidden="true")
      expect(screen.getByRole('navigation', { hidden: true })).not.toHaveClass('mobile-nav-menu--open');
    });

    it('resets expanded dropdowns when Escape closes menu', () => {
      const { container } = render(<MobileNav navigation={navigationWithDropdown} />);

      // Open menu
      const toggle = screen.getByRole('button', { name: /open navigation menu/i });
      fireEvent.click(toggle);

      // Expand dropdown
      const dropdownToggle = screen.getByRole('button', { name: /expand products submenu/i });
      fireEvent.click(dropdownToggle);

      expect(container.querySelector('.mobile-nav-dropdown')).toHaveClass('mobile-nav-dropdown--open');

      // Press Escape
      fireEvent.keyDown(document, { key: 'Escape' });

      // Reopen menu
      fireEvent.click(toggle);

      // Dropdown should be collapsed
      expect(container.querySelector('.mobile-nav-dropdown')).not.toHaveClass('mobile-nav-dropdown--open');
    });

    it('does not respond to Escape when menu is closed', () => {
      render(<MobileNav navigation={basicNavigation} />);

      // Menu is closed - use { hidden: true } because aria-hidden="true"
      expect(screen.getByRole('navigation', { hidden: true })).not.toHaveClass('mobile-nav-menu--open');

      // Press Escape (should have no effect)
      fireEvent.keyDown(document, { key: 'Escape' });

      // Still closed - use { hidden: true } because aria-hidden="true"
      expect(screen.getByRole('navigation', { hidden: true })).not.toHaveClass('mobile-nav-menu--open');
    });
  });

  describe('Edge Cases', () => {
    it('handles empty navigation array', () => {
      render(<MobileNav navigation={[]} />);

      // Use { hidden: true } because menu starts closed (aria-hidden="true")
      const menu = screen.getByRole('navigation', { hidden: true });
      expect(menu).toBeInTheDocument();

      const list = menu.querySelector('.mobile-nav-list');
      expect(list?.children.length).toBe(0);
    });

    it('handles items with empty children array', () => {
      const navWithEmptyChildren = [
        { label: 'Products', href: null, children: [] },
      ];

      render(<MobileNav navigation={navWithEmptyChildren} />);

      // Should not show dropdown toggle for empty children
      expect(screen.queryByRole('button', { name: /expand.*submenu/i })).not.toBeInTheDocument();
    });

    it('handles null href correctly', () => {
      const navWithNullHref = [
        { label: 'Coming Soon', href: null },
      ];

      render(<MobileNav navigation={navWithNullHref} />);

      const element = screen.getByText('Coming Soon');
      expect(element.tagName).toBe('SPAN');
      expect(element).toHaveClass('mobile-nav-link--no-href');
    });
  });
});
