/**
 * Unit tests for Upgrade page
 *
 * Tests cover:
 * - Pricing plans display (Professional, Business, Enterprise)
 * - Current plan highlighted
 * - Upgrade buttons work
 * - Feature comparison
 * - Payment flow initiation
 * - Billing period toggle (monthly/annual)
 * - Pricing calculations and savings display
 * - Enterprise contact flow
 * - Error handling
 */

import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { render, screen, waitFor, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { BrowserRouter, useNavigate, useOutletContext } from 'react-router-dom';
import React from 'react';
import Upgrade from '../Upgrade';
import { User, Business } from '../../types';

// Mock react-router-dom
vi.mock('react-router-dom', async () => {
  const actual = await vi.importActual('react-router-dom');
  return {
    ...actual,
    useNavigate: vi.fn(),
    useOutletContext: vi.fn(),
  };
});

// Mock react-i18next
vi.mock('react-i18next', () => ({
  useTranslation: () => ({
    t: (key: string, params?: any) => {
      // Handle translation keys with parameters
      if (key === 'upgrade.subtitle' && params?.businessName) {
        return `Choose the perfect plan for ${params.businessName}`;
      }
      if (key === 'upgrade.features.resources' && params?.count) {
        return `Up to ${params.count} resources`;
      }
      if (key === 'upgrade.billing.saveAmount' && params?.amount) {
        return `Save $${params.amount}/year`;
      }

      // Simple key mapping for other translations
      const translations: Record<string, string> = {
        'marketing.pricing.tiers.professional.name': 'Professional',
        'marketing.pricing.tiers.professional.description': 'For growing businesses',
        'marketing.pricing.tiers.business.name': 'Business',
        'marketing.pricing.tiers.business.description': 'For established businesses',
        'marketing.pricing.tiers.enterprise.name': 'Enterprise',
        'marketing.pricing.tiers.enterprise.description': 'For large organizations',
        'upgrade.title': 'Upgrade Your Plan',
        'upgrade.mostPopular': 'Most Popular',
        'upgrade.plan': 'Plan',
        'upgrade.selected': 'Selected',
        'upgrade.selectPlan': 'Select Plan',
        'upgrade.custom': 'Custom',
        'upgrade.month': 'month',
        'upgrade.year': 'year',
        'upgrade.billing.monthly': 'Monthly',
        'upgrade.billing.annual': 'Annual',
        'upgrade.billing.save20': 'Save 20%',
        'upgrade.features.unlimitedResources': 'Unlimited resources',
        'upgrade.features.customDomain': 'Custom domain',
        'upgrade.features.stripeConnect': 'Stripe Connect',
        'upgrade.features.whitelabel': 'White-label branding',
        'upgrade.features.emailReminders': 'Email reminders',
        'upgrade.features.prioritySupport': 'Priority email support',
        'upgrade.features.teamManagement': 'Team management',
        'upgrade.features.advancedAnalytics': 'Advanced analytics',
        'upgrade.features.apiAccess': 'API access',
        'upgrade.features.phoneSupport': 'Phone support',
        'upgrade.features.everything': 'Everything in Business',
        'upgrade.features.customIntegrations': 'Custom integrations',
        'upgrade.features.dedicatedManager': 'Dedicated success manager',
        'upgrade.features.sla': 'SLA guarantees',
        'upgrade.features.customContracts': 'Custom contracts',
        'upgrade.features.onPremise': 'On-premise option',
        'upgrade.orderSummary': 'Order Summary',
        'upgrade.billedMonthly': 'Billed monthly',
        'upgrade.billedAnnually': 'Billed annually',
        'upgrade.annualSavings': 'Annual Savings',
        'upgrade.trust.secure': 'Secure Checkout',
        'upgrade.trust.instant': 'Instant Access',
        'upgrade.trust.support': '24/7 Support',
        'upgrade.continueToPayment': 'Continue to Payment',
        'upgrade.contactSales': 'Contact Sales',
        'upgrade.processing': 'Processing...',
        'upgrade.secureCheckout': 'Secure checkout powered by Stripe',
        'upgrade.questions': 'Questions?',
        'upgrade.contactUs': 'Contact us',
        'upgrade.errors.processingFailed': 'Payment processing failed. Please try again.',
        'common.back': 'Back',
      };

      return translations[key] || key;
    },
  }),
}));

// Test data
const mockUser: User = {
  id: '1',
  name: 'John Doe',
  email: 'john@example.com',
  role: 'owner',
};

const mockBusiness: Business = {
  id: '1',
  name: 'Test Business',
  subdomain: 'testbiz',
  primaryColor: '#0066CC',
  secondaryColor: '#00AA66',
  whitelabelEnabled: false,
  plan: 'Professional',
  paymentsEnabled: true,
  requirePaymentMethodToBook: false,
  cancellationWindowHours: 24,
  lateCancellationFeePercent: 50,
};

// Test wrapper with Router
const createWrapper = () => {
  return ({ children }: { children: React.ReactNode }) => (
    <BrowserRouter>{children}</BrowserRouter>
  );
};

describe('Upgrade Page', () => {
  let mockNavigate: ReturnType<typeof vi.fn>;
  let mockUseOutletContext: ReturnType<typeof vi.fn>;

  beforeEach(() => {
    mockNavigate = vi.fn();
    mockUseOutletContext = vi.fn(() => ({ user: mockUser, business: mockBusiness }));

    vi.mocked(useNavigate).mockReturnValue(mockNavigate);
    vi.mocked(useOutletContext).mockImplementation(mockUseOutletContext);

    // Mock window.alert
    global.alert = vi.fn();

    // Mock window.location.href
    delete (window as any).location;
    window.location = { href: '' } as any;
  });

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

  describe('Page Rendering', () => {
    it('should render the page title', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      expect(screen.getByText('Upgrade Your Plan')).toBeInTheDocument();
    });

    it('should render the subtitle with business name', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      expect(screen.getByText('Choose the perfect plan for Test Business')).toBeInTheDocument();
    });

    it('should render back button', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      const backButton = screen.getByRole('button', { name: /back/i });
      expect(backButton).toBeInTheDocument();
    });

    it('should navigate back when back button is clicked', async () => {
      const user = userEvent.setup();
      render(<Upgrade />, { wrapper: createWrapper() });

      const backButton = screen.getByRole('button', { name: /back/i });
      await user.click(backButton);

      expect(mockNavigate).toHaveBeenCalledWith(-1);
    });
  });

  describe('Pricing Plans Display', () => {
    it('should display all three pricing tiers', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      expect(screen.getByText('Professional')).toBeInTheDocument();
      expect(screen.getByText('Business')).toBeInTheDocument();
      expect(screen.getByText('Enterprise')).toBeInTheDocument();
    });

    it('should display plan descriptions', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      expect(screen.getByText('For growing businesses')).toBeInTheDocument();
      expect(screen.getByText('For established businesses')).toBeInTheDocument();
      expect(screen.getByText('For large organizations')).toBeInTheDocument();
    });

    it('should display "Most Popular" badge on Business plan', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      expect(screen.getByText('Most Popular')).toBeInTheDocument();
    });

    it('should display monthly prices by default', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      // Use getAllByText since prices appear in both card and summary
      expect(screen.getAllByText('$29').length).toBeGreaterThan(0);
      expect(screen.getAllByText('$79').length).toBeGreaterThan(0);
    });

    it('should display "Custom" for Enterprise pricing', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      expect(screen.getByText('Custom')).toBeInTheDocument();
    });

    it('should display Professional plan as selected by default', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      const selectedBadges = screen.getAllByText('Selected');
      expect(selectedBadges).toHaveLength(1); // In the selected plan card
    });
  });

  describe('Billing Period Toggle', () => {
    it('should render monthly and annual billing options', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      const monthlyButton = screen.getByRole('button', { name: /monthly/i });
      const annualButton = screen.getByRole('button', { name: /annual/i });

      expect(monthlyButton).toBeInTheDocument();
      expect(annualButton).toBeInTheDocument();
    });

    it('should show "Save 20%" badge on annual option', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      expect(screen.getByText('Save 20%')).toBeInTheDocument();
    });

    it('should switch to annual pricing when annual button is clicked', async () => {
      const user = userEvent.setup();
      render(<Upgrade />, { wrapper: createWrapper() });

      const annualButton = screen.getByRole('button', { name: /annual/i });
      await user.click(annualButton);

      // Annual prices - use getAllByText since prices appear in both card and summary
      expect(screen.getAllByText('$290').length).toBeGreaterThan(0);
      expect(screen.getAllByText('$790').length).toBeGreaterThan(0);
    });

    it('should display annual savings when annual billing is selected', async () => {
      const user = userEvent.setup();
      render(<Upgrade />, { wrapper: createWrapper() });

      const annualButton = screen.getByRole('button', { name: /annual/i });
      await user.click(annualButton);

      // Professional: $29 * 12 - $290 = $58 savings
      expect(screen.getByText('Save $58/year')).toBeInTheDocument();
      // Business: $79 * 12 - $790 = $158 savings
      expect(screen.getByText('Save $158/year')).toBeInTheDocument();
    });

    it('should switch back to monthly pricing', async () => {
      const user = userEvent.setup();
      render(<Upgrade />, { wrapper: createWrapper() });

      const annualButton = screen.getByRole('button', { name: /annual/i });
      await user.click(annualButton);

      expect(screen.getAllByText('$290').length).toBeGreaterThan(0);

      const monthlyButton = screen.getByRole('button', { name: /monthly/i });
      await user.click(monthlyButton);

      expect(screen.getAllByText('$29').length).toBeGreaterThan(0);
    });
  });

  describe('Plan Selection', () => {
    it('should select Business plan when clicked', async () => {
      const user = userEvent.setup();
      render(<Upgrade />, { wrapper: createWrapper() });

      // Find the Business plan card
      const businessCard = screen.getByText('Business').closest('div[class*="cursor-pointer"]');
      expect(businessCard).toBeInTheDocument();

      await user.click(businessCard!);

      // Should update order summary
      expect(screen.getByText('Business Plan')).toBeInTheDocument();
      expect(screen.getAllByText('$79').length).toBeGreaterThan(0);
    });

    it('should select Enterprise plan when clicked', async () => {
      const user = userEvent.setup();
      render(<Upgrade />, { wrapper: createWrapper() });

      const enterpriseCard = screen.getByText('Enterprise').closest('div[class*="cursor-pointer"]');
      await user.click(enterpriseCard!);

      expect(screen.getByText('Enterprise Plan')).toBeInTheDocument();
    });

    it('should show selected state on clicked plan', async () => {
      const user = userEvent.setup();
      render(<Upgrade />, { wrapper: createWrapper() });

      const businessCard = screen.getByText('Business').closest('div[class*="cursor-pointer"]');
      await user.click(businessCard!);

      // Find all "Selected" badges - should be 2 (one in card, one in summary)
      const selectedBadges = screen.getAllByText('Selected');
      expect(selectedBadges.length).toBeGreaterThan(0);
    });
  });

  describe('Feature Comparison', () => {
    it('should display Professional plan features', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      // Use getAllByText since features may appear in multiple places
      expect(screen.getAllByText('Up to 10 resources').length).toBeGreaterThan(0);
      expect(screen.getAllByText('Custom domain').length).toBeGreaterThan(0);
      expect(screen.getAllByText('Stripe Connect').length).toBeGreaterThan(0);
      expect(screen.getAllByText('White-label branding').length).toBeGreaterThan(0);
      expect(screen.getAllByText('Email reminders').length).toBeGreaterThan(0);
      expect(screen.getAllByText('Priority email support').length).toBeGreaterThan(0);
    });

    it('should display Business plan features', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      // Use getAllByText since features may appear in multiple places
      expect(screen.getAllByText('Unlimited resources').length).toBeGreaterThan(0);
      expect(screen.getAllByText('Team management').length).toBeGreaterThan(0);
      expect(screen.getAllByText('Advanced analytics').length).toBeGreaterThan(0);
      expect(screen.getAllByText('API access')).toHaveLength(2); // Shown in both Business and Enterprise
      expect(screen.getAllByText('Phone support').length).toBeGreaterThan(0);
    });

    it('should display Enterprise plan features', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      expect(screen.getByText('Everything in Business')).toBeInTheDocument();
      expect(screen.getByText('Custom integrations')).toBeInTheDocument();
      expect(screen.getByText('Dedicated success manager')).toBeInTheDocument();
      expect(screen.getByText('SLA guarantees')).toBeInTheDocument();
      expect(screen.getByText('Custom contracts')).toBeInTheDocument();
      expect(screen.getByText('On-premise option')).toBeInTheDocument();
    });

    it('should show features with checkmarks', () => {
      const { container } = render(<Upgrade />, { wrapper: createWrapper() });

      // Check for lucide Check icons (SVGs with lucide-check class)
      const checkIcons = container.querySelectorAll('.lucide-check');
      expect(checkIcons.length).toBeGreaterThan(0);
    });
  });

  describe('Order Summary', () => {
    it('should display order summary section', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      expect(screen.getByText('Order Summary')).toBeInTheDocument();
    });

    it('should show selected plan in summary', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      expect(screen.getByText('Professional Plan')).toBeInTheDocument();
    });

    it('should show billing frequency in summary', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      expect(screen.getByText('Billed monthly')).toBeInTheDocument();
    });

    it('should show price in summary', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      // Professional plan monthly price
      const summarySection = screen.getByText('Order Summary').closest('div');
      expect(within(summarySection!).getAllByText('$29')).toHaveLength(1);
    });

    it('should update summary when plan changes', async () => {
      const user = userEvent.setup();
      render(<Upgrade />, { wrapper: createWrapper() });

      const businessCard = screen.getByText('Business').closest('div[class*="cursor-pointer"]');
      await user.click(businessCard!);

      expect(screen.getByText('Business Plan')).toBeInTheDocument();
    });

    it('should show annual savings in summary when annual billing selected', async () => {
      const user = userEvent.setup();
      render(<Upgrade />, { wrapper: createWrapper() });

      const annualButton = screen.getByRole('button', { name: /annual/i });
      await user.click(annualButton);

      expect(screen.getByText('Annual Savings')).toBeInTheDocument();
      expect(screen.getByText('-$58')).toBeInTheDocument(); // Professional plan savings
    });
  });

  describe('Trust Indicators', () => {
    it('should display trust indicators', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      expect(screen.getByText('Secure Checkout')).toBeInTheDocument();
      expect(screen.getByText('Instant Access')).toBeInTheDocument();
      expect(screen.getByText('24/7 Support')).toBeInTheDocument();
    });

    it('should display trust indicator icons', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      // Shield, Zap, and Users icons from lucide-react
      const trustSection = screen.getByText('Secure Checkout').closest('div')?.parentElement;
      expect(trustSection).toBeInTheDocument();
    });
  });

  describe('Payment Flow Initiation', () => {
    it('should display upgrade button', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      const upgradeButton = screen.getByRole('button', { name: /continue to payment/i });
      expect(upgradeButton).toBeInTheDocument();
    });

    it('should show processing state when upgrade button is clicked', async () => {
      const user = userEvent.setup();
      render(<Upgrade />, { wrapper: createWrapper() });

      const upgradeButton = screen.getByRole('button', { name: /continue to payment/i });

      // Click the button
      await user.click(upgradeButton);

      // Should show processing state
      await waitFor(() => {
        expect(screen.getByText('Processing...')).toBeInTheDocument();
      });
    });

    it('should disable button during processing', async () => {
      const user = userEvent.setup();
      render(<Upgrade />, { wrapper: createWrapper() });

      const upgradeButton = screen.getByRole('button', { name: /continue to payment/i });
      await user.click(upgradeButton);

      await waitFor(() => {
        expect(upgradeButton).toBeDisabled();
      });
    });

    it('should show alert with upgrade details (placeholder for Stripe integration)', async () => {
      const user = userEvent.setup();
      render(<Upgrade />, { wrapper: createWrapper() });

      const upgradeButton = screen.getByRole('button', { name: /continue to payment/i });
      await user.click(upgradeButton);

      await waitFor(() => {
        expect(global.alert).toHaveBeenCalledWith(
          expect.stringContaining('Upgrading to Professional')
        );
      }, { timeout: 3000 });
    });

    it('should navigate after successful payment', async () => {
      const user = userEvent.setup();
      render(<Upgrade />, { wrapper: createWrapper() });

      const upgradeButton = screen.getByRole('button', { name: /continue to payment/i });
      await user.click(upgradeButton);

      await waitFor(() => {
        expect(mockNavigate).toHaveBeenCalledWith('/');
      }, { timeout: 3000 });
    });

    it('should change button text for Enterprise plan', async () => {
      const user = userEvent.setup();
      render(<Upgrade />, { wrapper: createWrapper() });

      const enterpriseCard = screen.getByText('Enterprise').closest('div[class*="cursor-pointer"]');
      await user.click(enterpriseCard!);

      expect(screen.getByRole('button', { name: /contact sales/i })).toBeInTheDocument();
    });

    it('should open email client for Enterprise plan', async () => {
      const user = userEvent.setup();
      render(<Upgrade />, { wrapper: createWrapper() });

      const enterpriseCard = screen.getByText('Enterprise').closest('div[class*="cursor-pointer"]');
      await user.click(enterpriseCard!);

      const contactButton = screen.getByRole('button', { name: /contact sales/i });
      await user.click(contactButton);

      expect(window.location.href).toBe('mailto:sales@smoothschedule.com?subject=Enterprise Plan Inquiry');
    });
  });

  describe('Error Handling', () => {
    it('should not display error message initially', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      expect(screen.queryByText('Payment processing failed. Please try again.')).not.toBeInTheDocument();
    });

    // Note: Testing actual payment failure requires mocking the payment API
    // which is handled by the integration tests. This unit test just verifies
    // the error state is not shown initially.
  });

  describe('Responsive Behavior', () => {
    it('should have responsive grid for plan cards', () => {
      const { container } = render(<Upgrade />, { wrapper: createWrapper() });

      // Find the grid container with md:grid-cols-3
      const planGrid = container.querySelector('.md\\:grid-cols-3');
      expect(planGrid).toBeInTheDocument();
      expect(planGrid).toHaveClass('grid');
    });

    it('should center content in container', () => {
      const { container } = render(<Upgrade />, { wrapper: createWrapper() });

      const mainContainer = container.querySelector('.max-w-6xl');
      expect(mainContainer).toBeInTheDocument();
      expect(mainContainer).toHaveClass('mx-auto');
    });
  });

  describe('Accessibility', () => {
    it('should have proper heading hierarchy', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      const h1 = screen.getByRole('heading', { level: 1, name: /upgrade your plan/i });
      expect(h1).toBeInTheDocument();

      const h2 = screen.getByRole('heading', { level: 2, name: /order summary/i });
      expect(h2).toBeInTheDocument();
    });

    it('should have accessible plan tier headings', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      const h3Headings = screen.getAllByRole('heading', { level: 3 });
      expect(h3Headings.length).toBeGreaterThanOrEqual(3); // Professional, Business, Enterprise
    });

    it('should have accessible buttons', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      const upgradeButton = screen.getByRole('button', { name: /continue to payment/i });
      expect(upgradeButton).toHaveAccessibleName();
    });

    it('should have accessible links', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      const contactLink = screen.getByRole('link', { name: /contact us/i });
      expect(contactLink).toBeInTheDocument();
      expect(contactLink).toHaveAttribute('href', 'mailto:support@smoothschedule.com');
    });
  });

  describe('Dark Mode Support', () => {
    it('should have dark mode classes', () => {
      const { container } = render(<Upgrade />, { wrapper: createWrapper() });

      // The outer container has dark mode class
      const darkModeContainer = container.querySelector('.dark\\:bg-gray-900');
      expect(darkModeContainer).toBeInTheDocument();
    });
  });

  describe('Footer Links', () => {
    it('should display questions section', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      expect(screen.getByText('Questions?')).toBeInTheDocument();
    });

    it('should display contact us link', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      const contactLink = screen.getByRole('link', { name: /contact us/i });
      expect(contactLink).toBeInTheDocument();
      expect(contactLink).toHaveAttribute('href', 'mailto:support@smoothschedule.com');
    });

    it('should display secure checkout message', () => {
      render(<Upgrade />, { wrapper: createWrapper() });

      expect(screen.getByText('Secure checkout powered by Stripe')).toBeInTheDocument();
    });
  });

  describe('Integration Tests', () => {
    it('should maintain state across billing period changes', async () => {
      const user = userEvent.setup();
      render(<Upgrade />, { wrapper: createWrapper() });

      // Select Business plan
      const businessCard = screen.getByText('Business').closest('div[class*="cursor-pointer"]');
      await user.click(businessCard!);

      // Switch to annual
      const annualButton = screen.getByRole('button', { name: /annual/i });
      await user.click(annualButton);

      // Should still be Business plan
      expect(screen.getByText('Business Plan')).toBeInTheDocument();
      expect(screen.getAllByText('$790').length).toBeGreaterThan(0);
    });

    it('should update all prices when switching billing periods', async () => {
      const user = userEvent.setup();
      render(<Upgrade />, { wrapper: createWrapper() });

      // Switch to annual
      const annualButton = screen.getByRole('button', { name: /annual/i });
      await user.click(annualButton);

      // Check summary updates
      expect(screen.getByText('Billed annually')).toBeInTheDocument();
      expect(screen.getAllByText('$290').length).toBeGreaterThan(0);
    });

    it('should handle rapid plan selections', async () => {
      const user = userEvent.setup();
      render(<Upgrade />, { wrapper: createWrapper() });

      const professionalCard = screen.getByText('Professional').closest('div[class*="cursor-pointer"]');
      const businessCard = screen.getByText('Business').closest('div[class*="cursor-pointer"]');
      const enterpriseCard = screen.getByText('Enterprise').closest('div[class*="cursor-pointer"]');

      // Rapidly click different plans
      await user.click(businessCard!);
      await user.click(enterpriseCard!);
      await user.click(professionalCard!);

      // Should end up with Professional selected
      expect(screen.getByText('Professional Plan')).toBeInTheDocument();
    });
  });
});
