/**
 * Tests for WebPushPreviewContent Component
 *
 * Covers: OS/browser state, fullscreen modal, isUpdating/error early-returns,
 * handleOSChange, handleBrowserChange, handleCloseFullscreen, browser coercion effect.
 */

import React from 'react';
import { render, screen, fireEvent, act } from '@testing-library/react';
import '@testing-library/jest-dom';
import { IntlProvider } from 'react-intl';
import WebPushPreviewContent from '../../UnifiedPreview/WebPushPreviewContent';
import messages from '../../messages';

const messagesForIntl = Object.keys(messages).reduce((acc, key) => {
  const msg = messages[key];
  acc[msg.id] = msg.defaultMessage;
  return acc;
}, {});

const TestWrapper = ({ children }) => (
  <IntlProvider locale="en" messages={messagesForIntl}>
    {children}
  </IntlProvider>
);

// Mock heavy child components
jest.mock('../../../../v2Containers/WebPush/Create/preview/PreviewControls', () => ({
  __esModule: true,
  default: (props) => (
    <div data-testid="preview-controls">
      <button
        data-testid="os-change-btn"
        onClick={() => props.onOSChange('Windows')}
      >
        Change OS
      </button>
      <button
        data-testid="browser-change-btn"
        onClick={() => props.onBrowserChange('Firefox')}
      >
        Change Browser
      </button>
      <div data-testid="selected-os">{props.selectedOS}</div>
      <div data-testid="selected-browser">{props.selectedBrowser}</div>
      <div data-testid="browser-options">{JSON.stringify(props.browserOptions)}</div>
    </div>
  ),
}));

jest.mock('../../../../v2Containers/WebPush/Create/preview/PreviewContent', () => ({
  __esModule: true,
  default: (props) => (
    <div data-testid="preview-content">
      <div data-testid="content-title">{props.notificationTitle}</div>
      <div data-testid="content-body">{props.notificationBody}</div>
      <div data-testid="content-url">{props.url}</div>
      <div data-testid="content-os">{props.selectedOS}</div>
      <div data-testid="content-browser">{props.selectedBrowser}</div>
      <div data-testid="content-image">{props.imageSrc}</div>
      <div data-testid="content-icon">{props.brandIconSrc}</div>
      <div data-testid="content-buttons">{JSON.stringify(props.buttons)}</div>
    </div>
  ),
}));

jest.mock('../../../../v2Containers/WebPush/Create/preview/DevicePreviewContent', () => ({
  __esModule: true,
  default: (props) => (
    <div data-testid="device-preview-content">
      <div data-testid="device-title">{props.notificationTitle}</div>
      <div data-testid="device-body">{props.notificationBody}</div>
      <div data-testid="device-image">{props.imageSrc}</div>
      <div data-testid="device-icon">{props.brandIconSrc}</div>
    </div>
  ),
}));

// Mock CapModal to render children when visible
jest.mock('@capillarytech/cap-ui-library/CapModal', () => ({
  __esModule: true,
  default: ({ visible, children, onCancel }) => (
    <div data-testid="cap-modal" data-visible={visible ? 'true' : 'false'}>
      {visible && <div data-testid="modal-content">{children}</div>}
      <button data-testid="modal-cancel" onClick={onCancel}>Cancel</button>
    </div>
  ),
}));

jest.mock('@capillarytech/cap-ui-library/CapRow', () => ({
  __esModule: true,
  default: ({ children, className }) => <div className={className}>{children}</div>,
}));

jest.mock('@capillarytech/cap-ui-library/CapLabel', () => ({
  __esModule: true,
  default: ({ children }) => <span>{children}</span>,
}));

jest.mock('@capillarytech/cap-ui-library/CapIcon', () => ({
  __esModule: true,
  default: ({ type, onClick, className }) => (
    <span
      data-testid={`cap-icon-${type}`}
      className={className}
      onClick={onClick}
    />
  ),
}));

jest.mock('@capillarytech/cap-ui-library/CapDivider', () => ({
  __esModule: true,
  default: () => <hr data-testid="cap-divider" />,
}));

const defaultProps = {
  notificationTitle: 'Test Title',
  notificationBody: 'Test body text',
  imageSrc: 'https://example.com/image.jpg',
  brandIconSrc: 'https://example.com/icon.png',
  buttons: [{ text: 'Click', url: 'https://example.com', type: 'EXTERNAL_URL' }],
  url: 'https://example.com',
  isUpdating: false,
  error: null,
  isFullscreenOpen: false,
  setIsFullscreenOpen: jest.fn(),
  selectedCustomer: null,
};

describe('WebPushPreviewContent', () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  describe('Early-return guards', () => {
    it('should return null when isUpdating is true', () => {
      const { container } = render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} isUpdating={true} />
        </TestWrapper>
      );
      expect(container.firstChild).toBeNull();
    });

    it('should return null when error is truthy', () => {
      const { container } = render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} error="Something went wrong" />
        </TestWrapper>
      );
      expect(container.firstChild).toBeNull();
    });

    it('should render normally when isUpdating is false and error is null', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} />
        </TestWrapper>
      );
      expect(screen.getByTestId('preview-controls')).toBeTruthy();
      expect(screen.getByTestId('preview-content')).toBeTruthy();
    });
  });

  describe('Initial OS and browser state', () => {
    it('should render with default OS (macOS)', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} />
        </TestWrapper>
      );
      expect(screen.getByTestId('selected-os')).toHaveTextContent('macOS');
    });

    it('should render with default browser (Chrome)', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} />
        </TestWrapper>
      );
      expect(screen.getByTestId('selected-browser')).toHaveTextContent('Chrome');
    });

    it('should pass default OS to PreviewContent', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} />
        </TestWrapper>
      );
      expect(screen.getByTestId('content-os')).toHaveTextContent('macOS');
    });

    it('should pass default browser to PreviewContent', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} />
        </TestWrapper>
      );
      expect(screen.getByTestId('content-browser')).toHaveTextContent('Chrome');
    });
  });

  describe('Props forwarding to PreviewContent', () => {
    it('should pass notificationTitle to PreviewContent', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} />
        </TestWrapper>
      );
      expect(screen.getByTestId('content-title')).toHaveTextContent('Test Title');
    });

    it('should pass notificationBody to PreviewContent', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} />
        </TestWrapper>
      );
      expect(screen.getByTestId('content-body')).toHaveTextContent('Test body text');
    });

    it('should pass url to PreviewContent', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} />
        </TestWrapper>
      );
      expect(screen.getByTestId('content-url')).toHaveTextContent('https://example.com');
    });

    it('should pass imageSrc to PreviewContent', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} />
        </TestWrapper>
      );
      expect(screen.getByTestId('content-image')).toHaveTextContent('https://example.com/image.jpg');
    });

    it('should pass brandIconSrc to PreviewContent', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} />
        </TestWrapper>
      );
      expect(screen.getByTestId('content-icon')).toHaveTextContent('https://example.com/icon.png');
    });

    it('should pass buttons to PreviewContent', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} />
        </TestWrapper>
      );
      const buttons = JSON.parse(screen.getByTestId('content-buttons').textContent);
      expect(buttons).toHaveLength(1);
      expect(buttons[0]).toEqual({ text: 'Click', url: 'https://example.com', type: 'EXTERNAL_URL' });
    });
  });

  describe('OS and browser change handlers', () => {
    it('should update selected OS when handleOSChange is called', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} />
        </TestWrapper>
      );

      fireEvent.click(screen.getByTestId('os-change-btn'));
      expect(screen.getByTestId('selected-os')).toHaveTextContent('Windows');
    });

    it('should update selected browser when handleBrowserChange is called', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} />
        </TestWrapper>
      );

      fireEvent.click(screen.getByTestId('browser-change-btn'));
      expect(screen.getByTestId('selected-browser')).toHaveTextContent('Firefox');
    });

    it('should pass updated OS to PreviewContent after OS change', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} />
        </TestWrapper>
      );

      fireEvent.click(screen.getByTestId('os-change-btn'));
      expect(screen.getByTestId('content-os')).toHaveTextContent('Windows');
    });
  });

  describe('Browser coercion on OS change', () => {
    it('should keep Chrome when switching from macOS to Windows (Chrome is valid on both)', () => {
      // Chrome is supported on all OS platforms, so switching macOS → Windows should NOT coerce.
      render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} />
        </TestWrapper>
      );

      expect(screen.getByTestId('selected-browser')).toHaveTextContent('Chrome');
      fireEvent.click(screen.getByTestId('os-change-btn')); // sets OS to Windows
      // Chrome is still valid on Windows, so browser stays Chrome (no coercion)
      expect(screen.getByTestId('selected-browser')).toHaveTextContent('Chrome');
    });

    it('should update OS state when OS is changed', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} />
        </TestWrapper>
      );

      fireEvent.click(screen.getByTestId('os-change-btn')); // sets OS to Windows
      expect(screen.getByTestId('selected-os')).toHaveTextContent('Windows');
    });

    it('should allow explicit browser change independent of OS', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} />
        </TestWrapper>
      );

      fireEvent.click(screen.getByTestId('browser-change-btn')); // sets browser to Firefox
      expect(screen.getByTestId('selected-browser')).toHaveTextContent('Firefox');
    });
  });

  describe('Fullscreen modal', () => {
    it('should NOT show modal when isFullscreenOpen is false', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} isFullscreenOpen={false} />
        </TestWrapper>
      );

      const modal = screen.getByTestId('cap-modal');
      expect(modal.getAttribute('data-visible')).toBe('false');
      expect(screen.queryByTestId('modal-content')).toBeNull();
    });

    it('should show modal when isFullscreenOpen is true', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} isFullscreenOpen={true} />
        </TestWrapper>
      );

      const modal = screen.getByTestId('cap-modal');
      expect(modal.getAttribute('data-visible')).toBe('true');
      expect(screen.getByTestId('modal-content')).toBeTruthy();
    });

    it('should render DevicePreviewContent inside modal', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} isFullscreenOpen={true} />
        </TestWrapper>
      );

      expect(screen.getByTestId('device-preview-content')).toBeTruthy();
    });

    it('should pass notificationTitle to DevicePreviewContent', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} isFullscreenOpen={true} />
        </TestWrapper>
      );

      expect(screen.getByTestId('device-title')).toHaveTextContent('Test Title');
    });

    it('should pass notificationBody to DevicePreviewContent', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} isFullscreenOpen={true} />
        </TestWrapper>
      );

      expect(screen.getByTestId('device-body')).toHaveTextContent('Test body text');
    });

    it('should call setIsFullscreenOpen(false) when close icon is clicked', () => {
      const setIsFullscreenOpen = jest.fn();
      render(
        <TestWrapper>
          <WebPushPreviewContent
            {...defaultProps}
            isFullscreenOpen={true}
            setIsFullscreenOpen={setIsFullscreenOpen}
          />
        </TestWrapper>
      );

      fireEvent.click(screen.getByTestId('cap-icon-collapse2'));
      expect(setIsFullscreenOpen).toHaveBeenCalledWith(false);
    });

    it('should call setIsFullscreenOpen(false) when modal onCancel fires', () => {
      const setIsFullscreenOpen = jest.fn();
      render(
        <TestWrapper>
          <WebPushPreviewContent
            {...defaultProps}
            isFullscreenOpen={true}
            setIsFullscreenOpen={setIsFullscreenOpen}
          />
        </TestWrapper>
      );

      fireEvent.click(screen.getByTestId('modal-cancel'));
      expect(setIsFullscreenOpen).toHaveBeenCalledWith(false);
    });

    it('should display selectedCustomer name in modal header when customer is provided', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent
            {...defaultProps}
            isFullscreenOpen={true}
            selectedCustomer={{ name: 'Alice' }}
          />
        </TestWrapper>
      );

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

    it('should display default preview text in modal header when no customer', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent
            {...defaultProps}
            isFullscreenOpen={true}
            selectedCustomer={null}
          />
        </TestWrapper>
      );

      // FormattedMessage renders defaultMessage for defaultPreview
      expect(screen.queryByText('Alice')).toBeNull();
    });
  });

  describe('Default props', () => {
    it('should render with minimal props (title and body only)', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent
            notificationTitle="Min title"
            notificationBody="Min body"
          />
        </TestWrapper>
      );

      expect(screen.getByTestId('content-title')).toHaveTextContent('Min title');
      expect(screen.getByTestId('content-body')).toHaveTextContent('Min body');
    });

    it('should render with no props at all (all defaults)', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent />
        </TestWrapper>
      );

      expect(screen.getByTestId('preview-controls')).toBeTruthy();
    });

    it('should render empty buttons array by default', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent notificationTitle="T" notificationBody="B" />
        </TestWrapper>
      );

      const buttons = JSON.parse(screen.getByTestId('content-buttons').textContent);
      expect(buttons).toEqual([]);
    });
  });

  describe('PreviewControls props', () => {
    it('should pass OS_OPTIONS to PreviewControls', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} />
        </TestWrapper>
      );
      // PreviewControls is rendered
      expect(screen.getByTestId('preview-controls')).toBeTruthy();
    });

    it('should pass browserOptions derived from selectedOS to PreviewControls', () => {
      render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} />
        </TestWrapper>
      );

      // macOS supports all browsers including Safari
      const browserOptions = JSON.parse(screen.getByTestId('browser-options').textContent);
      expect(Array.isArray(browserOptions)).toBe(true);
      expect(browserOptions.length).toBeGreaterThan(0);
    });

    it('should pass layoutMode="newRow" to PreviewControls', () => {
      // PreviewControls mock just renders - verifying no crash when layoutMode is set
      render(
        <TestWrapper>
          <WebPushPreviewContent {...defaultProps} />
        </TestWrapper>
      );
      expect(screen.getByTestId('preview-controls')).toBeTruthy();
    });
  });
});
