/**
 * Tests for SmsPreviewContent Component
 * 
 * Tests SMS preview rendering on Android and iOS devices
 */

import React from 'react';
import { render, screen } from '@testing-library/react';
import { IntlProvider, injectIntl } from 'react-intl';
import SmsPreviewContent from '../../UnifiedPreview/SmsPreviewContent';
import { ANDROID, IOS } from '../../constants';
import messages from '../../messages';

// Convert messages object to format expected by IntlProvider
const messagesForIntl = Object.keys(messages).reduce((acc, key) => {
  const message = messages[key];
  acc[message.id] = message.defaultMessage;
  return acc;
}, {});
    
// Wrap component with injectIntl - PreviewHeader doesn't need formatMessage, it uses FormattedMessage
// But we still need IntlProvider for FormattedMessage to work
const ComponentToRender = injectIntl(({ intl, ...props }) => (
  <SmsPreviewContent {...props} formatMessage={intl.formatMessage} />
));
    
// Test wrapper - use IntlProvider with messages
const TestWrapper = ({ children }) => (
  <IntlProvider locale="en" messages={messagesForIntl}>
    {children}
  </IntlProvider>
);

describe('SmsPreviewContent', () => {
  const defaultProps = {
    content: 'Test SMS message',
    device: ANDROID,
    isUpdating: false,
    error: null,
    formatMessage: jest.fn((msg) => msg.defaultMessage || msg.id),
    senderId: 'SENDER123',
  };

  beforeEach(() => {
    jest.clearAllMocks();
    // Restore Date if it was mocked
    jest.restoreAllMocks();
  });

  afterEach(() => {
    // Ensure Date is restored after each test
    jest.restoreAllMocks();
  });

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

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

      expect(screen.getByText('Updating preview with the latest changes')).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 show device image in loading state', () => {
      const props = {
        ...defaultProps,
        isUpdating: true,
        device: ANDROID,
      };

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

      expect(container.querySelector('.sms-device-image')).toBeTruthy();
    });
  });

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

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

      expect(screen.getAllByText('Failed to load preview')).toHaveLength(2);
    });

    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 Preview - Android', () => {
    it('should render Android device preview', () => {
      const props = {
        ...defaultProps,
        device: ANDROID,
      };

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

      expect(container.querySelector('.sms-device-container')).toBeTruthy();
      expect(container.querySelector('.sms-android')).toBeTruthy();
    });

    it('should display SMS content', () => {
      const props = {
        ...defaultProps,
        device: ANDROID,
        content: 'Hello, this is a test SMS',
      };

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

      expect(screen.getByText('Hello, this is a test SMS')).toBeTruthy();
    });

    it('should display sender ID', () => {
      const props = {
        ...defaultProps,
        device: ANDROID,
        senderId: 'MY_SENDER',
      };

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

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

    it('should display timestamp', () => {
      const props = {
        ...defaultProps,
        device: ANDROID,
      };

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

      // Timestamp format: "H:MM AM/PM"
      const timestamp = screen.getByText(/\d{1,2}:\d{2} (AM|PM)/);
      expect(timestamp).toBeTruthy();
    });

    it('should display date separator', () => {
      const props = {
        ...defaultProps,
        device: ANDROID,
      };

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

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

    it('should render navigation bar', () => {
      const props = {
        ...defaultProps,
        device: ANDROID,
      };

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

      expect(container.querySelector('.sms-navigation-bar')).toBeTruthy();
    });
  });

  describe('Normal Preview - iOS', () => {
    it('should render iOS device preview', () => {
      const props = {
        ...defaultProps,
        device: IOS,
      };

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

      expect(container.querySelector('.sms-device-container')).toBeTruthy();
      expect(container.querySelector('.sms-ios')).toBeTruthy();
    });

    it('should display SMS content on iOS', () => {
      const props = {
        ...defaultProps,
        device: IOS,
        content: 'iOS SMS message',
      };

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

      expect(screen.getByText('iOS SMS message')).toBeTruthy();
    });
  });

  describe('Content Handling', () => {
    it('should handle empty content', () => {
      const props = {
        ...defaultProps,
        content: '',
      };

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

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

    it('should handle null content', () => {
      const props = {
        ...defaultProps,
        content: null,
      };

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

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

    it('should handle undefined content', () => {
      const props = {
        ...defaultProps,
        content: undefined,
      };

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

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

    it('should handle long content', () => {
      const longContent = 'A'.repeat(500);
      const props = {
        ...defaultProps,
        content: longContent,
      };

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

      expect(screen.getByText(longContent)).toBeTruthy();
    });

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

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

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

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

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

      expect(screen.getByText(/Line 1/)).toBeTruthy();
    });
  });

  describe('Sender ID Handling', () => {
    it('should display default sender ID when not provided', () => {
      const props = {
        ...defaultProps,
        senderId: null,
      };

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

      expect(screen.getByText('Sender ID')).toBeTruthy();
    });

    it('should handle empty sender ID', () => {
      const props = {
        ...defaultProps,
        senderId: '',
      };

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

      expect(screen.getByText('Sender ID')).toBeTruthy();
    });

    it('should handle undefined sender ID', () => {
      const props = {
        ...defaultProps,
        senderId: undefined,
      };

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

      expect(screen.getByText('Sender ID')).toBeTruthy();
    });
  });

  describe('Timestamp Generation', () => {
    it('should generate timestamp in correct format', () => {
      const props = {
        ...defaultProps,
      };

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

      // Timestamp should match format: "H:MM AM/PM"
      const timestamp = screen.getByText(/\d{1,2}:\d{2} (AM|PM)/);
      expect(timestamp).toBeTruthy();
    });

    it('should format minutes with leading zero when needed', () => {
      // Mock Date to test specific time
      const mockDate = new Date('2024-01-01T09:05:00');
      const OriginalDate = global.Date;
      const dateSpy = jest.spyOn(global, 'Date').mockImplementation((...args) => {
        if (args.length === 0) {
          return mockDate;
        }
        return new OriginalDate(...args);
      });
      // Preserve Date.now
      dateSpy.now = OriginalDate.now;

      const props = {
        ...defaultProps,
      };

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

      const timestamp = screen.getByText(/9:05/);
      expect(timestamp).toBeTruthy();

      dateSpy.mockRestore();
    });

    it('should display AM for morning hours', () => {
      const mockDate = new Date('2024-01-01T09:00:00');
      const OriginalDate = global.Date;
      const dateSpy = jest.spyOn(global, 'Date').mockImplementation((...args) => {
        if (args.length === 0) {
          return mockDate;
        }
        return new OriginalDate(...args);
      });
      // Preserve Date.now
      dateSpy.now = OriginalDate.now;

      const props = {
        ...defaultProps,
      };

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

      const timestamp = screen.getByText(/AM/);
      expect(timestamp).toBeTruthy();

      dateSpy.mockRestore();
    });

    it('should display PM for afternoon hours', () => {
      const mockDate = new Date('2024-01-01T15:00:00');
      const OriginalDate = global.Date;
      const dateSpy = jest.spyOn(global, 'Date').mockImplementation((...args) => {
        if (args.length === 0) {
          return mockDate;
        }
        return new OriginalDate(...args);
      });
      // Preserve Date.now
      dateSpy.now = OriginalDate.now;

      const props = {
        ...defaultProps,
      };

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

      const timestamp = screen.getByText(/PM/);
      expect(timestamp).toBeTruthy();

      dateSpy.mockRestore();
    });

    it('should convert 12-hour format correctly', () => {
      const mockDate = new Date('2024-01-01T00:00:00');
      const OriginalDate = global.Date;
      const dateSpy = jest.spyOn(global, 'Date').mockImplementation((...args) => {
        if (args.length === 0) {
          return mockDate;
        }
        return new OriginalDate(...args);
      });
      // Preserve Date.now
      dateSpy.now = OriginalDate.now;

      const props = {
        ...defaultProps,
      };

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

      // Midnight should be 12:00 AM
      const timestamp = screen.getByText(/12:00 AM/);
      expect(timestamp).toBeTruthy();

      dateSpy.mockRestore();
    });
  });

  describe('Edge Cases', () => {
    it('should handle all device types', () => {
      const devices = [ANDROID, IOS];

      devices.forEach((device) => {
        const { unmount } = render(
          <TestWrapper>
            <ComponentToRender
              {...defaultProps}
              device={device}
            />
          </TestWrapper>
        );
        expect(screen.getByText(defaultProps.content)).toBeTruthy();
        unmount();
      });
    });

    it('should handle missing formatMessage', () => {
      const props = {
        ...defaultProps,
        formatMessage: undefined,
      };

      // Should not crash
      expect(() => {
        render(
          <TestWrapper>
            <ComponentToRender {...props} />
          </TestWrapper>
        );
      }).not.toThrow();
    });
  });

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

      render(
        <TestWrapper>
          <ComponentToRender {...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();
    });
  });
});
