/**
 * Tests for Recaptcha component
 */
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { render, screen, waitFor } from '@testing-library/react';
import Recaptcha from '../Recaptcha';
import * as systemSettingsService from '../../../features/system/services/systemSettingsService';

// Mock the reCAPTCHA service
vi.mock('../../../services/api/systemSettingsService', () => ({
  recaptchaService: {
    getRecaptchaSettings: vi.fn(),
  },
}));

// Mock react-google-recaptcha
vi.mock('react-google-recaptcha', () => ({
  default: ({ sitekey, onChange, onExpired, onError, theme, size }: any) => (
    <div data-testid="recaptcha-mock">
      <div>Site Key: {sitekey}</div>
      <div>Theme: {theme}</div>
      <div>Size: {size}</div>
      <button onClick={() => onChange && onChange('test-token')}>Verify</button>
      <button onClick={() => onExpired && onExpired()}>Expire</button>
      <button onClick={() => onError && onError()}>Error</button>
    </div>
  ),
}));

describe('Recaptcha', () => {
  beforeEach(() => {
    // Clear localStorage before each test
    localStorage.clear();
    vi.clearAllMocks();
  });

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

  it('renders nothing when reCAPTCHA is disabled', async () => {
    vi.mocked(systemSettingsService.recaptchaService.getRecaptchaSettings).mockResolvedValue({
      status: 'success',
      data: {
        recaptcha_enabled: false,
        recaptcha_site_key: 'test-key',
      },
    });

    const { container } = render(<Recaptcha />);
    
    await waitFor(() => {
      expect(container.firstChild).toBeNull();
    });
  });

  it('renders reCAPTCHA when enabled', async () => {
    vi.mocked(systemSettingsService.recaptchaService.getRecaptchaSettings).mockResolvedValue({
      status: 'success',
      data: {
        recaptcha_enabled: true,
        recaptcha_site_key: 'test-site-key',
      },
    });

    render(<Recaptcha />);
    
    await waitFor(() => {
      expect(screen.getByTestId('recaptcha-mock')).toBeInTheDocument();
      expect(screen.getByText('Site Key: test-site-key')).toBeInTheDocument();
    });
  });

  it('calls onChange callback when token is received', async () => {
    const onChange = vi.fn();
    
    vi.mocked(systemSettingsService.recaptchaService.getRecaptchaSettings).mockResolvedValue({
      status: 'success',
      data: {
        recaptcha_enabled: true,
        recaptcha_site_key: 'test-key',
      },
    });

    render(<Recaptcha onChange={onChange} />);
    
    await waitFor(() => {
      expect(screen.getByTestId('recaptcha-mock')).toBeInTheDocument();
    });

    const verifyButton = screen.getByText('Verify');
    verifyButton.click();

    await waitFor(() => {
      expect(onChange).toHaveBeenCalledWith('test-token');
    });
  });

  it('calls onError callback when error occurs', async () => {
    const onError = vi.fn();
    
    vi.mocked(systemSettingsService.recaptchaService.getRecaptchaSettings).mockResolvedValue({
      status: 'success',
      data: {
        recaptcha_enabled: true,
        recaptcha_site_key: 'test-key',
      },
    });

    render(<Recaptcha onError={onError} />);
    
    await waitFor(() => {
      expect(screen.getByTestId('recaptcha-mock')).toBeInTheDocument();
    });

    const errorButton = screen.getByText('Error');
    errorButton.click();

    await waitFor(() => {
      expect(onError).toHaveBeenCalledWith('reCAPTCHA error occurred');
    });
  });

  it('uses cached settings on subsequent renders', async () => {
    vi.mocked(systemSettingsService.recaptchaService.getRecaptchaSettings).mockResolvedValue({
      status: 'success',
      data: {
        recaptcha_enabled: true,
        recaptcha_site_key: 'cached-key',
      },
    });

    // First render
    const { unmount } = render(<Recaptcha />);
    await waitFor(() => {
      expect(screen.getByText('Site Key: cached-key')).toBeInTheDocument();
    });
    unmount();

    // Second render should use cache
    render(<Recaptcha />);
    await waitFor(() => {
      expect(screen.getByText('Site Key: cached-key')).toBeInTheDocument();
    });

    // Should only call API once
    expect(systemSettingsService.recaptchaService.getRecaptchaSettings).toHaveBeenCalledTimes(1);
  });

  it('applies custom theme and size props', async () => {
    vi.mocked(systemSettingsService.recaptchaService.getRecaptchaSettings).mockResolvedValue({
      status: 'success',
      data: {
        recaptcha_enabled: true,
        recaptcha_site_key: 'test-key',
      },
    });

    render(<Recaptcha theme="light" size="compact" />);
    
    await waitFor(() => {
      expect(screen.getByText('Theme: light')).toBeInTheDocument();
      expect(screen.getByText('Size: compact')).toBeInTheDocument();
    });
  });
});

