/**
 * Tests for ViberPreviewContent Component
 * 
 * Tests Viber preview rendering with all states, media types, and edge cases
 */

import React from 'react';
import { render, screen } from '@testing-library/react';
import { IntlProvider, injectIntl } from 'react-intl';
import '@testing-library/jest-dom';
import ViberPreviewContent from '../../UnifiedPreview/ViberPreviewContent';
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 }) => (
  <ViberPreviewContent {...props} formatMessage={intl.formatMessage} />
));
      
// Test wrapper - use IntlProvider with messages
const TestWrapper = ({ children }) => (
  <IntlProvider locale="en" messages={messagesForIntl}>
    {children}
  </IntlProvider>
);

describe('ViberPreviewContent', () => {
  const defaultProps = {
    content: {
      viberPreviewContent: {
        messageContent: 'Viber message text',
        imageURL: '',
        videoParams: {},
        buttonText: '',
      },
    },
    device: ANDROID,
    isUpdating: false,
    error: null,
    formatMessage: jest.fn((msg) => msg.defaultMessage || msg.id),
    accountName: 'Viber Account',
    brandName: 'Brand Name',
  };

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

  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();
    });
  });

  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);
    });
  });

  describe('Text Content', () => {
    it('should render message content', () => {
      const props = {
        ...defaultProps,
        content: {
          viberPreviewContent: {
            messageContent: 'Hello, this is a Viber message',
          },
        },
      };

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

      expect(screen.getByText('Hello, this is a Viber message')).toBeTruthy();
    });
  });

  describe('Image Content', () => {
    it('should render image when imageURL is present', () => {
      const props = {
        ...defaultProps,
        content: {
          viberPreviewContent: {
            messageContent: 'Message',
            imageURL: 'https://image.url',
          },
        },
      };

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

      const image = container.querySelector('.viber-image-preview');
      expect(image).toBeTruthy();
      expect(image.getAttribute('src')).toBe('https://image.url');
    });
  });

  describe('Video Content', () => {
    it('should render video preview when videoParams.viberVideoSrc is present', () => {
      const props = {
        ...defaultProps,
        content: {
          viberPreviewContent: {
            messageContent: 'Message',
            videoParams: {
              viberVideoSrc: 'https://video.url',
              viberVideoPreviewImg: 'https://preview.url',
            },
          },
        },
      };

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

    it('should use viberVideoSrc as fallback for preview image', () => {
      const props = {
        ...defaultProps,
        content: {
          viberPreviewContent: {
            messageContent: 'Message',
            videoParams: {
              viberVideoSrc: 'https://video.url',
            },
          },
        },
      };

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

      const image = container.querySelector('.viber-video-preview');
      expect(image.getAttribute('src')).toBe('https://video.url');
    });
  });

  describe('Button Content', () => {
    it('should render button when buttonText is present', () => {
      const props = {
        ...defaultProps,
        content: {
          viberPreviewContent: {
            messageContent: 'Message',
            buttonText: 'Click Here',
          },
        },
      };

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

      expect(screen.getByText('Click Here')).toBeTruthy();
    });

    it('should not render button when buttonText has only whitespace', () => {
      const props = {
        ...defaultProps,
        content: {
          viberPreviewContent: {
            messageContent: 'Message',
            buttonText: '   ',
          },
        },
      };

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

      expect(container.querySelector('.viber-button-base')).toBeFalsy();
    });
  });

  describe('Carousel Content', () => {
    it('should render no content when carousel is selected but cards are empty', () => {
      const props = {
        ...defaultProps,
        content: {
          viberPreviewContent: {
            type: 'CAROUSEL',
            cards: [
              {
                text: '',
                mediaUrl: '',
                buttons: [
                  { title: '', action: '' },
                ],
              },
              {
                text: '   ',
                mediaUrl: '   ',
                buttons: [
                  { title: '   ', action: 'https://example.com/2' },
                ],
              },
            ],
          },
        },
      };

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

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

    it('should render carousel cards when type is CAROUSEL', () => {
      const props = {
        ...defaultProps,
        content: {
          viberPreviewContent: {
            type: 'CAROUSEL',
            cards: [
              {
                text: 'Card 1 text',
                mediaUrl: 'https://image.url/card1.jpg',
                buttons: [
                  { title: 'Button 1', action: 'https://example.com/1' },
                ],
              },
              {
                text: 'Card 2 text',
                mediaUrl: 'https://image.url/card2.jpg',
                buttons: [
                  { title: 'Button 2', action: 'https://example.com/2' },
                ],
              },
            ],
          },
        },
      };

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

      expect(screen.getByText('Card 1 text')).toBeTruthy();
      expect(screen.getByText('Card 2 text')).toBeTruthy();
      expect(screen.getByText('Button 1')).toBeTruthy();
      expect(screen.getByText('Button 2')).toBeTruthy();
    });

    it('should not render empty carousel button placeholder', () => {
      const props = {
        ...defaultProps,
        content: {
          viberPreviewContent: {
            type: 'CAROUSEL',
            cards: [
              {
                text: 'Card 1 text',
                mediaUrl: 'https://image.url/card1.jpg',
                buttons: [
                  { title: '', action: 'https://example.com/1' },
                  { title: '   ', action: 'https://example.com/2' },
                ],
              },
            ],
          },
        },
      };

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

      expect(container.querySelector('.viber-carousel-preview-button')).toBeNull();
    });

    it('should show carousel shell when showCarouselEditorPreview is true even if cards are empty', () => {
      const props = {
        ...defaultProps,
        content: {
          viberPreviewContent: {
            type: 'CAROUSEL',
            showCarouselEditorPreview: true,
            cards: [
              { text: '', mediaUrl: '', buttons: [{ title: '', action: '' }] },
              { text: '', mediaUrl: '', buttons: [{ title: '', action: '' }] },
            ],
          },
        },
      };

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

      expect(screen.queryByText('No content available')).toBeNull();
      expect(container.querySelector('.viber-carousel-preview-scroll')).toBeTruthy();
      expect(container.querySelector('.viber-carousel-message-box-placeholder')).toBeTruthy();
    });

    it('should render carousel message text in message box when type is CAROUSEL', () => {
      const props = {
        ...defaultProps,
        content: {
          viberPreviewContent: {
            type: 'CAROUSEL',
            messageContent: 'Carousel intro copy',
            cards: [
              {
                text: 'Card text',
                mediaUrl: 'https://image.url/c.jpg',
                buttons: [{ title: 'Go', action: 'https://example.com' }],
              },
            ],
          },
        },
      };

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

      expect(container.querySelector('.viber-carousel-message-box-text')).toHaveTextContent('Carousel intro copy');
      expect(screen.queryByText('Carousel intro copy')).toBeTruthy();
    });

    it('should hide account icon when carousel is shown', () => {
      const props = {
        ...defaultProps,
        content: {
          viberPreviewContent: {
            type: 'CAROUSEL',
            cards: [
              {
                text: 'Carousel card line',
                mediaUrl: '',
                buttons: [{ title: 'Open link', action: 'https://x.com' }],
              },
            ],
          },
        },
      };

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

      expect(container.querySelector('.viber-account-icon')).toBeNull();
    });

    it('should use image placeholder when carousel card mediaUrl is whitespace only', () => {
      const props = {
        ...defaultProps,
        content: {
          viberPreviewContent: {
            type: 'CAROUSEL',
            cards: [
              {
                text: 'Only text',
                mediaUrl: '   ',
                buttons: [{ title: 'Btn', action: 'https://example.com' }],
              },
            ],
          },
        },
      };

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

      expect(container.querySelector('.viber-carousel-preview-image-placeholder')).toBeTruthy();
      expect(container.querySelector('.viber-carousel-preview-image')).toBeNull();
    });

    it('should render at most two carousel buttons per card', () => {
      const props = {
        ...defaultProps,
        content: {
          viberPreviewContent: {
            type: 'CAROUSEL',
            cards: [
              {
                text: 'Card',
                mediaUrl: 'https://image.url/c.jpg',
                buttons: [
                  { title: 'One', action: 'https://a.com' },
                  { title: 'Two', action: 'https://b.com' },
                  { title: 'Three', action: 'https://c.com' },
                ],
              },
            ],
          },
        },
      };

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

      expect(container.querySelectorAll('.viber-carousel-preview-button')).toHaveLength(2);
      expect(screen.getByText('One')).toBeTruthy();
      expect(screen.getByText('Two')).toBeTruthy();
      expect(screen.queryByText('Three')).toBeNull();
    });

    it('should apply secondary class to second carousel button', () => {
      const props = {
        ...defaultProps,
        content: {
          viberPreviewContent: {
            type: 'CAROUSEL',
            cards: [
              {
                text: 'Card',
                mediaUrl: 'https://image.url/c.jpg',
                buttons: [
                  { title: 'Primary', action: 'https://a.com' },
                  { title: 'Secondary', action: 'https://b.com' },
                ],
              },
            ],
          },
        },
      };

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

      const buttons = container.querySelectorAll('.viber-carousel-preview-button');
      expect(buttons[0].className).toContain('viber-carousel-preview-button');
      expect(buttons[0].className).not.toContain('viber-carousel-preview-button-secondary');
      expect(buttons[1].className).toContain('viber-carousel-preview-button-secondary');
    });

    it('should show carousel when only a button title is present on a card', () => {
      const props = {
        ...defaultProps,
        content: {
          viberPreviewContent: {
            type: 'CAROUSEL',
            cards: [
              {
                text: '',
                mediaUrl: '',
                buttons: [{ title: 'Tap me', action: 'https://example.com' }],
              },
            ],
          },
        },
      };

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

      expect(screen.getByText('Tap me')).toBeTruthy();
      expect(screen.queryByText('No content available')).toBeNull();
    });

    it('should show one placeholder card when editor preview and cards array is empty', () => {
      const props = {
        ...defaultProps,
        content: {
          viberPreviewContent: {
            type: 'CAROUSEL',
            showCarouselEditorPreview: true,
            cards: [],
          },
        },
      };

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

      expect(container.querySelectorAll('.viber-carousel-preview-card')).toHaveLength(1);
    });

    it('should show no content when CAROUSEL has empty cards and no editor preview flag', () => {
      const props = {
        ...defaultProps,
        content: {
          viberPreviewContent: {
            type: 'CAROUSEL',
            cards: [],
          },
        },
      };

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

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

  describe('Account and Brand Name', () => {
    it('should use brandName when provided', () => {
      const props = {
        ...defaultProps,
        brandName: 'My Brand',
        accountName: 'My Account',
      };

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

      expect(screen.getByText('My Brand')).toBeTruthy();
    });

    it('should use accountName as fallback when brandName is not provided', () => {
      const props = {
        ...defaultProps,
        brandName: null,
        accountName: 'My Account',
      };

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

      expect(screen.getByText('My Account')).toBeTruthy();
    });

    it('should use default "Viber" when neither is provided', () => {
      const props = {
        ...defaultProps,
        brandName: null,
        accountName: null,
      };

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

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

    it('should use first letter of account/brand name for icon', () => {
      const props = {
        ...defaultProps,
        brandName: 'Brand',
      };

      const { container } = render(
        <TestWrapper>
          <ComponentToRender {...props} />
        </TestWrapper>
      );
      expect(container.querySelector('.viber-account-icon')).toHaveTextContent('V');
    });

    it('should use "V" as default icon when no account/brand name', () => {
      const props = {
        ...defaultProps,
        brandName: null,
        accountName: null,
      };

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

      expect(container.querySelector('.viber-account-icon')).toHaveTextContent('V');
    });
  });

  describe('Device Handling', () => {
    it('should apply Android-specific classes for ANDROID device', () => {
      const props = {
        ...defaultProps,
        device: ANDROID,
        showHeader: false,
      };

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

      expect(container.querySelector('.viber-content-overlay')).toBeTruthy();
      expect(container.querySelector('.viber-navigation-bar')).toBeTruthy();
    });

    it('should apply iOS-specific classes for IOS device', () => {
      const props = {
        ...defaultProps,
        device: IOS,
      };

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

      expect(container.querySelector('.viber-message-container-ios')).toBeTruthy();
    });
  });

  describe('Timestamp', () => {
    it('should display timestamp', () => {
      render(
        <TestWrapper>
          <ComponentToRender {...defaultProps} />
        </TestWrapper>
      );

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

  describe('No Content State', () => {
    it('should render no content message when hasContent is false', () => {
      const props = {
        ...defaultProps,
        content: {
          viberPreviewContent: {
            messageContent: '',
            imageURL: '',
            videoParams: {},
            buttonText: '',
          },
        },
      };

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

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

  describe('Edge Cases', () => {
    it('should handle content with only messageContent', () => {
      const props = {
        ...defaultProps,
        content: {
          viberPreviewContent: {
            messageContent: 'Text only',
          },
        },
      };

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

      expect(screen.getByText('Text only')).toBeTruthy();
    });

    it('should handle content with only image', () => {
      const props = {
        ...defaultProps,
        content: {
          viberPreviewContent: {
            imageURL: 'https://image.url',
          },
        },
      };

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

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

    it('should handle content with only video', () => {
      const props = {
        ...defaultProps,
        content: {
          viberPreviewContent: {
            videoParams: {
              viberVideoSrc: 'https://video.url',
            },
          },
        },
      };

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

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

    it('should handle content with only button', () => {
      const props = {
        ...defaultProps,
        content: {
          viberPreviewContent: {
            buttonText: 'Button Text',
          },
        },
      };

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

      expect(screen.getByText('Button Text')).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 empty content object', () => {
      const props = {
        ...defaultProps,
        content: {},
      };

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

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

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

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

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

  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();
    });
  });
});
