/**
 * Tests for PreviewHeader Component
 * 
 * Tests customer display, device toggle, and channel-specific behavior
 */

import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import '@testing-library/jest-dom';
import { injectIntl, IntlProvider } from 'react-intl';
import PreviewHeader from '../../UnifiedPreview/PreviewHeader';
import { CHANNELS, DESKTOP, MOBILE, ANDROID, IOS, ACTIVE } 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 }) => (
    <PreviewHeader {...props} formatMessage={intl.formatMessage} />
  ));

// Test wrapper - use IntlProvider with messages
const TestWrapper = ({ children }) => (
  <IntlProvider locale="en" messages={messagesForIntl}>
    {children}
  </IntlProvider>
);

describe('PreviewHeader', () => {
  const defaultProps = {
    selectedCustomer: {
      name: 'John Doe',
      email: 'john@example.com',
      mobile: '1234567890',
    },
    device: DESKTOP,
    showDeviceToggle: false,
    onDeviceChange: jest.fn(),
    channel: CHANNELS.EMAIL,
  };

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

  describe('Customer Display', () => {
    it('should display selected customer name', () => {
      render(
        <TestWrapper>
          <ComponentToRender {...defaultProps} />
        </TestWrapper>
      );

      expect(screen.getByText('Preview for')).toBeTruthy();
      expect(screen.getByText('John Doe')).toBeTruthy();
    });

    it('should display default preview when no customer selected', () => {
      const props = {
        ...defaultProps,
        selectedCustomer: null,
      };

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

      // Component uses FormattedMessage for "Default Preview"
      expect(screen.getByText(/Default Preview/i)).toBeTruthy();
    });

    it('should handle customer without name', () => {
      const props = {
        ...defaultProps,
        selectedCustomer: null,
      };

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

      // Component uses FormattedMessage for "Default Preview"
      expect(screen.getByText(/Default Preview/i)).toBeTruthy();
    });
  });

  describe('Device Toggle - Desktop/Mobile (Email, etc.)', () => {
    it('should show desktop/mobile toggle for EMAIL channel', () => {
      const props = {
        ...defaultProps,
        channel: CHANNELS.EMAIL,
        showDeviceToggle: true,
      };

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

      // Should have desktop and mobile icons
      const icons = document.querySelectorAll('.anticon');
      expect(icons.length).toBeGreaterThan(0);
    });

    it('should call onDeviceChange when desktop icon is clicked', () => {
      const props = {
        ...defaultProps,
        channel: CHANNELS.EMAIL,
        showDeviceToggle: true,
        device: MOBILE,
      };

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

      // Find and click desktop icon
      const desktopIcon = document.querySelector('[class*="desktop"]');
      if (desktopIcon) {
        fireEvent.click(desktopIcon);
        expect(props.onDeviceChange).toHaveBeenCalledWith(DESKTOP);
      }
    });

    it('should call onDeviceChange when mobile icon is clicked', () => {
      const props = {
        ...defaultProps,
        channel: CHANNELS.EMAIL,
        showDeviceToggle: true,
        device: DESKTOP,
      };

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

      // Find and click mobile icon
      const mobileIcon = document.querySelector('[class*="mobile"]');
      if (mobileIcon) {
        fireEvent.click(mobileIcon);
        expect(props.onDeviceChange).toHaveBeenCalledWith(MOBILE);
      }
    });

    it('should highlight active device (desktop)', () => {
      const props = {
        ...defaultProps,
        channel: CHANNELS.EMAIL,
        showDeviceToggle: true,
        device: DESKTOP,
      };

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

      // Desktop icon should have active class
      const desktopIcon = container.querySelector(`.${ACTIVE}`);
      expect(desktopIcon || container.querySelector('[class*="desktop"]')).toBeTruthy();
    });

    it('should highlight active device (mobile)', () => {
      const props = {
        ...defaultProps,
        channel: CHANNELS.EMAIL,
        showDeviceToggle: true,
        device: MOBILE,
      };

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

      // Mobile icon should have active class
      const mobileIcon = container.querySelector(`.${ACTIVE}`);
      expect(mobileIcon || container.querySelector('[class*="mobile"]')).toBeTruthy();
    });
  });

  describe('Device Toggle - Android/iOS (SMS, WhatsApp, etc.)', () => {
    it('should show android/ios toggle for SMS channel', () => {
      const props = {
        ...defaultProps,
        channel: CHANNELS.SMS,
        showDeviceToggle: true,
      };

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

      // Should have android and ios icons
      const icons = document.querySelectorAll('.anticon');
      expect(icons.length).toBeGreaterThan(0);
    });

    it('should show android/ios toggle for WHATSAPP channel', () => {
      const props = {
        ...defaultProps,
        channel: CHANNELS.WHATSAPP,
        showDeviceToggle: true,
      };

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

      const icons = document.querySelectorAll('.anticon');
      expect(icons.length).toBeGreaterThan(0);
    });

    it('should show android/ios toggle for RCS channel', () => {
      const props = {
        ...defaultProps,
        channel: CHANNELS.RCS,
        showDeviceToggle: true,
      };

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

      const icons = document.querySelectorAll('.anticon');
      expect(icons.length).toBeGreaterThan(0);
    });

    it('should show android/ios toggle for INAPP channel', () => {
      const props = {
        ...defaultProps,
        channel: CHANNELS.INAPP,
        showDeviceToggle: true,
      };

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

      const icons = document.querySelectorAll('.anticon');
      expect(icons.length).toBeGreaterThan(0);
    });

    it('should show android/ios toggle for MOBILEPUSH channel', () => {
      const props = {
        ...defaultProps,
        channel: CHANNELS.MOBILEPUSH,
        showDeviceToggle: true,
      };

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

      const icons = document.querySelectorAll('.anticon');
      expect(icons.length).toBeGreaterThan(0);
    });

    it('should show android/ios toggle for VIBER channel', () => {
      const props = {
        ...defaultProps,
        channel: CHANNELS.VIBER,
        showDeviceToggle: true,
      };

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

      const icons = document.querySelectorAll('.anticon');
      expect(icons.length).toBeGreaterThan(0);
    });

    it('should call onDeviceChange when android icon is clicked', () => {
      const props = {
        ...defaultProps,
        channel: CHANNELS.SMS,
        showDeviceToggle: true,
        device: IOS,
      };

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

      const androidIcon = document.querySelector('[class*="android"]');
      if (androidIcon) {
        fireEvent.click(androidIcon);
        expect(props.onDeviceChange).toHaveBeenCalledWith(ANDROID);
      }
    });

    it('should call onDeviceChange when ios icon is clicked', () => {
      const props = {
        ...defaultProps,
        channel: CHANNELS.SMS,
        showDeviceToggle: true,
        device: ANDROID,
      };

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

      const iosIcon = document.querySelector('[class*="ios"]');
      if (iosIcon) {
        fireEvent.click(iosIcon);
        expect(props.onDeviceChange).toHaveBeenCalledWith(IOS);
      }
    });

    it('should highlight active device (android)', () => {
      const props = {
        ...defaultProps,
        channel: CHANNELS.SMS,
        showDeviceToggle: true,
        device: ANDROID,
      };

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

      const androidIcon = container.querySelector(`.${ACTIVE}`);
      expect(androidIcon || container.querySelector('[class*="android"]')).toBeTruthy();
    });

    it('should highlight active device (ios)', () => {
      const props = {
        ...defaultProps,
        channel: CHANNELS.SMS,
        showDeviceToggle: true,
        device: IOS,
      };

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

      const iosIcon = container.querySelector(`.${ACTIVE}`);
      expect(iosIcon || container.querySelector('[class*="ios"]')).toBeTruthy();
    });
  });

  describe('Device Toggle Visibility', () => {
    it('should not show device toggle when showDeviceToggle is false', () => {
      const props = {
        ...defaultProps,
        showDeviceToggle: false,
      };

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

      const deviceToggle = container.querySelector('.device-toggle');
      expect(deviceToggle).toBeFalsy();
    });

    it('should show device toggle when showDeviceToggle is true', () => {
      const props = {
        ...defaultProps,
        showDeviceToggle: true,
      };

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

      const deviceToggle = container.querySelector('.device-toggle');
      expect(deviceToggle).toBeTruthy();
    });
  });

  describe('Edge Cases', () => {
    it('should handle undefined selectedCustomer', () => {
      const props = {
        ...defaultProps,
        selectedCustomer: undefined,
      };

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

      // Component uses FormattedMessage for "Default Preview"
      expect(screen.getByText(/Default Preview/i)).toBeTruthy();
    });

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

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

      // Should not crash
      expect(screen.getByText('Preview for')).toBeTruthy();
    });

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

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

      // Should default to desktop/mobile toggle
      expect(screen.getByText('Preview for')).toBeTruthy();
    });

    it('should handle all channel types', () => {
      const channels = Object.values(CHANNELS);

      channels.forEach((channel) => {
        const { unmount } = render(
          <TestWrapper>
            <PreviewHeader
              {...defaultProps}
              channel={channel}
              showDeviceToggle={true}
            />
          </TestWrapper>
        );
        expect(screen.getByText('Preview for')).toBeTruthy();
        unmount();
      });
    });
  });

  describe('Default Props', () => {
    it('should use default props when not provided', () => {
      const minimalProps = {
        channel: CHANNELS.EMAIL,
      };

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

      // Component uses FormattedMessage for "Default Preview"
      expect(screen.getByText(/Default Preview/i)).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();
    });
  });

  describe('WEBPUSH channel - Fullscreen expander', () => {
    it('should render expander icon for WEBPUSH channel', () => {
      const setIsFullscreenOpen = jest.fn();
      const props = {
        ...defaultProps,
        channel: CHANNELS.WEBPUSH,
        setIsFullscreenOpen,
      };

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

      // expander icon should be present for WEBPUSH
      const expanderIcon = container.querySelector('[class*="expander"], [aria-label*="expander"], .anticon');
      expect(expanderIcon).toBeTruthy();
    });

    it('should NOT render expander icon for non-WEBPUSH channels', () => {
      const setIsFullscreenOpen = jest.fn();
      const props = {
        ...defaultProps,
        channel: CHANNELS.EMAIL,
        setIsFullscreenOpen,
        showDeviceToggle: false,
      };

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

      // No expander icon for EMAIL channel (only device toggle icons may appear)
      const expanderIcon = container.querySelector('[class*="expander"]');
      expect(expanderIcon).toBeNull();
    });

    it('should call setIsFullscreenOpen(true) when expander icon is clicked', () => {
      const setIsFullscreenOpen = jest.fn();
      const props = {
        ...defaultProps,
        channel: CHANNELS.WEBPUSH,
        setIsFullscreenOpen,
      };

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

      const expanderIcon = container.querySelector('[class*="expander"]') ||
        container.querySelector('.anticon');
      if (expanderIcon) {
        fireEvent.click(expanderIcon);
        expect(setIsFullscreenOpen).toHaveBeenCalledWith(true);
      }
    });

    it('should render expander icon without ACTIVE class when device is MOBILE', () => {
      const setIsFullscreenOpen = jest.fn();
      const props = {
        ...defaultProps,
        channel: CHANNELS.WEBPUSH,
        device: MOBILE,
        setIsFullscreenOpen,
      };

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

      // Expander icon no longer adds ACTIVE class based on device
      const activeEl = container.querySelector('.active');
      expect(activeEl).toBeNull();
      // But the expander icon itself should still be present
      const expanderIcon = container.querySelector('[class*="expander"]') ||
        container.querySelector('.anticon');
      expect(expanderIcon).toBeTruthy();
    });

    it('should render expander icon without ACTIVE class when device is DESKTOP', () => {
      const setIsFullscreenOpen = jest.fn();
      const props = {
        ...defaultProps,
        channel: CHANNELS.WEBPUSH,
        device: DESKTOP,
        setIsFullscreenOpen,
      };

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

      // Expander icon does not have ACTIVE class for any device
      const activeEl = container.querySelector('.active');
      expect(activeEl).toBeNull();
    });

    it('should render expander icon alongside device content for WEBPUSH', () => {
      // Note: suppression of showDeviceToggle for WEBPUSH is done in UnifiedPreview (parent),
      // not in PreviewHeader itself. PreviewHeader only adds the expander icon for WEBPUSH.
      const setIsFullscreenOpen = jest.fn();
      const props = {
        ...defaultProps,
        channel: CHANNELS.WEBPUSH,
        setIsFullscreenOpen,
        showDeviceToggle: false,
      };

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

      // expander icon should be present for WEBPUSH
      const expanderIcon = container.querySelector('[class*="expander"]') ||
        container.querySelector('.anticon');
      expect(expanderIcon).toBeTruthy();
    });

    it('should accept isFullscreenOpen and setIsFullscreenOpen as props', () => {
      const setIsFullscreenOpen = jest.fn();
      const props = {
        ...defaultProps,
        channel: CHANNELS.WEBPUSH,
        isFullscreenOpen: false,
        setIsFullscreenOpen,
      };

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

    it('should use default setIsFullscreenOpen when not provided', () => {
      const props = {
        ...defaultProps,
        channel: CHANNELS.WEBPUSH,
      };

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