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

// Mock react-router-dom's Outlet
vi.mock('react-router-dom', async () => {
  const actual = await vi.importActual('react-router-dom');
  return {
    ...actual,
    Outlet: () => <div data-testid="outlet-content">Page Content</div>,
  };
});

// Mock PlatformSidebar component
vi.mock('../../components/PlatformSidebar', () => ({
  default: ({ user, isCollapsed, toggleCollapse, onSignOut }: any) => (
    <div data-testid="platform-sidebar">
      <div data-testid="sidebar-user">{user.name}</div>
      <div data-testid="sidebar-role">{user.role}</div>
      <button onClick={toggleCollapse} data-testid="sidebar-collapse">
        {isCollapsed ? 'Expand' : 'Collapse'}
      </button>
      <button onClick={onSignOut} data-testid="sidebar-signout">
        Sign Out
      </button>
    </div>
  ),
}));

// Mock lucide-react icons
vi.mock('lucide-react', () => ({
  Moon: ({ size }: { size: number }) => <svg data-testid="moon-icon" width={size} height={size} />,
  Sun: ({ size }: { size: number }) => <svg data-testid="sun-icon" width={size} height={size} />,
  Bell: ({ size }: { size: number }) => <svg data-testid="bell-icon" width={size} height={size} />,
  Globe: ({ size }: { size: number }) => <svg data-testid="globe-icon" width={size} height={size} />,
  Menu: ({ size }: { size: number }) => <svg data-testid="menu-icon" width={size} height={size} />,
}));

// Mock useScrollToTop hook
const mockUseScrollToTop = vi.fn();
vi.mock('../../hooks/useScrollToTop', () => ({
  useScrollToTop: (ref: any) => mockUseScrollToTop(ref),
}));

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

  const managerUser: User = {
    id: '1',
    name: 'John Manager',
    email: 'manager@platform.com',
    role: 'platform_manager',
  };

  const superUser: User = {
    id: '2',
    name: 'Admin User',
    email: 'admin@platform.com',
    role: 'superuser',
  };

  const supportUser: User = {
    id: '3',
    name: 'Support User',
    email: 'support@platform.com',
    role: 'platform_support',
  };

  beforeEach(() => {
    vi.clearAllMocks();
  });

  const renderLayout = (user: User = managerUser, darkMode: boolean = false) => {
    return render(
      <MemoryRouter>
        <ManagerLayout
          user={user}
          darkMode={darkMode}
          toggleTheme={mockToggleTheme}
          onSignOut={mockOnSignOut}
        />
      </MemoryRouter>
    );
  };

  describe('Rendering Children Content', () => {
    it('renders the main layout structure', () => {
      renderLayout();

      // Check that main container exists
      const mainContainer = screen.getByRole('main');
      expect(mainContainer).toBeInTheDocument();
    });

    it('renders Outlet for nested routes', () => {
      renderLayout();

      // Check that Outlet content is rendered
      expect(screen.getByTestId('outlet-content')).toBeInTheDocument();
      expect(screen.getByText('Page Content')).toBeInTheDocument();
    });

    it('renders the header with correct elements', () => {
      renderLayout();

      // Check header exists with proper structure
      const header = screen.getByRole('banner');
      expect(header).toBeInTheDocument();
      expect(header).toHaveClass('bg-white', 'dark:bg-gray-800');
    });

    it('renders main content area with correct styling', () => {
      renderLayout();

      const mainContent = screen.getByRole('main');
      expect(mainContent).toHaveClass('flex-1', 'overflow-auto', 'bg-gray-50', 'dark:bg-gray-900');
    });

    it('applies dark mode classes correctly', () => {
      renderLayout(managerUser, true);

      const mainContent = screen.getByRole('main');
      expect(mainContent).toHaveClass('dark:bg-gray-900');
    });

    it('applies light mode classes correctly', () => {
      renderLayout(managerUser, false);

      const mainContent = screen.getByRole('main');
      expect(mainContent).toHaveClass('bg-gray-50');
    });
  });

  describe('Manager-Specific Navigation', () => {
    it('renders PlatformSidebar with correct props', () => {
      renderLayout();

      const sidebars = screen.getAllByTestId('platform-sidebar');
      expect(sidebars.length).toBe(2); // Mobile and desktop

      // Check user data is passed correctly (using first sidebar)
      const userElements = screen.getAllByTestId('sidebar-user');
      expect(userElements[0]).toHaveTextContent('John Manager');
      const roleElements = screen.getAllByTestId('sidebar-role');
      expect(roleElements[0]).toHaveTextContent('platform_manager');
    });

    it('displays Management Console in breadcrumb', () => {
      renderLayout();

      expect(screen.getByText('Management Console')).toBeInTheDocument();
    });

    it('displays domain information in breadcrumb', () => {
      renderLayout();

      expect(screen.getByText('smoothschedule.com')).toBeInTheDocument();
    });

    it('renders globe icon in breadcrumb', () => {
      renderLayout();

      const globeIcon = screen.getByTestId('globe-icon');
      expect(globeIcon).toBeInTheDocument();
      expect(globeIcon).toHaveAttribute('width', '16');
      expect(globeIcon).toHaveAttribute('height', '16');
    });

    it('hides breadcrumb on mobile', () => {
      renderLayout();

      const breadcrumb = screen.getByText('Management Console').closest('div');
      expect(breadcrumb).toHaveClass('hidden', 'md:flex');
    });

    it('handles sidebar collapse state', () => {
      renderLayout();

      const collapseButton = screen.getAllByTestId('sidebar-collapse')[0];
      expect(collapseButton).toHaveTextContent('Collapse');

      // Click to collapse
      fireEvent.click(collapseButton);

      // Note: The sidebar is mocked, so we just verify the button exists
      expect(collapseButton).toBeInTheDocument();
    });

    it('renders desktop sidebar by default', () => {
      renderLayout();

      // There are 2 sidebars: mobile (index 0) and desktop (index 1)
      const sidebars = screen.getAllByTestId('platform-sidebar');
      expect(sidebars.length).toBe(2);
      // Desktop sidebar exists and is in a hidden md:flex container
      const desktopSidebar = sidebars[1];
      expect(desktopSidebar).toBeInTheDocument();
    });

    it('mobile sidebar is hidden by default', () => {
      renderLayout();

      // Mobile menu should be off-screen initially
      const mobileSidebar = screen.getAllByTestId('platform-sidebar')[0];
      const mobileContainer = mobileSidebar.closest('.fixed');
      expect(mobileContainer).toHaveClass('-translate-x-full');
    });

    it('mobile menu button opens mobile sidebar', () => {
      renderLayout();

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

      // After clicking, mobile sidebar should be visible
      const mobileSidebar = screen.getAllByTestId('platform-sidebar')[0];
      const mobileContainer = mobileSidebar.closest('.fixed');
      expect(mobileContainer).toHaveClass('translate-x-0');
    });

    it('clicking backdrop closes mobile menu', () => {
      renderLayout();

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

      // Find and click backdrop
      const backdrop = document.querySelector('.bg-black\\/50');
      expect(backdrop).toBeInTheDocument();

      fireEvent.click(backdrop!);

      // Mobile sidebar should be hidden again
      const mobileSidebar = screen.getAllByTestId('platform-sidebar')[0];
      const mobileContainer = mobileSidebar.closest('.fixed');
      expect(mobileContainer).toHaveClass('-translate-x-full');
    });
  });

  describe('Access Controls', () => {
    it('allows platform_manager role to access layout', () => {
      renderLayout(managerUser);

      expect(screen.getAllByTestId('sidebar-role')[0]).toHaveTextContent('platform_manager');
      expect(screen.getByTestId('outlet-content')).toBeInTheDocument();
    });

    it('allows superuser role to access layout', () => {
      renderLayout(superUser);

      expect(screen.getAllByTestId('sidebar-role')[0]).toHaveTextContent('superuser');
      expect(screen.getByTestId('outlet-content')).toBeInTheDocument();
    });

    it('allows platform_support role to access layout', () => {
      renderLayout(supportUser);

      expect(screen.getAllByTestId('sidebar-role')[0]).toHaveTextContent('platform_support');
      expect(screen.getByTestId('outlet-content')).toBeInTheDocument();
    });

    it('renders sign out button for authenticated users', () => {
      renderLayout();

      const signOutButton = screen.getAllByTestId('sidebar-signout')[0];
      expect(signOutButton).toBeInTheDocument();
    });

    it('calls onSignOut when sign out button is clicked', () => {
      renderLayout();

      const signOutButton = screen.getAllByTestId('sidebar-signout')[0];
      fireEvent.click(signOutButton);

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

    it('renders layout for different user emails', () => {
      const customUser: User = {
        ...managerUser,
        email: 'custom@example.com',
      };

      renderLayout(customUser);
      expect(screen.getByTestId('outlet-content')).toBeInTheDocument();
    });

    it('renders layout for users with numeric IDs', () => {
      const numericIdUser: User = {
        ...managerUser,
        id: 123,
      };

      renderLayout(numericIdUser);
      expect(screen.getByTestId('outlet-content')).toBeInTheDocument();
    });
  });

  describe('Theme Toggle', () => {
    it('renders theme toggle button', () => {
      renderLayout();

      // Find the button containing the moon icon (theme toggle)
      const moonIcon = screen.getByTestId('moon-icon');
      const themeButton = moonIcon.closest('button');
      expect(themeButton).toBeInTheDocument();
    });

    it('displays Moon icon in light mode', () => {
      renderLayout(managerUser, false);

      const moonIcon = screen.getByTestId('moon-icon');
      expect(moonIcon).toBeInTheDocument();
      expect(screen.queryByTestId('sun-icon')).not.toBeInTheDocument();
    });

    it('displays Sun icon in dark mode', () => {
      renderLayout(managerUser, true);

      const sunIcon = screen.getByTestId('sun-icon');
      expect(sunIcon).toBeInTheDocument();
      expect(screen.queryByTestId('moon-icon')).not.toBeInTheDocument();
    });

    it('calls toggleTheme when theme button is clicked', () => {
      renderLayout();

      // Find the button containing the moon icon
      const moonIcon = screen.getByTestId('moon-icon');
      const themeButton = moonIcon.closest('button');

      expect(themeButton).toBeInTheDocument();
      fireEvent.click(themeButton!);

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

    it('theme button has proper styling', () => {
      renderLayout();

      const moonIcon = screen.getByTestId('moon-icon');
      const themeButton = moonIcon.closest('button');

      expect(themeButton).toHaveClass('text-gray-400', 'hover:text-gray-600');
    });

    it('icon size is correct', () => {
      renderLayout();

      const moonIcon = screen.getByTestId('moon-icon');
      expect(moonIcon).toHaveAttribute('width', '20');
      expect(moonIcon).toHaveAttribute('height', '20');
    });
  });

  describe('Notification Bell', () => {
    it('renders notification bell icon', () => {
      renderLayout();

      const bellIcon = screen.getByTestId('bell-icon');
      expect(bellIcon).toBeInTheDocument();
    });

    it('bell icon has correct size', () => {
      renderLayout();

      const bellIcon = screen.getByTestId('bell-icon');
      expect(bellIcon).toHaveAttribute('width', '20');
      expect(bellIcon).toHaveAttribute('height', '20');
    });

    it('bell button has proper styling', () => {
      renderLayout();

      const bellIcon = screen.getByTestId('bell-icon');
      const bellButton = bellIcon.closest('button');

      expect(bellButton).toHaveClass('text-gray-400', 'hover:text-gray-600');
    });

    it('bell button is clickable', () => {
      renderLayout();

      const bellIcon = screen.getByTestId('bell-icon');
      const bellButton = bellIcon.closest('button');

      expect(bellButton).toBeInTheDocument();
      fireEvent.click(bellButton!);

      // Button should be clickable (no error thrown)
    });
  });

  describe('Mobile Menu', () => {
    it('renders mobile menu button with Menu icon', () => {
      renderLayout();

      const menuIcon = screen.getByTestId('menu-icon');
      expect(menuIcon).toBeInTheDocument();
    });

    it('mobile menu button has correct aria-label', () => {
      renderLayout();

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

    it('mobile menu button is only visible on mobile', () => {
      renderLayout();

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

    it('menu icon has correct size', () => {
      renderLayout();

      const menuIcon = screen.getByTestId('menu-icon');
      expect(menuIcon).toHaveAttribute('width', '24');
      expect(menuIcon).toHaveAttribute('height', '24');
    });

    it('toggles mobile menu visibility', () => {
      renderLayout();

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

      // Initially closed
      let mobileSidebar = screen.getAllByTestId('platform-sidebar')[0];
      let mobileContainer = mobileSidebar.closest('.fixed');
      expect(mobileContainer).toHaveClass('-translate-x-full');

      // Open menu
      fireEvent.click(menuButton);

      mobileSidebar = screen.getAllByTestId('platform-sidebar')[0];
      mobileContainer = mobileSidebar.closest('.fixed');
      expect(mobileContainer).toHaveClass('translate-x-0');
    });

    it('mobile backdrop appears when menu is open', () => {
      renderLayout();

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

      // No backdrop initially
      expect(document.querySelector('.bg-black\\/50')).not.toBeInTheDocument();

      // Open menu
      fireEvent.click(menuButton);

      // Backdrop should appear
      expect(document.querySelector('.bg-black\\/50')).toBeInTheDocument();
    });

    it('mobile backdrop has correct z-index', () => {
      renderLayout();

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

      const backdrop = document.querySelector('.bg-black\\/50');
      expect(backdrop).toHaveClass('z-30');
    });

    it('mobile sidebar has higher z-index than backdrop', () => {
      renderLayout();

      const mobileSidebar = screen.getAllByTestId('platform-sidebar')[0];
      const mobileContainer = mobileSidebar.closest('.fixed');

      expect(mobileContainer).toHaveClass('z-40');
    });
  });

  describe('Layout Responsiveness', () => {
    it('applies responsive padding to header', () => {
      renderLayout();

      const header = screen.getByRole('banner');
      expect(header).toHaveClass('px-4', 'sm:px-8');
    });

    it('main content has proper spacing', () => {
      renderLayout();

      const mainContent = screen.getByRole('main');
      expect(mainContent).toHaveClass('p-8');
    });

    it('desktop sidebar is hidden on mobile', () => {
      renderLayout();

      const desktopSidebar = screen.getAllByTestId('platform-sidebar')[1].closest('.md\\:flex');
      expect(desktopSidebar).toHaveClass('hidden');
    });

    it('layout uses flexbox for proper structure', () => {
      const { container } = renderLayout();

      const flexContainer = container.querySelector('.flex.h-full');
      expect(flexContainer).toBeInTheDocument();
    });

    it('main content area is scrollable', () => {
      renderLayout();

      const mainContent = screen.getByRole('main');
      expect(mainContent).toHaveClass('overflow-auto');
    });

    it('layout has proper height constraints', () => {
      const { container } = renderLayout();

      const flexContainer = container.querySelector('.flex.h-full');
      expect(flexContainer).toBeInTheDocument();
    });
  });

  describe('Styling and Visual State', () => {
    it('applies background color classes', () => {
      const { container } = renderLayout();

      const flexContainer = container.querySelector('.flex.h-full');
      expect(flexContainer).toHaveClass('bg-gray-100');
    });

    it('header has border', () => {
      renderLayout();

      const header = screen.getByRole('banner');
      expect(header).toHaveClass('border-b', 'border-gray-200', 'dark:border-gray-700');
    });

    it('header has fixed height', () => {
      renderLayout();

      const header = screen.getByRole('banner');
      expect(header).toHaveClass('h-16');
    });

    it('applies transition classes for animations', () => {
      renderLayout();

      const mobileSidebar = screen.getAllByTestId('platform-sidebar')[0];
      const mobileContainer = mobileSidebar.closest('.fixed');

      expect(mobileContainer).toHaveClass('transition-transform', 'duration-300', 'ease-in-out');
    });

    it('buttons have hover states', () => {
      renderLayout();

      const moonIcon = screen.getByTestId('moon-icon');
      const themeButton = moonIcon.closest('button');

      expect(themeButton).toHaveClass('hover:text-gray-600');
    });

    it('menu button has negative margin for alignment', () => {
      renderLayout();

      const menuButton = screen.getByLabelText('Open sidebar');
      expect(menuButton).toHaveClass('-ml-2');
    });
  });

  describe('Scroll Behavior', () => {
    it('calls useScrollToTop hook on mount', () => {
      mockUseScrollToTop.mockClear();
      renderLayout();

      expect(mockUseScrollToTop).toHaveBeenCalled();
    });

    it('passes main content ref to useScrollToTop', () => {
      mockUseScrollToTop.mockClear();
      renderLayout();

      // Verify hook was called with a ref object
      expect(mockUseScrollToTop).toHaveBeenCalledWith(
        expect.objectContaining({ current: expect.anything() })
      );
    });
  });

  describe('Edge Cases', () => {
    it('handles user without optional fields', () => {
      const minimalUser: User = {
        id: '1',
        name: 'Test User',
        email: 'test@example.com',
        role: 'platform_manager',
      };

      renderLayout(minimalUser);
      expect(screen.getByTestId('outlet-content')).toBeInTheDocument();
    });

    it('renders with extremely long user names', () => {
      const longNameUser: User = {
        ...managerUser,
        name: 'This Is An Extremely Long User Name That Should Still Render Properly Without Breaking The Layout',
      };

      renderLayout(longNameUser);
      expect(screen.getAllByTestId('sidebar-user')[0]).toBeInTheDocument();
    });

    it('handles rapid theme toggle clicks', () => {
      renderLayout();

      const moonIcon = screen.getByTestId('moon-icon');
      const themeButton = moonIcon.closest('button');

      fireEvent.click(themeButton!);
      fireEvent.click(themeButton!);
      fireEvent.click(themeButton!);

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

    it('handles rapid mobile menu toggles', () => {
      renderLayout();

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

      fireEvent.click(menuButton);
      fireEvent.click(menuButton);
      fireEvent.click(menuButton);

      // Should not crash
      expect(menuButton).toBeInTheDocument();
    });

    it('maintains state during re-renders', () => {
      const { rerender } = renderLayout();

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

      // Re-render with same props
      rerender(
        <MemoryRouter>
          <ManagerLayout
            user={managerUser}
            darkMode={false}
            toggleTheme={mockToggleTheme}
            onSignOut={mockOnSignOut}
          />
        </MemoryRouter>
      );

      // State should persist
      const mobileSidebar = screen.getAllByTestId('platform-sidebar')[0];
      const mobileContainer = mobileSidebar.closest('.fixed');
      expect(mobileContainer).toHaveClass('translate-x-0');
    });
  });

  describe('Accessibility', () => {
    it('header has correct semantic role', () => {
      renderLayout();

      const header = screen.getByRole('banner');
      expect(header.tagName).toBe('HEADER');
    });

    it('main has correct semantic role', () => {
      renderLayout();

      const main = screen.getByRole('main');
      expect(main.tagName).toBe('MAIN');
    });

    it('buttons have proper interactive elements', () => {
      renderLayout();

      const menuButton = screen.getByLabelText('Open sidebar');
      expect(menuButton.tagName).toBe('BUTTON');
    });

    it('mobile menu button has aria-label', () => {
      renderLayout();

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

    it('all interactive elements are keyboard accessible', () => {
      renderLayout();

      const menuButton = screen.getByLabelText('Open sidebar');
      const moonIcon = screen.getByTestId('moon-icon');
      const themeButton = moonIcon.closest('button');
      const bellIcon = screen.getByTestId('bell-icon');
      const bellButton = bellIcon.closest('button');

      expect(menuButton.tagName).toBe('BUTTON');
      expect(themeButton?.tagName).toBe('BUTTON');
      expect(bellButton?.tagName).toBe('BUTTON');
    });
  });

  describe('Component Integration', () => {
    it('renders without crashing', () => {
      expect(() => renderLayout()).not.toThrow();
    });

    it('renders all major sections together', () => {
      renderLayout();

      expect(screen.getAllByTestId('platform-sidebar').length).toBeGreaterThan(0);
      expect(screen.getByRole('banner')).toBeInTheDocument();
      expect(screen.getByRole('main')).toBeInTheDocument();
      expect(screen.getByTestId('outlet-content')).toBeInTheDocument();
    });

    it('passes correct props to PlatformSidebar', () => {
      renderLayout();

      expect(screen.getAllByTestId('sidebar-user')[0]).toHaveTextContent('John Manager');
      expect(screen.getAllByTestId('sidebar-signout')[0]).toBeInTheDocument();
    });

    it('integrates with React Router Outlet', () => {
      renderLayout();

      const outlet = screen.getByTestId('outlet-content');
      expect(outlet).toHaveTextContent('Page Content');
    });

    it('handles multiple simultaneous interactions', () => {
      renderLayout();

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

      // Toggle theme
      const moonIcon = screen.getByTestId('moon-icon');
      const themeButton = moonIcon.closest('button');
      fireEvent.click(themeButton!);

      // Click bell
      const bellIcon = screen.getByTestId('bell-icon');
      const bellButton = bellIcon.closest('button');
      fireEvent.click(bellButton!);

      expect(mockToggleTheme).toHaveBeenCalledTimes(1);
      const mobileSidebar = screen.getAllByTestId('platform-sidebar')[0];
      const mobileContainer = mobileSidebar.closest('.fixed');
      expect(mobileContainer).toHaveClass('translate-x-0');
    });
  });
});
