import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent, within } from '@testing-library/react';
import React from 'react';
import { MemoryRouter, Route, Routes } from 'react-router-dom';
import SettingsLayout from '../SettingsLayout';
import { Business, User, PlanPermissions } from '../../types';

// Mock react-i18next
vi.mock('react-i18next', () => ({
  useTranslation: () => ({
    t: (key: string, fallback?: string) => {
      const translations: Record<string, string> = {
        'settings.backToApp': 'Back to App',
        'settings.title': 'Settings',
        'settings.sections.business': 'Business',
        'settings.sections.branding': 'Branding',
        'settings.sections.integrations': 'Integrations',
        'settings.sections.access': 'Access',
        'settings.sections.communication': 'Communication',
        'settings.sections.billing': 'Billing',
        'settings.general.title': 'General',
        'settings.general.description': 'Name, timezone, contact',
        'settings.resourceTypes.title': 'Resource Types',
        'settings.resourceTypes.description': 'Staff, rooms, equipment',
        'settings.booking.title': 'Booking',
        'settings.booking.description': 'Booking URL, redirects',
        'settings.appearance.title': 'Appearance',
        'settings.appearance.description': 'Logo, colors, theme',
        'settings.emailTemplates.title': 'Email Templates',
        'settings.emailTemplates.description': 'Customize email designs',
        'settings.customDomains.title': 'Custom Domains',
        'settings.customDomains.description': 'Use your own domain',
        'settings.api.title': 'API & Webhooks',
        'settings.api.description': 'API tokens, webhooks',
        'settings.authentication.title': 'Authentication',
        'settings.authentication.description': 'OAuth, social login',
        'settings.email.title': 'Email Setup',
        'settings.email.description': 'Email addresses for tickets',
        'settings.smsCalling.title': 'SMS & Calling',
        'settings.smsCalling.description': 'Credits, phone numbers',
        'settings.billing.title': 'Plan & Billing',
        'settings.billing.description': 'Subscription, invoices',
        'settings.quota.title': 'Quota Management',
        'settings.quota.description': 'Usage limits, archiving',
      };
      return translations[key] || fallback || key;
    },
  }),
}));

// Mock lucide-react icons
vi.mock('lucide-react', () => ({
  ArrowLeft: ({ size }: { size: number }) => <svg data-testid="arrow-left-icon" width={size} height={size} />,
  Building2: ({ size }: { size: number }) => <svg data-testid="building2-icon" width={size} height={size} />,
  Palette: ({ size }: { size: number }) => <svg data-testid="palette-icon" width={size} height={size} />,
  Layers: ({ size }: { size: number }) => <svg data-testid="layers-icon" width={size} height={size} />,
  Globe: ({ size }: { size: number }) => <svg data-testid="globe-icon" width={size} height={size} />,
  Key: ({ size }: { size: number }) => <svg data-testid="key-icon" width={size} height={size} />,
  Lock: ({ size }: { size: number }) => <svg data-testid="lock-icon" width={size} height={size} />,
  Mail: ({ size }: { size: number }) => <svg data-testid="mail-icon" width={size} height={size} />,
  Phone: ({ size }: { size: number }) => <svg data-testid="phone-icon" width={size} height={size} />,
  CreditCard: ({ size }: { size: number }) => <svg data-testid="credit-card-icon" width={size} height={size} />,
  AlertTriangle: ({ size }: { size: number }) => <svg data-testid="alert-triangle-icon" width={size} height={size} />,
  Calendar: ({ size }: { size: number }) => <svg data-testid="calendar-icon" width={size} height={size} />,
}));

// Mock usePlanFeatures hook
const mockCanUse = vi.fn();
vi.mock('../../hooks/usePlanFeatures', () => ({
  usePlanFeatures: () => ({
    canUse: mockCanUse,
  }),
}));

// Mock useOutletContext to provide parent context
const mockUseOutletContext = vi.fn();
vi.mock('react-router-dom', async (importOriginal) => {
  const actual = await importOriginal();
  return {
    ...actual,
    useOutletContext: () => mockUseOutletContext(),
  };
});

describe('SettingsLayout', () => {
  const mockUser: User = {
    id: '1',
    name: 'John Doe',
    email: 'john@example.com',
    role: 'owner',
  };

  const mockBusiness: Business = {
    id: 'business-1',
    name: 'Test Business',
    subdomain: 'testbiz',
    primaryColor: '#3B82F6',
    secondaryColor: '#10B981',
    whitelabelEnabled: false,
    plan: 'Professional',
    paymentsEnabled: false,
    requirePaymentMethodToBook: false,
    cancellationWindowHours: 24,
    lateCancellationFeePercent: 0,
  };

  const mockUpdateBusiness = vi.fn();

  const mockOutletContext = {
    user: mockUser,
    business: mockBusiness,
    updateBusiness: mockUpdateBusiness,
  };

  beforeEach(() => {
    vi.clearAllMocks();
    // Default: all features are unlocked
    mockCanUse.mockReturnValue(true);
    // Default: provide parent context
    mockUseOutletContext.mockReturnValue(mockOutletContext);
  });

  const renderWithRouter = (initialPath = '/settings/general') => {
    return render(
      <MemoryRouter initialEntries={[initialPath]}>
        <Routes>
          <Route path="/settings/*" element={<SettingsLayout />}>
            <Route path="general" element={<div>General Settings Content</div>} />
            <Route path="branding" element={<div>Branding Settings Content</div>} />
            <Route path="api" element={<div>API Settings Content</div>} />
            <Route path="billing" element={<div>Billing Settings Content</div>} />
          </Route>
          <Route path="/" element={<div>Home Page</div>} />
        </Routes>
      </MemoryRouter>
    );
  };

  describe('Rendering', () => {
    it('renders the layout with sidebar and content area', () => {
      renderWithRouter();

      // Check for sidebar
      const sidebar = screen.getByRole('complementary');
      expect(sidebar).toBeInTheDocument();
      expect(sidebar).toHaveClass('w-64', 'bg-white');

      // Check for main content area
      const main = screen.getByRole('main');
      expect(main).toBeInTheDocument();
      expect(main).toHaveClass('flex-1', 'overflow-y-auto');
    });

    it('renders the Settings title', () => {
      renderWithRouter();
      expect(screen.getByText('Settings')).toBeInTheDocument();
    });

    it('renders all section headings', () => {
      renderWithRouter();
      expect(screen.getByText('Business')).toBeInTheDocument();
      expect(screen.getByText('Branding')).toBeInTheDocument();
      expect(screen.getByText('Integrations')).toBeInTheDocument();
      expect(screen.getByText('Access')).toBeInTheDocument();
      expect(screen.getByText('Communication')).toBeInTheDocument();
      expect(screen.getByText('Billing')).toBeInTheDocument();
    });

    it('renders children content from Outlet', () => {
      renderWithRouter('/settings/general');
      expect(screen.getByText('General Settings Content')).toBeInTheDocument();
    });
  });

  describe('Back Button', () => {
    it('renders the back button', () => {
      renderWithRouter();
      const backButton = screen.getByRole('button', { name: /back to app/i });
      expect(backButton).toBeInTheDocument();
    });

    it('displays ArrowLeft icon in back button', () => {
      renderWithRouter();
      expect(screen.getByTestId('arrow-left-icon')).toBeInTheDocument();
    });

    it('navigates to home when back button is clicked', () => {
      renderWithRouter('/settings/general');
      const backButton = screen.getByRole('button', { name: /back to app/i });
      fireEvent.click(backButton);

      // Should navigate to home
      expect(screen.getByText('Home Page')).toBeInTheDocument();
    });

    it('has correct styling for back button', () => {
      renderWithRouter();
      const backButton = screen.getByRole('button', { name: /back to app/i });
      expect(backButton).toHaveClass('text-gray-600', 'hover:text-gray-900', 'transition-colors');
    });
  });

  describe('Navigation Links', () => {
    describe('Business Section', () => {
      it('renders General settings link', () => {
        renderWithRouter();
        const generalLink = screen.getByRole('link', { name: /General/i });
        expect(generalLink).toBeInTheDocument();
        expect(generalLink).toHaveAttribute('href', '/settings/general');
      });

      it('renders Resource Types settings link', () => {
        renderWithRouter();
        const resourceTypesLink = screen.getByRole('link', { name: /Resource Types/i });
        expect(resourceTypesLink).toBeInTheDocument();
        expect(resourceTypesLink).toHaveAttribute('href', '/settings/resource-types');
      });

      it('renders Booking settings link', () => {
        renderWithRouter();
        const bookingLink = screen.getByRole('link', { name: /Booking/i });
        expect(bookingLink).toBeInTheDocument();
        expect(bookingLink).toHaveAttribute('href', '/settings/booking');
      });

      it('displays icons for Business section links', () => {
        renderWithRouter();
        expect(screen.getByTestId('building2-icon')).toBeInTheDocument();
        expect(screen.getByTestId('layers-icon')).toBeInTheDocument();
        expect(screen.getByTestId('calendar-icon')).toBeInTheDocument();
      });
    });

    describe('Branding Section', () => {
      it('renders Appearance settings link', () => {
        renderWithRouter();
        const appearanceLink = screen.getByRole('link', { name: /Appearance/i });
        expect(appearanceLink).toBeInTheDocument();
        expect(appearanceLink).toHaveAttribute('href', '/settings/branding');
      });

      it('renders Email Templates settings link', () => {
        renderWithRouter();
        const emailTemplatesLink = screen.getByRole('link', { name: /Email Templates/i });
        expect(emailTemplatesLink).toBeInTheDocument();
        expect(emailTemplatesLink).toHaveAttribute('href', '/settings/email-templates');
      });

      it('renders Custom Domains settings link', () => {
        renderWithRouter();
        const customDomainsLink = screen.getByRole('link', { name: /Custom Domains/i });
        expect(customDomainsLink).toBeInTheDocument();
        expect(customDomainsLink).toHaveAttribute('href', '/settings/custom-domains');
      });

      it('displays icons for Branding section links', () => {
        renderWithRouter();
        expect(screen.getByTestId('palette-icon')).toBeInTheDocument();
        expect(screen.getAllByTestId('mail-icon').length).toBeGreaterThan(0);
        expect(screen.getByTestId('globe-icon')).toBeInTheDocument();
      });
    });

    describe('Integrations Section', () => {
      it('renders API & Webhooks settings link', () => {
        renderWithRouter();
        const apiLink = screen.getByRole('link', { name: /API & Webhooks/i });
        expect(apiLink).toBeInTheDocument();
        expect(apiLink).toHaveAttribute('href', '/settings/api');
      });

      it('displays Key icon for API link', () => {
        renderWithRouter();
        expect(screen.getByTestId('key-icon')).toBeInTheDocument();
      });
    });

    describe('Access Section', () => {
      it('renders Authentication settings link', () => {
        renderWithRouter();
        const authLink = screen.getByRole('link', { name: /Authentication/i });
        expect(authLink).toBeInTheDocument();
        expect(authLink).toHaveAttribute('href', '/settings/authentication');
      });

      it('displays Lock icon for Authentication link', () => {
        renderWithRouter();
        expect(screen.getAllByTestId('lock-icon').length).toBeGreaterThan(0);
      });
    });

    describe('Communication Section', () => {
      it('renders Email Setup settings link', () => {
        renderWithRouter();
        const emailSetupLink = screen.getByRole('link', { name: /Email Setup/i });
        expect(emailSetupLink).toBeInTheDocument();
        expect(emailSetupLink).toHaveAttribute('href', '/settings/email');
      });

      it('renders SMS & Calling settings link', () => {
        renderWithRouter();
        const smsLink = screen.getByRole('link', { name: /SMS & Calling/i });
        expect(smsLink).toBeInTheDocument();
        expect(smsLink).toHaveAttribute('href', '/settings/sms-calling');
      });

      it('displays Phone icon for SMS & Calling link', () => {
        renderWithRouter();
        expect(screen.getByTestId('phone-icon')).toBeInTheDocument();
      });
    });

    describe('Billing Section', () => {
      it('renders Plan & Billing settings link', () => {
        renderWithRouter();
        const billingLink = screen.getByRole('link', { name: /Plan & Billing/i });
        expect(billingLink).toBeInTheDocument();
        expect(billingLink).toHaveAttribute('href', '/settings/billing');
      });

      it('renders Quota Management settings link', () => {
        renderWithRouter();
        const quotaLink = screen.getByRole('link', { name: /Quota Management/i });
        expect(quotaLink).toBeInTheDocument();
        expect(quotaLink).toHaveAttribute('href', '/settings/quota');
      });

      it('displays icons for Billing section links', () => {
        renderWithRouter();
        expect(screen.getByTestId('credit-card-icon')).toBeInTheDocument();
        expect(screen.getByTestId('alert-triangle-icon')).toBeInTheDocument();
      });
    });
  });

  describe('Active Section Highlighting', () => {
    it('highlights the General link when on /settings/general', () => {
      renderWithRouter('/settings/general');
      const generalLink = screen.getByRole('link', { name: /General/i });
      expect(generalLink).toHaveClass('bg-brand-50', 'text-brand-700');
    });

    it('highlights the Branding link when on /settings/branding', () => {
      renderWithRouter('/settings/branding');
      const brandingLink = screen.getByRole('link', { name: /Appearance/i });
      expect(brandingLink).toHaveClass('bg-brand-50', 'text-brand-700');
    });

    it('highlights the API link when on /settings/api', () => {
      renderWithRouter('/settings/api');
      const apiLink = screen.getByRole('link', { name: /API & Webhooks/i });
      expect(apiLink).toHaveClass('bg-brand-50', 'text-brand-700');
    });

    it('highlights the Billing link when on /settings/billing', () => {
      renderWithRouter('/settings/billing');
      const billingLink = screen.getByRole('link', { name: /Plan & Billing/i });
      expect(billingLink).toHaveClass('bg-brand-50', 'text-brand-700');
    });

    it('does not highlight links when on different pages', () => {
      renderWithRouter('/settings/general');
      const brandingLink = screen.getByRole('link', { name: /Appearance/i });
      expect(brandingLink).not.toHaveClass('bg-brand-50', 'text-brand-700');
      expect(brandingLink).toHaveClass('text-gray-600');
    });
  });

  describe('Locked Features', () => {
    beforeEach(() => {
      // Reset mock for locked feature tests
      mockCanUse.mockImplementation((feature: string) => {
        // Lock specific features
        if (feature === 'white_label') return false;
        if (feature === 'custom_domain') return false;
        if (feature === 'api_access') return false;
        if (feature === 'custom_oauth') return false;
        if (feature === 'sms_reminders') return false;
        return true;
      });
    });

    it('shows lock icon for Appearance link when white_label is locked', () => {
      renderWithRouter();
      const appearanceLink = screen.getByRole('link', { name: /Appearance/i });
      const lockIcons = within(appearanceLink).queryAllByTestId('lock-icon');
      expect(lockIcons.length).toBeGreaterThan(0);
    });

    it('shows lock icon for Custom Domains link when custom_domain is locked', () => {
      renderWithRouter();
      const customDomainsLink = screen.getByRole('link', { name: /Custom Domains/i });
      const lockIcons = within(customDomainsLink).queryAllByTestId('lock-icon');
      expect(lockIcons.length).toBeGreaterThan(0);
    });

    it('shows lock icon for API link when api_access is locked', () => {
      renderWithRouter();
      const apiLink = screen.getByRole('link', { name: /API & Webhooks/i });
      const lockIcons = within(apiLink).queryAllByTestId('lock-icon');
      expect(lockIcons.length).toBeGreaterThan(0);
    });

    it('shows lock icon for Authentication link when custom_oauth is locked', () => {
      renderWithRouter();
      const authLink = screen.getByRole('link', { name: /Authentication/i });
      const lockIcons = within(authLink).queryAllByTestId('lock-icon');
      expect(lockIcons.length).toBeGreaterThan(0);
    });

    it('shows lock icon for SMS & Calling link when sms_reminders is locked', () => {
      renderWithRouter();
      const smsLink = screen.getByRole('link', { name: /SMS & Calling/i });
      const lockIcons = within(smsLink).queryAllByTestId('lock-icon');
      expect(lockIcons.length).toBeGreaterThan(0);
    });

    it('applies locked styling to locked links', () => {
      renderWithRouter();
      const appearanceLink = screen.getByRole('link', { name: /Appearance/i });
      expect(appearanceLink).toHaveClass('text-gray-400');
    });

    it('does not show lock icon for unlocked features', () => {
      // Reset to all unlocked
      mockCanUse.mockReturnValue(true);
      renderWithRouter();

      const generalLink = screen.getByRole('link', { name: /General/i });
      const lockIcons = within(generalLink).queryAllByTestId('lock-icon');
      expect(lockIcons.length).toBe(0);
    });
  });

  describe('Outlet Context', () => {
    it('passes parent context to child routes', () => {
      const ChildComponent = () => {
        const context = require('react-router-dom').useOutletContext();
        return (
          <div>
            <div data-testid="user-name">{context.user?.name}</div>
            <div data-testid="business-name">{context.business?.name}</div>
          </div>
        );
      };

      render(
        <MemoryRouter initialEntries={['/settings/general']}>
          <Routes>
            <Route path="/settings/*" element={<SettingsLayout />}>
              <Route path="general" element={<ChildComponent />} />
            </Route>
          </Routes>
        </MemoryRouter>
      );

      expect(screen.getByTestId('user-name')).toHaveTextContent('John Doe');
      expect(screen.getByTestId('business-name')).toHaveTextContent('Test Business');
    });

    it('passes isFeatureLocked to child routes when feature is locked', () => {
      mockCanUse.mockImplementation((feature: string) => {
        return feature !== 'white_label';
      });

      const ChildComponent = () => {
        const context = require('react-router-dom').useOutletContext();
        return (
          <div>
            <div data-testid="is-locked">{String(context.isFeatureLocked)}</div>
            <div data-testid="locked-feature">{context.lockedFeature || 'none'}</div>
          </div>
        );
      };

      render(
        <MemoryRouter initialEntries={['/settings/branding']}>
          <Routes>
            <Route path="/settings/*" element={<SettingsLayout />}>
              <Route path="branding" element={<ChildComponent />} />
            </Route>
          </Routes>
        </MemoryRouter>
      );

      expect(screen.getByTestId('is-locked')).toHaveTextContent('true');
      expect(screen.getByTestId('locked-feature')).toHaveTextContent('white_label');
    });

    it('passes isFeatureLocked as false when feature is unlocked', () => {
      mockCanUse.mockReturnValue(true);

      const ChildComponent = () => {
        const context = require('react-router-dom').useOutletContext();
        return <div data-testid="is-locked">{String(context.isFeatureLocked)}</div>;
      };

      render(
        <MemoryRouter initialEntries={['/settings/general']}>
          <Routes>
            <Route path="/settings/*" element={<SettingsLayout />}>
              <Route path="general" element={<ChildComponent />} />
            </Route>
          </Routes>
        </MemoryRouter>
      );

      expect(screen.getByTestId('is-locked')).toHaveTextContent('false');
    });
  });

  describe('Layout Structure', () => {
    it('has proper flexbox layout', () => {
      renderWithRouter();
      const layout = screen.getByRole('complementary').parentElement;
      expect(layout).toHaveClass('flex', 'h-full');
    });

    it('sidebar has correct width and styling', () => {
      renderWithRouter();
      const sidebar = screen.getByRole('complementary');
      expect(sidebar).toHaveClass('w-64', 'bg-white', 'border-r', 'flex', 'flex-col', 'shrink-0');
    });

    it('main content area has proper overflow handling', () => {
      renderWithRouter();
      const main = screen.getByRole('main');
      expect(main).toHaveClass('flex-1', 'overflow-y-auto');
    });

    it('content is constrained with max-width', () => {
      renderWithRouter();
      const contentWrapper = screen.getByText('General Settings Content').parentElement;
      expect(contentWrapper).toHaveClass('max-w-4xl', 'mx-auto', 'p-8');
    });
  });

  describe('Link Descriptions', () => {
    it('displays description for General settings', () => {
      renderWithRouter();
      expect(screen.getByText('Name, timezone, contact')).toBeInTheDocument();
    });

    it('displays description for Resource Types settings', () => {
      renderWithRouter();
      expect(screen.getByText('Staff, rooms, equipment')).toBeInTheDocument();
    });

    it('displays description for Appearance settings', () => {
      renderWithRouter();
      expect(screen.getByText('Logo, colors, theme')).toBeInTheDocument();
    });

    it('displays description for API settings', () => {
      renderWithRouter();
      expect(screen.getByText('API tokens, webhooks')).toBeInTheDocument();
    });

    it('displays description for Billing settings', () => {
      renderWithRouter();
      expect(screen.getByText('Subscription, invoices')).toBeInTheDocument();
    });
  });

  describe('Dark Mode Support', () => {
    it('has dark mode classes on sidebar', () => {
      renderWithRouter();
      const sidebar = screen.getByRole('complementary');
      expect(sidebar).toHaveClass('dark:bg-gray-800', 'dark:border-gray-700');
    });

    it('has dark mode classes on Settings title', () => {
      renderWithRouter();
      const title = screen.getByText('Settings');
      expect(title).toHaveClass('dark:text-white');
    });

    it('has dark mode classes on layout background', () => {
      renderWithRouter();
      const layout = screen.getByRole('complementary').parentElement;
      expect(layout).toHaveClass('dark:bg-gray-900');
    });
  });

  describe('Accessibility', () => {
    it('uses semantic HTML with aside element', () => {
      renderWithRouter();
      const sidebar = screen.getByRole('complementary');
      expect(sidebar.tagName).toBe('ASIDE');
    });

    it('uses semantic HTML with main element', () => {
      renderWithRouter();
      const main = screen.getByRole('main');
      expect(main.tagName).toBe('MAIN');
    });

    it('uses semantic HTML with nav element', () => {
      renderWithRouter();
      const nav = screen.getByRole('navigation');
      expect(nav.tagName).toBe('NAV');
    });

    it('all navigation links are keyboard accessible', () => {
      renderWithRouter();
      const links = screen.getAllByRole('link');
      links.forEach(link => {
        expect(link).toHaveAttribute('href');
      });
    });

    it('back button is keyboard accessible', () => {
      renderWithRouter();
      const backButton = screen.getByRole('button', { name: /back to app/i });
      expect(backButton.tagName).toBe('BUTTON');
    });
  });

  describe('Edge Cases', () => {
    it('handles navigation between different settings pages', () => {
      const { rerender } = renderWithRouter('/settings/general');
      expect(screen.getByText('General Settings Content')).toBeInTheDocument();

      // Navigate to branding
      render(
        <MemoryRouter initialEntries={['/settings/branding']}>
          <Routes>
            <Route path="/settings/*" element={<SettingsLayout />}>
              <Route path="branding" element={<div>Branding Settings Content</div>} />
            </Route>
          </Routes>
        </MemoryRouter>
      );

      expect(screen.getByText('Branding Settings Content')).toBeInTheDocument();
    });

    it('handles all features being locked', () => {
      mockCanUse.mockReturnValue(false);
      renderWithRouter();

      // Should still render all links, just with locked styling
      expect(screen.getByRole('link', { name: /Appearance/i })).toBeInTheDocument();
      expect(screen.getByRole('link', { name: /Custom Domains/i })).toBeInTheDocument();
      expect(screen.getByRole('link', { name: /API & Webhooks/i })).toBeInTheDocument();
    });

    it('handles all features being unlocked', () => {
      mockCanUse.mockReturnValue(true);
      renderWithRouter();

      // Lock icons should not be visible
      const appearanceLink = screen.getByRole('link', { name: /Appearance/i });
      const lockIcons = within(appearanceLink).queryAllByTestId('lock-icon');
      expect(lockIcons.length).toBe(0);
    });

    it('renders without crashing when no route matches', () => {
      expect(() => renderWithRouter('/settings/nonexistent')).not.toThrow();
    });
  });
});
