/**
 * Unit tests for QuotaWarningBanner component
 *
 * Tests cover:
 * - Rendering based on quota overage state
 * - Critical, urgent, and warning severity levels
 * - Display of correct percentage and usage information
 * - Multiple overages display
 * - Manage Quota button/link functionality
 * - Dismiss button functionality
 * - Date formatting
 * - Internationalization (i18n)
 * - Accessibility attributes
 */

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { BrowserRouter } from 'react-router-dom';
import React from 'react';
import QuotaWarningBanner from '../QuotaWarningBanner';
import { QuotaOverage } from '../../api/auth';

// Mock react-i18next
vi.mock('react-i18next', () => ({
  useTranslation: () => ({
    t: (key: string, fallback: string, options?: Record<string, unknown>) => {
      // Handle interpolation for dynamic values
      if (options) {
        let result = fallback;
        Object.entries(options).forEach(([key, value]) => {
          result = result.replace(`{{${key}}}`, String(value));
        });
        return result;
      }
      return fallback;
    },
  }),
}));

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

// Test data factories
const createMockOverage = (overrides?: Partial<QuotaOverage>): QuotaOverage => ({
  id: 1,
  quota_type: 'resources',
  display_name: 'Resources',
  current_usage: 15,
  allowed_limit: 10,
  overage_amount: 5,
  days_remaining: 14,
  grace_period_ends_at: '2025-12-21T00:00:00Z',
  ...overrides,
});

describe('QuotaWarningBanner', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  describe('Rendering Conditions', () => {
    it('should not render when overages array is empty', () => {
      const { container } = render(
        <QuotaWarningBanner overages={[]} />,
        { wrapper: createWrapper() }
      );

      expect(container).toBeEmptyDOMElement();
    });

    it('should not render when overages is null', () => {
      const { container } = render(
        <QuotaWarningBanner overages={null as any} />,
        { wrapper: createWrapper() }
      );

      expect(container).toBeEmptyDOMElement();
    });

    it('should not render when overages is undefined', () => {
      const { container } = render(
        <QuotaWarningBanner overages={undefined as any} />,
        { wrapper: createWrapper() }
      );

      expect(container).toBeEmptyDOMElement();
    });

    it('should render when quota is near limit (warning state)', () => {
      const overages = [createMockOverage({ days_remaining: 14 })];

      render(<QuotaWarningBanner overages={overages} />, {
        wrapper: createWrapper(),
      });

      expect(screen.getByText(/quota exceeded/i)).toBeInTheDocument();
    });

    it('should render when quota is critical (1 day remaining)', () => {
      const overages = [createMockOverage({ days_remaining: 1 })];

      render(<QuotaWarningBanner overages={overages} />, {
        wrapper: createWrapper(),
      });

      expect(screen.getByText(/urgent.*automatic archiving tomorrow/i)).toBeInTheDocument();
    });

    it('should render when quota is urgent (7 days remaining)', () => {
      const overages = [createMockOverage({ days_remaining: 7 })];

      render(<QuotaWarningBanner overages={overages} />, {
        wrapper: createWrapper(),
      });

      expect(screen.getByText(/action required.*7 days left/i)).toBeInTheDocument();
    });
  });

  describe('Severity Levels and Styling', () => {
    it('should apply warning styles for normal overages (>7 days)', () => {
      const overages = [createMockOverage({ days_remaining: 14 })];

      const { container } = render(
        <QuotaWarningBanner overages={overages} />,
        { wrapper: createWrapper() }
      );

      const banner = container.querySelector('div[class*="bg-amber-100"]');
      expect(banner).toBeInTheDocument();
    });

    it('should apply urgent styles for 7 days or less', () => {
      const overages = [createMockOverage({ days_remaining: 7 })];

      const { container } = render(
        <QuotaWarningBanner overages={overages} />,
        { wrapper: createWrapper() }
      );

      const banner = container.querySelector('div[class*="bg-amber-500"]');
      expect(banner).toBeInTheDocument();
    });

    it('should apply critical styles for 1 day or less', () => {
      const overages = [createMockOverage({ days_remaining: 1 })];

      const { container } = render(
        <QuotaWarningBanner overages={overages} />,
        { wrapper: createWrapper() }
      );

      const banner = container.querySelector('div[class*="bg-red-600"]');
      expect(banner).toBeInTheDocument();
    });

    it('should apply critical styles for 0 days remaining', () => {
      const overages = [createMockOverage({ days_remaining: 0 })];

      const { container } = render(
        <QuotaWarningBanner overages={overages} />,
        { wrapper: createWrapper() }
      );

      const banner = container.querySelector('div[class*="bg-red-600"]');
      expect(banner).toBeInTheDocument();
    });
  });

  describe('Usage and Percentage Display', () => {
    it('should display correct overage amount', () => {
      const overages = [
        createMockOverage({
          overage_amount: 5,
          display_name: 'Resources',
        }),
      ];

      render(<QuotaWarningBanner overages={overages} />, {
        wrapper: createWrapper(),
      });

      expect(screen.getByText(/you have 5 Resources over your plan limit/i)).toBeInTheDocument();
    });

    it('should display current usage and limit in multi-overage list', () => {
      const overages = [
        createMockOverage({
          id: 1,
          current_usage: 15,
          allowed_limit: 10,
          display_name: 'Staff Members',
        }),
        createMockOverage({
          id: 2,
          current_usage: 20,
          allowed_limit: 15,
          display_name: 'Resources',
        }),
      ];

      render(<QuotaWarningBanner overages={overages} />, {
        wrapper: createWrapper(),
      });

      // Usage/limit is shown in the "All overages" list when there are multiple
      expect(screen.getByText(/Staff Members: 15\/10/)).toBeInTheDocument();
      expect(screen.getByText(/Resources: 20\/15/)).toBeInTheDocument();
    });

    it('should display quota type name', () => {
      const overages = [
        createMockOverage({
          display_name: 'Calendar Events',
          overage_amount: 100,
        }),
      ];

      render(<QuotaWarningBanner overages={overages} />, {
        wrapper: createWrapper(),
      });

      expect(screen.getByText(/you have 100 Calendar Events over your plan limit/i)).toBeInTheDocument();
    });

    it('should format and display grace period end date', () => {
      const overages = [
        createMockOverage({
          grace_period_ends_at: '2025-12-25T00:00:00Z',
        }),
      ];

      render(<QuotaWarningBanner overages={overages} />, {
        wrapper: createWrapper(),
      });

      // Date formatting will depend on locale, but should contain the date components
      const detailsText = screen.getByText(/grace period ends/i);
      expect(detailsText).toBeInTheDocument();
    });
  });

  describe('Multiple Overages', () => {
    it('should display most urgent overage in main message', () => {
      const overages = [
        createMockOverage({ id: 1, days_remaining: 14, display_name: 'Resources' }),
        createMockOverage({ id: 2, days_remaining: 3, display_name: 'Staff Members' }),
        createMockOverage({ id: 3, days_remaining: 7, display_name: 'Events' }),
      ];

      render(<QuotaWarningBanner overages={overages} />, {
        wrapper: createWrapper(),
      });

      // Should show the most urgent (3 days)
      expect(screen.getByText(/action required.*3 days left/i)).toBeInTheDocument();
    });

    it('should show additional overages section when multiple overages exist', () => {
      const overages = [
        createMockOverage({ id: 1, days_remaining: 14, display_name: 'Resources', current_usage: 15, allowed_limit: 10, overage_amount: 5 }),
        createMockOverage({ id: 2, days_remaining: 7, display_name: 'Staff', current_usage: 8, allowed_limit: 5, overage_amount: 3 }),
      ];

      render(<QuotaWarningBanner overages={overages} />, {
        wrapper: createWrapper(),
      });

      expect(screen.getByText(/all overages:/i)).toBeInTheDocument();
    });

    it('should list all overages with details in the additional section', () => {
      const overages = [
        createMockOverage({
          id: 1,
          display_name: 'Resources',
          current_usage: 15,
          allowed_limit: 10,
          overage_amount: 5,
          days_remaining: 14,
        }),
        createMockOverage({
          id: 2,
          display_name: 'Staff',
          current_usage: 8,
          allowed_limit: 5,
          overage_amount: 3,
          days_remaining: 7,
        }),
      ];

      render(<QuotaWarningBanner overages={overages} />, {
        wrapper: createWrapper(),
      });

      expect(screen.getByText(/Resources: 15\/10/)).toBeInTheDocument();
      expect(screen.getByText(/over by 5/)).toBeInTheDocument();
      expect(screen.getByText(/Staff: 8\/5/)).toBeInTheDocument();
      expect(screen.getByText(/over by 3/)).toBeInTheDocument();
    });

    it('should not show additional overages section for single overage', () => {
      const overages = [createMockOverage()];

      render(<QuotaWarningBanner overages={overages} />, {
        wrapper: createWrapper(),
      });

      expect(screen.queryByText(/all overages:/i)).not.toBeInTheDocument();
    });

    it('should display "expires today" for 0 days remaining in overage list', () => {
      const overages = [
        createMockOverage({ id: 1, days_remaining: 14 }),
        createMockOverage({ id: 2, days_remaining: 0, display_name: 'Critical Item' }),
      ];

      render(<QuotaWarningBanner overages={overages} />, {
        wrapper: createWrapper(),
      });

      expect(screen.getByText(/expires today!/i)).toBeInTheDocument();
    });
  });

  describe('Manage Quota Button', () => {
    it('should render Manage Quota link', () => {
      const overages = [createMockOverage()];

      render(<QuotaWarningBanner overages={overages} />, {
        wrapper: createWrapper(),
      });

      const link = screen.getByRole('link', { name: /manage quota/i });
      expect(link).toBeInTheDocument();
    });

    it('should link to settings/quota page', () => {
      const overages = [createMockOverage()];

      render(<QuotaWarningBanner overages={overages} />, {
        wrapper: createWrapper(),
      });

      const link = screen.getByRole('link', { name: /manage quota/i });
      expect(link).toHaveAttribute('href', '/settings/quota');
    });

    it('should display external link icon', () => {
      const overages = [createMockOverage()];

      render(<QuotaWarningBanner overages={overages} />, {
        wrapper: createWrapper(),
      });

      const link = screen.getByRole('link', { name: /manage quota/i });
      const icon = link.querySelector('svg');
      expect(icon).toBeInTheDocument();
    });

    it('should apply warning button styles for normal overages', () => {
      const overages = [createMockOverage({ days_remaining: 14 })];

      render(<QuotaWarningBanner overages={overages} />, {
        wrapper: createWrapper(),
      });

      const link = screen.getByRole('link', { name: /manage quota/i });
      expect(link).toHaveClass('bg-amber-600');
    });

    it('should apply urgent button styles for urgent/critical overages', () => {
      const overages = [createMockOverage({ days_remaining: 7 })];

      render(<QuotaWarningBanner overages={overages} />, {
        wrapper: createWrapper(),
      });

      const link = screen.getByRole('link', { name: /manage quota/i });
      expect(link).toHaveClass('bg-white/20');
    });
  });

  describe('Dismiss Button', () => {
    it('should render dismiss button when onDismiss prop is provided', () => {
      const overages = [createMockOverage()];
      const onDismiss = vi.fn();

      render(<QuotaWarningBanner overages={overages} onDismiss={onDismiss} />, {
        wrapper: createWrapper(),
      });

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

    it('should not render dismiss button when onDismiss prop is not provided', () => {
      const overages = [createMockOverage()];

      render(<QuotaWarningBanner overages={overages} />, {
        wrapper: createWrapper(),
      });

      const dismissButton = screen.queryByRole('button', { name: /dismiss/i });
      expect(dismissButton).not.toBeInTheDocument();
    });

    it('should call onDismiss when dismiss button is clicked', async () => {
      const user = userEvent.setup();
      const overages = [createMockOverage()];
      const onDismiss = vi.fn();

      render(<QuotaWarningBanner overages={overages} onDismiss={onDismiss} />, {
        wrapper: createWrapper(),
      });

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

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

    it('should display X icon in dismiss button', () => {
      const overages = [createMockOverage()];
      const onDismiss = vi.fn();

      render(<QuotaWarningBanner overages={overages} onDismiss={onDismiss} />, {
        wrapper: createWrapper(),
      });

      const dismissButton = screen.getByRole('button', { name: /dismiss/i });
      const icon = dismissButton.querySelector('svg');
      expect(icon).toBeInTheDocument();
    });
  });

  describe('Accessibility', () => {
    it('should have alert icon with appropriate styling', () => {
      const overages = [createMockOverage()];

      const { container } = render(
        <QuotaWarningBanner overages={overages} />,
        { wrapper: createWrapper() }
      );

      // AlertTriangle icon should be present
      const icon = container.querySelector('svg');
      expect(icon).toBeInTheDocument();
    });

    it('should have accessible label for dismiss button', () => {
      const overages = [createMockOverage()];
      const onDismiss = vi.fn();

      render(<QuotaWarningBanner overages={overages} onDismiss={onDismiss} />, {
        wrapper: createWrapper(),
      });

      const dismissButton = screen.getByRole('button', { name: /dismiss/i });
      expect(dismissButton).toHaveAttribute('aria-label', 'Dismiss');
    });

    it('should use semantic HTML structure', () => {
      const overages = [createMockOverage({ days_remaining: 14 })];

      const { container } = render(
        <QuotaWarningBanner overages={overages} />,
        { wrapper: createWrapper() }
      );

      // Should have proper div structure
      expect(container.querySelector('div')).toBeInTheDocument();
    });

    it('should have accessible link for Manage Quota', () => {
      const overages = [createMockOverage()];

      render(<QuotaWarningBanner overages={overages} />, {
        wrapper: createWrapper(),
      });

      const link = screen.getByRole('link', { name: /manage quota/i });
      expect(link).toBeInTheDocument();
      expect(link.tagName).toBe('A');
    });
  });

  describe('Message Priority', () => {
    it('should show critical message for 1 day remaining', () => {
      const overages = [createMockOverage({ days_remaining: 1 })];

      render(<QuotaWarningBanner overages={overages} />, {
        wrapper: createWrapper(),
      });

      expect(screen.getByText(/urgent.*automatic archiving tomorrow/i)).toBeInTheDocument();
    });

    it('should show urgent message for 2-7 days remaining', () => {
      const overages = [createMockOverage({ days_remaining: 5 })];

      render(<QuotaWarningBanner overages={overages} />, {
        wrapper: createWrapper(),
      });

      expect(screen.getByText(/action required.*5 days left/i)).toBeInTheDocument();
    });

    it('should show warning message for more than 7 days remaining', () => {
      const overages = [createMockOverage({ days_remaining: 10 })];

      render(<QuotaWarningBanner overages={overages} />, {
        wrapper: createWrapper(),
      });

      expect(screen.getByText(/quota exceeded for 1 item/i)).toBeInTheDocument();
    });

    it('should show count of overages in warning message', () => {
      const overages = [
        createMockOverage({ id: 1, days_remaining: 14 }),
        createMockOverage({ id: 2, days_remaining: 10 }),
        createMockOverage({ id: 3, days_remaining: 12 }),
      ];

      render(<QuotaWarningBanner overages={overages} />, {
        wrapper: createWrapper(),
      });

      expect(screen.getByText(/quota exceeded for 3 item/i)).toBeInTheDocument();
    });
  });

  describe('Integration', () => {
    it('should render complete banner with all elements', () => {
      const overages = [
        createMockOverage({
          id: 1,
          quota_type: 'resources',
          display_name: 'Resources',
          current_usage: 15,
          allowed_limit: 10,
          overage_amount: 5,
          days_remaining: 7,
          grace_period_ends_at: '2025-12-21T00:00:00Z',
        }),
      ];
      const onDismiss = vi.fn();

      render(<QuotaWarningBanner overages={overages} onDismiss={onDismiss} />, {
        wrapper: createWrapper(),
      });

      // Check main message
      expect(screen.getByText(/action required.*7 days left/i)).toBeInTheDocument();

      // Check details
      expect(screen.getByText(/you have 5 Resources over your plan limit/i)).toBeInTheDocument();

      // Check Manage Quota link
      const link = screen.getByRole('link', { name: /manage quota/i });
      expect(link).toBeInTheDocument();
      expect(link).toHaveAttribute('href', '/settings/quota');

      // Check dismiss button
      const dismissButton = screen.getByRole('button', { name: /dismiss/i });
      expect(dismissButton).toBeInTheDocument();

      // Check icons are present (via SVG elements)
      const { container } = render(<QuotaWarningBanner overages={overages} onDismiss={onDismiss} />, {
        wrapper: createWrapper(),
      });
      const icons = container.querySelectorAll('svg');
      expect(icons.length).toBeGreaterThan(0);
    });

    it('should handle complex multi-overage scenario', async () => {
      const user = userEvent.setup();
      const overages = [
        createMockOverage({
          id: 1,
          display_name: 'Resources',
          current_usage: 15,
          allowed_limit: 10,
          overage_amount: 5,
          days_remaining: 14,
        }),
        createMockOverage({
          id: 2,
          display_name: 'Staff Members',
          current_usage: 12,
          allowed_limit: 8,
          overage_amount: 4,
          days_remaining: 2,
        }),
        createMockOverage({
          id: 3,
          display_name: 'Calendar Events',
          current_usage: 500,
          allowed_limit: 400,
          overage_amount: 100,
          days_remaining: 7,
        }),
      ];
      const onDismiss = vi.fn();

      render(<QuotaWarningBanner overages={overages} onDismiss={onDismiss} />, {
        wrapper: createWrapper(),
      });

      // Should show most urgent (2 days)
      expect(screen.getByText(/action required.*2 days left/i)).toBeInTheDocument();

      // Should show all overages section
      expect(screen.getByText(/all overages:/i)).toBeInTheDocument();
      expect(screen.getByText(/Resources: 15\/10/)).toBeInTheDocument();
      expect(screen.getByText(/Staff Members: 12\/8/)).toBeInTheDocument();
      expect(screen.getByText(/Calendar Events: 500\/400/)).toBeInTheDocument();

      // Should be able to dismiss
      const dismissButton = screen.getByRole('button', { name: /dismiss/i });
      await user.click(dismissButton);
      expect(onDismiss).toHaveBeenCalledTimes(1);
    });
  });

  describe('Edge Cases', () => {
    it('should handle negative days remaining', () => {
      const overages = [createMockOverage({ days_remaining: -1 })];

      render(<QuotaWarningBanner overages={overages} />, {
        wrapper: createWrapper(),
      });

      // Should treat as critical (0 or less)
      const { container } = render(
        <QuotaWarningBanner overages={overages} />,
        { wrapper: createWrapper() }
      );

      const banner = container.querySelector('div[class*="bg-red-600"]');
      expect(banner).toBeInTheDocument();
    });

    it('should handle very large overage amounts', () => {
      const overages = [
        createMockOverage({
          overage_amount: 999999,
          display_name: 'Events',
        }),
      ];

      render(<QuotaWarningBanner overages={overages} />, {
        wrapper: createWrapper(),
      });

      expect(screen.getByText(/you have 999999 Events over your plan limit/i)).toBeInTheDocument();
    });

    it('should handle zero overage amount', () => {
      const overages = [
        createMockOverage({
          overage_amount: 0,
          current_usage: 10,
          allowed_limit: 10,
        }),
      ];

      render(<QuotaWarningBanner overages={overages} />, {
        wrapper: createWrapper(),
      });

      expect(screen.getByText(/you have 0 Resources over your plan limit/i)).toBeInTheDocument();
    });
  });
});
