/**
 * Tests for EmailPreviewContent Component
 * 
 * Tests email preview rendering with all states, devices, and edge cases
 */

import React from 'react';
import { render, screen } from '@testing-library/react';
import { injectIntl, IntlProvider } from 'react-intl';
import EmailPreviewContent from '../../UnifiedPreview/EmailPreviewContent';
import { DESKTOP, MOBILE, TABLET } from '../../constants';
import messages from '../../messages';

// Wrap component with injectIntl - extract formatMessage from intl and pass to component
const ComponentToRender = injectIntl(({ intl, ...props }) => (
  <EmailPreviewContent {...props} formatMessage={intl.formatMessage} />
));

// Convert messages object to format expected by IntlProvider
// messages is a defineMessages object, need to convert to flat object
const messagesForIntl = Object.keys(messages).reduce((acc, key) => {
  const message = messages[key];
  acc[message.id] = message.defaultMessage;
  return acc;
}, {});

// Test wrapper - use IntlProvider with messages
// injectIntl will inject formatMessage into ComponentToRender props
const TestWrapper = ({ children }) => (
  <IntlProvider locale="en" messages={messagesForIntl}>
    {children}
  </IntlProvider>
);

describe('EmailPreviewContent', () => {
  const defaultProps = {
    content: '<html><body>Test Email Content</body></html>',
    subject: 'Test Subject',
    device: DESKTOP,
    isUpdating: false,
    error: null,
  };

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

  describe('Loading State', () => {
    it('should render loading state when isUpdating is true', () => {
      const props = {
        ...defaultProps,
        isUpdating: true,
      };

      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      // Check for loading container and text element
      const loadingContainer = container.querySelector('.loading-container');
      expect(loadingContainer).toBeTruthy();
      const loadingText = container.querySelector('.loading-text');
      expect(loadingText).toBeTruthy();
    });

    it('should show loading spinner', () => {
      const props = {
        ...defaultProps,
        isUpdating: true,
      };

      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      expect(container.querySelector('.ant-spin')).toBeTruthy();
    });

    it('should render email structure in loading state', () => {
      const props = {
        ...defaultProps,
        isUpdating: true,
      };

      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      expect(container.querySelector('.preview-body')).toBeTruthy();
      expect(container.querySelector('.browser-bar')).toBeTruthy();
      expect(container.querySelector('.email-header')).toBeTruthy();
    });
  });

  describe('Error State', () => {
    it('should render error state when error is present', () => {
      const props = {
        ...defaultProps,
        error: 'Error message',
      };

      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      // Check for error container instead of text (text might appear multiple times)
      expect(container.querySelector('.error-container')).toBeTruthy();
    });

    it('should show error icon', () => {
      const props = {
        ...defaultProps,
        error: 'Error message',
      };

      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      expect(container.querySelector('.anticon-exclamation-circle')).toBeTruthy();
    });

    it('should display error message', () => {
      const props = {
        ...defaultProps,
        error: 'Custom error message',
      };

      render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      expect(screen.getByText('Custom error message')).toBeTruthy();
    });
  });

  describe('Normal State with Content', () => {
    it('should render iframe with content', () => {
      const props = {
        ...defaultProps,
        content: '<html><body>Email Content</body></html>',
      };

      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      const iframe = container.querySelector('iframe');
      expect(iframe).not.toBeNull();
      expect(iframe).toBeTruthy();
      if (iframe) {
        expect(iframe.getAttribute('title')).toBe('Email Preview');
        expect(iframe.getAttribute('frameBorder')).toBe('0');
      }
    });

    it('should set correct iframe dimensions for desktop', () => {
      const props = {
        ...defaultProps,
        device: DESKTOP,
        content: '<html>Content</html>',
      };

      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      const iframe = container.querySelector('iframe');
      expect(iframe).not.toBeNull();
      expect(iframe).toBeTruthy();
      if (iframe) {
        expect(iframe.getAttribute('width')).toBe('1024');
        expect(iframe.getAttribute('height')).toBe('500');
      }
    });

    it('should set correct iframe dimensions for tablet with subject', () => {
      const props = {
        ...defaultProps,
        device: TABLET,
        subject: 'Test Subject',
        content: '<html>Content</html>',
      };

      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      const iframe = container.querySelector('iframe');
      expect(iframe).toBeTruthy();
      expect(iframe).not.toBeNull();
      expect(iframe.getAttribute('width')).toBe('450');
      expect(iframe.getAttribute('height')).toBe('570');
    });

    it('should set correct iframe dimensions for tablet without subject', () => {
      const props = {
        ...defaultProps,
        device: TABLET,
        subject: '',
        content: '<html>Content</html>',
      };

      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      const iframe = container.querySelector('iframe');
      expect(iframe).not.toBeNull();
      if (iframe) {
        expect(iframe.getAttribute('width')).toBe('450');
        expect(iframe.getAttribute('height')).toBe('600');
      }
    });

    it('should set correct iframe dimensions for mobile with subject', () => {
      const props = {
        ...defaultProps,
        device: MOBILE,
        subject: 'Test Subject',
        content: '<html>Content</html>',
      };

      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      const iframe = container.querySelector('iframe');
      expect(iframe).toBeTruthy();
      expect(iframe).not.toBeNull();
      expect(iframe.getAttribute('width')).toBe('310');
      expect(iframe.getAttribute('height')).toBe('570');
    });

    it('should set correct iframe dimensions for mobile without subject', () => {
      const props = {
        ...defaultProps,
        device: MOBILE,
        subject: '',
        content: '<html>Content</html>',
      };

      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      const iframe = container.querySelector('iframe');
      expect(iframe).toBeTruthy();
      expect(iframe).not.toBeNull();
      expect(iframe.getAttribute('width')).toBe('310');
      expect(iframe.getAttribute('height')).toBe('600');
    });

    it('should use cleaned content in iframe', () => {
      // eslint-disable-next-line global-require
      // eslint-disable-next-line global-require
      const props = {
        ...defaultProps,
        content: '<html><a href="#">Link</a></html>',
      };

      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );
      const iframe = container.querySelector('iframe');
      expect(iframe).toBeTruthy();
    });
  });

  describe('No Content State', () => {
    it('should render no content message when content is empty', () => {
      const props = {
        ...defaultProps,
        content: '',
      };

      render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      expect(screen.getByText('No content available')).toBeTruthy();
    });

    it('should render no content message when content is null', () => {
      const props = {
        ...defaultProps,
        content: null,
      };

      render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      expect(screen.getByText('No content available')).toBeTruthy();
    });

    it('should render no content message when content is undefined', () => {
      const props = {
        ...defaultProps,
        content: undefined,
      };

      render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      expect(screen.getByText('No content available')).toBeTruthy();
    });
  });

  describe('Email Structure', () => {
    it('should render browser bar', () => {
      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...defaultProps} />
        </TestWrapper>
      );

      expect(container.querySelector('.browser-bar')).toBeTruthy();
      expect(container.querySelector('.browser-controls')).toBeTruthy();
      expect(container.querySelector('.address-bar')).toBeTruthy();
    });

    it('should render browser controls icons', () => {
      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...defaultProps} />
        </TestWrapper>
      );

      const controls = container.querySelector('.browser-controls');
      expect(controls).toBeTruthy();
    });

    it('should render address bar with label', () => {
      render(
        <TestWrapper>
          <ComponentToRender {...defaultProps} />
        </TestWrapper>
      );

      expect(screen.getByText('www.yourmail.com')).toBeTruthy();
    });

    it('should render divider', () => {
      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...defaultProps} />
        </TestWrapper>
      );

      expect(container.querySelector('.preview-divider')).toBeTruthy();
    });

    it('should render email header', () => {
      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...defaultProps} />
        </TestWrapper>
      );

      expect(container.querySelector('.email-header')).toBeTruthy();
      expect(container.querySelector('.email-subject')).toBeTruthy();
      expect(container.querySelector('.email-meta')).toBeTruthy();
    });

    it('should display subject in email header', () => {
      const props = {
        ...defaultProps,
        subject: 'My Email Subject',
      };

      render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      expect(screen.getByText('My Email Subject')).toBeTruthy();
    });

    it('should display empty subject when not provided', () => {
      const props = {
        ...defaultProps,
        subject: '',
      };

      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      const subjectElement = container.querySelector('.email-subject');
      expect(subjectElement).toBeTruthy();
      expect(subjectElement.textContent).toBe('');
    });

    it('should render time ago in email meta', () => {
      render(
        <TestWrapper>
          <ComponentToRender {...defaultProps} />
        </TestWrapper>
      );

      expect(screen.getByText('Today')).toBeTruthy();
    });

    it('should render email from section', () => {
      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...defaultProps} />
        </TestWrapper>
      );

      expect(container.querySelector('.email-from')).toBeTruthy();
      expect(container.querySelector('.sender-avatar')).toBeTruthy();
      expect(container.querySelector('.sender-info')).toBeTruthy();
    });

    it('should display sender name', () => {
      render(
        <TestWrapper>
          <ComponentToRender {...defaultProps} />
        </TestWrapper>
      );

      expect(screen.getByText('Capillary Technologies')).toBeTruthy();
    });

    it('should display recipient info', () => {
      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...defaultProps} />
        </TestWrapper>
      );

      const recipientInfo = container.querySelector('.recipient-info');
      expect(recipientInfo).toBeTruthy();
      expect(recipientInfo.textContent).toBe('to me');
    });

    it('should render email content section', () => {
      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...defaultProps} />
        </TestWrapper>
      );

      expect(container.querySelector('.email-content')).toBeTruthy();
    });
  });

  describe('Device Handling', () => {
    it('should apply desktop class for desktop device', () => {
      const props = {
        ...defaultProps,
        device: DESKTOP,
      };

      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      expect(container.querySelector('.preview-body.desktop')).toBeTruthy();
    });

    it('should apply mobile class for mobile device', () => {
      const props = {
        ...defaultProps,
        device: MOBILE,
      };

      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      expect(container.querySelector('.preview-body.mobile')).toBeTruthy();
    });

    it('should apply tablet class for tablet device', () => {
      const props = {
        ...defaultProps,
        device: TABLET,
      };

      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      expect(container.querySelector('.preview-body.tablet')).toBeTruthy();
    });

    it('should default to desktop when device is undefined', () => {
      const props = {
        ...defaultProps,
        device: undefined,
      };

      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      expect(container.querySelector('.preview-body.desktop')).toBeTruthy();
    });

    it('should default to desktop when device is null', () => {
      const props = {
        ...defaultProps,
        device: null,
      };

      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      expect(container.querySelector('.preview-body.desktop')).toBeTruthy();
    });
  });

  describe('Content Cleaning', () => {
    it('should render iframe when content is provided', () => {
      const content = '<html><a href="#">Link</a></html>';
      const props = {
        ...defaultProps,
        content,
      };

      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      const iframe = container.querySelector('iframe');
      expect(iframe).toBeTruthy();
    });

    it('should render no content message when content is null', () => {
      const props = {
        ...defaultProps,
        content: null,
      };

      render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      expect(screen.getByText('No content available')).toBeTruthy();
    });

    it('should render no content message when content is empty', () => {
      const props = {
        ...defaultProps,
        content: '',
      };

      render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      expect(screen.getByText('No content available')).toBeTruthy();
    });
  });

  describe('Edge Cases', () => {
    it('should handle very long content', () => {
      const longContent = '<html><body>' + 'A'.repeat(10000) + '</body></html>';
      const props = {
        ...defaultProps,
        content: longContent,
      };

      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      const iframe = container.querySelector('iframe');
      expect(iframe).toBeTruthy();
      expect(iframe).not.toBeNull();
    });

    it('should handle content with special characters', () => {
      const props = {
        ...defaultProps,
        content: '<html><body>&lt;script&gt;alert("test")&lt;/script&gt;</body></html>',
      };

      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      const iframe = container.querySelector('iframe');
      expect(iframe).toBeTruthy();
      expect(iframe).not.toBeNull();
    });

    it('should handle content with newlines', () => {
      const props = {
        ...defaultProps,
        content: '<html><body>Line 1\nLine 2\nLine 3</body></html>',
      };

      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      const iframe = container.querySelector('iframe');
      expect(iframe).toBeTruthy();
      expect(iframe).not.toBeNull();
    });

    it('should handle very long subject', () => {
      const props = {
        ...defaultProps,
        subject: 'A'.repeat(200),
      };

      render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      expect(screen.getByText('A'.repeat(200))).toBeTruthy();
    });

    it('should handle subject with special characters', () => {
      const props = {
        ...defaultProps,
        subject: 'Subject with @#$%^&*() characters',
      };

      render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );

      expect(screen.getByText('Subject with @#$%^&*() characters')).toBeTruthy();
    });
  });

  describe('Default Props', () => {
    it('should use default props when not provided', () => {
      const minimalProps = {
        formatMessage: jest.fn((msg) => msg.defaultMessage || msg.id),
      };

      render(
        <TestWrapper>
          <EmailPreviewContent {...minimalProps} />
        </TestWrapper>
      );

      expect(screen.getByText('No content available')).toBeTruthy();
    });
  });

  describe('PropTypes Validation', () => {
    it('should accept all required props without warnings', () => {
      const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {});

      render(
        <TestWrapper>
          <ComponentToRender {...defaultProps} />
        </TestWrapper>
      );

      expect(consoleSpy).not.toHaveBeenCalled();
      consoleSpy.mockRestore();
    });
  });
});
