/**
 * Unit tests for Navbar component
 *
 * Tests cover:
 * - Logo and brand rendering
 * - Navigation links presence
 * - Login/signup buttons
 * - Mobile menu toggle functionality
 * - Scroll behavior (background change on scroll)
 * - Theme toggle functionality
 * - User authentication states
 * - Dashboard URL generation based on user role
 * - Route change effects on mobile menu
 * - Accessibility attributes
 */

import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { BrowserRouter, MemoryRouter } from 'react-router-dom';
import React from 'react';
import Navbar from '../Navbar';
import { User } from '../../../api/auth';

// Mock react-i18next
vi.mock('react-i18next', () => ({
  useTranslation: () => ({
    t: (key: string) => {
      const translations: Record<string, string> = {
        'marketing.nav.features': 'Features',
        'marketing.nav.pricing': 'Pricing',
        'marketing.nav.about': 'About',
        'marketing.nav.contact': 'Contact',
        'marketing.nav.login': 'Login',
        'marketing.nav.getStarted': 'Get Started',
        'marketing.nav.brandName': 'Smooth Schedule',
        'marketing.nav.switchToLightMode': 'Switch to light mode',
        'marketing.nav.switchToDarkMode': 'Switch to dark mode',
        'marketing.nav.toggleMenu': 'Toggle menu',
      };
      return translations[key] || key;
    },
  }),
}));

// Mock SmoothScheduleLogo
vi.mock('../../SmoothScheduleLogo', () => ({
  default: ({ className }: { className?: string }) => (
    <div data-testid="smooth-schedule-logo" className={className}>Logo</div>
  ),
}));

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

// Mock domain utilities
vi.mock('../../../utils/domain', () => ({
  buildSubdomainUrl: (subdomain: string | null, path: string = '/') => {
    if (subdomain) {
      return `http://${subdomain}.lvh.me:5173${path}`;
    }
    return `http://lvh.me:5173${path}`;
  },
}));

// Test wrapper with Router
const createWrapper = (initialRoute: string = '/') => {
  return ({ children }: { children: React.ReactNode }) => (
    <MemoryRouter initialEntries={[initialRoute]}>{children}</MemoryRouter>
  );
};

describe('Navbar', () => {
  const mockToggleTheme = vi.fn();

  beforeEach(() => {
    vi.clearAllMocks();
    // Reset window.scrollY before each test
    Object.defineProperty(window, 'scrollY', {
      writable: true,
      configurable: true,
      value: 0,
    });
  });

  afterEach(() => {
    vi.restoreAllMocks();
  });

  describe('Logo and Brand Rendering', () => {
    it('should render the logo', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const logo = screen.getByTestId('smooth-schedule-logo');
      expect(logo).toBeInTheDocument();
    });

    it('should render the brand name', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const brandName = screen.getByText('Smooth Schedule');
      expect(brandName).toBeInTheDocument();
    });

    it('should have logo link pointing to home', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const logoLink = screen.getByRole('link', { name: /smooth schedule/i });
      expect(logoLink).toHaveAttribute('href', '/');
    });

    it('should apply correct classes to logo link', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const logoLink = screen.getByRole('link', { name: /smooth schedule/i });
      expect(logoLink).toHaveClass('flex', 'items-center', 'gap-2', 'group');
    });
  });

  describe('Navigation Links', () => {
    it('should render all navigation links on desktop', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      expect(screen.getAllByText('Features')[0]).toBeInTheDocument();
      expect(screen.getAllByText('Pricing')[0]).toBeInTheDocument();
      expect(screen.getAllByText('About')[0]).toBeInTheDocument();
      expect(screen.getAllByText('Contact')[0]).toBeInTheDocument();
    });

    it('should have correct href attributes for navigation links', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const featuresLinks = screen.getAllByRole('link', { name: 'Features' });
      expect(featuresLinks[0]).toHaveAttribute('href', '/features');

      const pricingLinks = screen.getAllByRole('link', { name: 'Pricing' });
      expect(pricingLinks[0]).toHaveAttribute('href', '/pricing');

      const aboutLinks = screen.getAllByRole('link', { name: 'About' });
      expect(aboutLinks[0]).toHaveAttribute('href', '/about');

      const contactLinks = screen.getAllByRole('link', { name: 'Contact' });
      expect(contactLinks[0]).toHaveAttribute('href', '/contact');
    });

    it('should highlight active navigation link', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper('/features'),
      });

      const featuresLinks = screen.getAllByRole('link', { name: 'Features' });
      const activeLink = featuresLinks[0];

      expect(activeLink).toHaveClass('text-brand-600');
    });

    it('should not highlight inactive navigation links', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper('/features'),
      });

      const pricingLinks = screen.getAllByRole('link', { name: 'Pricing' });
      const inactiveLink = pricingLinks[0];

      expect(inactiveLink).toHaveClass('text-gray-600');
      expect(inactiveLink).not.toHaveClass('text-brand-600');
    });
  });

  describe('Login and Signup Buttons', () => {
    it('should render login button when no user is provided', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const loginButtons = screen.getAllByText('Login');
      expect(loginButtons.length).toBeGreaterThan(0);
    });

    it('should render login link with correct href when no user', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const loginLinks = screen.getAllByRole('link', { name: 'Login' });
      expect(loginLinks[0]).toHaveAttribute('href', '/login');
    });

    it('should render signup button', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const signupButtons = screen.getAllByText('Get Started');
      expect(signupButtons.length).toBeGreaterThan(0);
    });

    it('should render signup link with correct href', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const signupLinks = screen.getAllByRole('link', { name: 'Get Started' });
      expect(signupLinks[0]).toHaveAttribute('href', '/signup');
    });

    it('should render dashboard link when user is authenticated', () => {
      const mockUser: User = {
        id: 1,
        email: 'test@example.com',
        username: 'testuser',
        first_name: 'Test',
        last_name: 'User',
        role: 'owner',
        business_subdomain: 'testbusiness',
        is_active: true,
      };

      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} user={mockUser} />, {
        wrapper: createWrapper(),
      });

      const loginLinks = screen.getAllByText('Login');
      // Should still show "Login" text but as anchor tag to dashboard
      expect(loginLinks.length).toBeGreaterThan(0);
    });

    it('should generate correct dashboard URL for platform users', () => {
      const mockUser: User = {
        id: 1,
        email: 'admin@example.com',
        username: 'admin',
        first_name: 'Admin',
        last_name: 'User',
        role: 'superuser',
        business_subdomain: null,
        is_active: true,
      };

      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} user={mockUser} />, {
        wrapper: createWrapper(),
      });

      const loginLinks = screen.getAllByText('Login');
      const dashboardLink = loginLinks[0].closest('a');
      expect(dashboardLink).toHaveAttribute('href', 'http://platform.lvh.me:5173/');
    });

    it('should generate correct dashboard URL for business users', () => {
      const mockUser: User = {
        id: 1,
        email: 'owner@example.com',
        username: 'owner',
        first_name: 'Owner',
        last_name: 'User',
        role: 'owner',
        business_subdomain: 'mybusiness',
        is_active: true,
      };

      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} user={mockUser} />, {
        wrapper: createWrapper(),
      });

      const loginLinks = screen.getAllByText('Login');
      const dashboardLink = loginLinks[0].closest('a');
      expect(dashboardLink).toHaveAttribute('href', 'http://mybusiness.lvh.me:5173/');
    });
  });

  describe('Theme Toggle', () => {
    it('should render theme toggle button', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const themeButton = screen.getByLabelText('Switch to dark mode');
      expect(themeButton).toBeInTheDocument();
    });

    it('should call toggleTheme when theme button is clicked', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const themeButton = screen.getByLabelText('Switch to dark mode');
      fireEvent.click(themeButton);

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

    it('should show moon icon in light mode', () => {
      const { container } = render(
        <Navbar darkMode={false} toggleTheme={mockToggleTheme} />,
        { wrapper: createWrapper() }
      );

      const themeButton = screen.getByLabelText('Switch to dark mode');
      const svg = themeButton.querySelector('svg');
      expect(svg).toBeInTheDocument();
    });

    it('should show sun icon in dark mode', () => {
      const { container } = render(
        <Navbar darkMode={true} toggleTheme={mockToggleTheme} />,
        { wrapper: createWrapper() }
      );

      const themeButton = screen.getByLabelText('Switch to light mode');
      const svg = themeButton.querySelector('svg');
      expect(svg).toBeInTheDocument();
    });

    it('should have correct aria-label in light mode', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const themeButton = screen.getByLabelText('Switch to dark mode');
      expect(themeButton).toHaveAttribute('aria-label', 'Switch to dark mode');
    });

    it('should have correct aria-label in dark mode', () => {
      render(<Navbar darkMode={true} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const themeButton = screen.getByLabelText('Switch to light mode');
      expect(themeButton).toHaveAttribute('aria-label', 'Switch to light mode');
    });
  });

  describe('Mobile Menu Toggle', () => {
    it('should render mobile menu button', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const menuButton = screen.getByLabelText('Toggle menu');
      expect(menuButton).toBeInTheDocument();
    });

    it('should show mobile menu when menu button is clicked', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const menuButton = screen.getByLabelText('Toggle menu');
      fireEvent.click(menuButton);

      // Mobile menu should be visible (max-h-96 instead of max-h-0)
      const mobileMenuContainer = menuButton.closest('nav')?.querySelector('.lg\\:hidden.overflow-hidden');
      expect(mobileMenuContainer).toBeInTheDocument();
    });

    it('should toggle mobile menu on multiple clicks', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const menuButton = screen.getByLabelText('Toggle menu');

      // First click - open
      fireEvent.click(menuButton);
      let mobileMenuContainer = menuButton.closest('nav')?.querySelector('.lg\\:hidden.overflow-hidden');
      expect(mobileMenuContainer).toHaveClass('max-h-96');

      // Second click - close
      fireEvent.click(menuButton);
      mobileMenuContainer = menuButton.closest('nav')?.querySelector('.lg\\:hidden.overflow-hidden');
      expect(mobileMenuContainer).toHaveClass('max-h-0');
    });

    it('should show Menu icon when menu is closed', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const menuButton = screen.getByLabelText('Toggle menu');
      const svg = menuButton.querySelector('svg');
      expect(svg).toBeInTheDocument();
    });

    it('should show X icon when menu is open', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const menuButton = screen.getByLabelText('Toggle menu');
      fireEvent.click(menuButton);

      const svg = menuButton.querySelector('svg');
      expect(svg).toBeInTheDocument();
    });

    it('should render all navigation links in mobile menu', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const menuButton = screen.getByLabelText('Toggle menu');
      fireEvent.click(menuButton);

      // Each link appears twice (desktop + mobile)
      expect(screen.getAllByText('Features')).toHaveLength(2);
      expect(screen.getAllByText('Pricing')).toHaveLength(2);
      expect(screen.getAllByText('About')).toHaveLength(2);
      expect(screen.getAllByText('Contact')).toHaveLength(2);
    });

    it('should render language selector in mobile menu', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const menuButton = screen.getByLabelText('Toggle menu');
      fireEvent.click(menuButton);

      const languageSelectors = screen.getAllByTestId('language-selector');
      // Should appear twice (desktop + mobile)
      expect(languageSelectors).toHaveLength(2);
    });

    it('should close mobile menu on route change', () => {
      // Test that clicking a navigation link closes the mobile menu
      // In production, clicking a link triggers a route change which closes the menu via useEffect
      // In tests with MemoryRouter, the route change happens and the useEffect fires
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper('/'),
      });

      const menuButton = screen.getByLabelText('Toggle menu');
      fireEvent.click(menuButton);

      // Verify menu is open
      let mobileMenuContainer = menuButton.closest('nav')?.querySelector('.lg\\:hidden.overflow-hidden');
      expect(mobileMenuContainer).toHaveClass('max-h-96');

      // Click a navigation link - this triggers navigation to /features
      // The useEffect with location.pathname dependency should close the menu
      const featuresLink = screen.getAllByRole('link', { name: 'Features' })[1]; // Mobile menu link
      fireEvent.click(featuresLink);

      // After navigation, menu should be closed
      mobileMenuContainer = menuButton.closest('nav')?.querySelector('.lg\\:hidden.overflow-hidden');
      expect(mobileMenuContainer).toHaveClass('max-h-0');
    });
  });

  describe('Scroll Behavior', () => {
    it('should have transparent background when not scrolled', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const nav = screen.getByRole('navigation');
      expect(nav).toHaveClass('bg-transparent');
    });

    it('should change background on scroll', async () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const nav = screen.getByRole('navigation');

      // Simulate scroll
      Object.defineProperty(window, 'scrollY', { writable: true, value: 50 });
      fireEvent.scroll(window);

      await waitFor(() => {
        expect(nav).toHaveClass('bg-white/80');
        expect(nav).toHaveClass('backdrop-blur-lg');
        expect(nav).toHaveClass('shadow-sm');
      });
    });

    it('should remove background when scrolled back to top', async () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const nav = screen.getByRole('navigation');

      // Scroll down
      Object.defineProperty(window, 'scrollY', { writable: true, value: 50 });
      fireEvent.scroll(window);

      await waitFor(() => {
        expect(nav).toHaveClass('bg-white/80');
      });

      // Scroll back to top
      Object.defineProperty(window, 'scrollY', { writable: true, value: 0 });
      fireEvent.scroll(window);

      await waitFor(() => {
        expect(nav).toHaveClass('bg-transparent');
      });
    });

    it('should clean up scroll event listener on unmount', () => {
      const removeEventListenerSpy = vi.spyOn(window, 'removeEventListener');

      const { unmount } = render(
        <Navbar darkMode={false} toggleTheme={mockToggleTheme} />,
        { wrapper: createWrapper() }
      );

      unmount();

      expect(removeEventListenerSpy).toHaveBeenCalledWith('scroll', expect.any(Function));
    });
  });

  describe('Accessibility', () => {
    it('should have navigation role', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const nav = screen.getByRole('navigation');
      expect(nav).toBeInTheDocument();
    });

    it('should have aria-label on theme toggle button', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const themeButton = screen.getByLabelText('Switch to dark mode');
      expect(themeButton).toHaveAttribute('aria-label');
    });

    it('should have aria-label on mobile menu toggle button', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const menuButton = screen.getByLabelText('Toggle menu');
      expect(menuButton).toHaveAttribute('aria-label');
    });

    it('should have semantic link elements for navigation', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const links = screen.getAllByRole('link');
      expect(links.length).toBeGreaterThan(0);
    });
  });

  describe('Language Selector', () => {
    it('should render language selector on desktop', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const languageSelectors = screen.getAllByTestId('language-selector');
      expect(languageSelectors.length).toBeGreaterThan(0);
    });

    it('should render language selector in mobile menu', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const menuButton = screen.getByLabelText('Toggle menu');
      fireEvent.click(menuButton);

      const languageSelectors = screen.getAllByTestId('language-selector');
      expect(languageSelectors).toHaveLength(2); // Desktop + Mobile
    });
  });

  describe('Styling and Layout', () => {
    it('should have fixed positioning', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const nav = screen.getByRole('navigation');
      expect(nav).toHaveClass('fixed', 'top-0', 'left-0', 'right-0', 'z-50');
    });

    it('should have transition classes for smooth animations', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const nav = screen.getByRole('navigation');
      expect(nav).toHaveClass('transition-all', 'duration-300');
    });

    it('should have max-width container', () => {
      const { container } = render(
        <Navbar darkMode={false} toggleTheme={mockToggleTheme} />,
        { wrapper: createWrapper() }
      );

      const maxWidthContainer = container.querySelector('.max-w-7xl');
      expect(maxWidthContainer).toBeInTheDocument();
    });

    it('should hide desktop nav on mobile screens', () => {
      const { container } = render(
        <Navbar darkMode={false} toggleTheme={mockToggleTheme} />,
        { wrapper: createWrapper() }
      );

      const desktopNav = container.querySelector('.hidden.lg\\:flex');
      expect(desktopNav).toBeInTheDocument();
    });

    it('should hide mobile menu button on large screens', () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const menuButton = screen.getByLabelText('Toggle menu');
      expect(menuButton).toHaveClass('lg:hidden');
    });
  });

  describe('Dark Mode Support', () => {
    it('should apply dark mode classes when darkMode is true and scrolled', async () => {
      render(<Navbar darkMode={true} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const nav = screen.getByRole('navigation');

      // Simulate scroll to trigger background change
      Object.defineProperty(window, 'scrollY', { writable: true, value: 50 });
      fireEvent.scroll(window);

      await waitFor(() => {
        // The component uses dark: prefix for dark mode classes
        expect(nav.className).toContain('dark:bg-gray-900/80');
      });
    });

    it('should apply light mode classes when darkMode is false and scrolled', async () => {
      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} />, {
        wrapper: createWrapper(),
      });

      const nav = screen.getByRole('navigation');

      // Simulate scroll to trigger background change
      Object.defineProperty(window, 'scrollY', { writable: true, value: 50 });
      fireEvent.scroll(window);

      await waitFor(() => {
        expect(nav.className).toContain('bg-white/80');
      });
    });
  });

  describe('User Role Based Dashboard Links', () => {
    it('should link to platform dashboard for platform_manager', () => {
      const mockUser: User = {
        id: 1,
        email: 'manager@example.com',
        username: 'manager',
        first_name: 'Manager',
        last_name: 'User',
        role: 'platform_manager',
        business_subdomain: null,
        is_active: true,
      };

      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} user={mockUser} />, {
        wrapper: createWrapper(),
      });

      const loginLinks = screen.getAllByText('Login');
      const dashboardLink = loginLinks[0].closest('a');
      expect(dashboardLink).toHaveAttribute('href', 'http://platform.lvh.me:5173/');
    });

    it('should link to platform dashboard for platform_support', () => {
      const mockUser: User = {
        id: 1,
        email: 'support@example.com',
        username: 'support',
        first_name: 'Support',
        last_name: 'User',
        role: 'platform_support',
        business_subdomain: null,
        is_active: true,
      };

      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} user={mockUser} />, {
        wrapper: createWrapper(),
      });

      const loginLinks = screen.getAllByText('Login');
      const dashboardLink = loginLinks[0].closest('a');
      expect(dashboardLink).toHaveAttribute('href', 'http://platform.lvh.me:5173/');
    });

    it('should link to login when user has no subdomain', () => {
      const mockUser: User = {
        id: 1,
        email: 'user@example.com',
        username: 'user',
        first_name: 'Regular',
        last_name: 'User',
        role: 'customer',
        business_subdomain: null,
        is_active: true,
      };

      render(<Navbar darkMode={false} toggleTheme={mockToggleTheme} user={mockUser} />, {
        wrapper: createWrapper(),
      });

      const loginLinks = screen.getAllByText('Login');
      const dashboardLink = loginLinks[0].closest('a');
      // Falls back to /login when no business_subdomain
      expect(dashboardLink).toHaveAttribute('href', '/login');
    });
  });
});
