/**
 * DeviceToggle Component Tests
 *
 * Tests for the DeviceToggle component used in InApp variant.
 */

import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import '@testing-library/jest-dom';
import { IntlProvider } from 'react-intl';
import DeviceToggle from '../index';
import { DEVICE_TYPES } from '../../../constants';

// Mock Cap UI components
jest.mock('@capillarytech/cap-ui-library/CapButton', () => {
  return function MockCapButton({ children, onClick, className, type }) {
    return (
      <button
        onClick={onClick}
        className={className}
        data-type={type}
        data-testid="cap-button"
      >
        {children}
      </button>
    );
  };
});

jest.mock('@capillarytech/cap-ui-library/CapCheckbox', () => {
  return function MockCapCheckbox({ children, checked, onChange, className }) {
    return (
      <label className={className}>
        <input
          type="checkbox"
          checked={checked}
          onChange={onChange}
          data-testid="cap-checkbox"
        />
        {children}
      </label>
    );
  };
});

jest.mock('@capillarytech/cap-ui-library/CapIcon', () => {
  return function MockCapIcon({ type, size }) {
    return <span data-testid="cap-icon" data-type={type} data-size={size} />;
  };
});

// Test messages
const messages = {
  android: { id: 'android', defaultMessage: 'Android' },
  ios: { id: 'ios', defaultMessage: 'iOS' },
  keepContentSameForBoth: { id: 'keepSame', defaultMessage: 'Keep content same for both' }
};

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

describe('DeviceToggle', () => {
  const defaultProps = {
    activeDevice: DEVICE_TYPES.ANDROID,
    onDeviceChange: jest.fn(),
    keepContentSame: false,
    onKeepContentSameChange: jest.fn()
  };

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

  it('renders with default props', () => {
    render(
      <TestWrapper>
        <DeviceToggle {...defaultProps} />
      </TestWrapper>
    );

    expect(screen.getByText('Android')).toBeInTheDocument();
    expect(screen.getByText('iOS')).toBeInTheDocument();
    expect(screen.getByText('Keep content same for both')).toBeInTheDocument();
  });

  it('shows Android as active by default', () => {
    render(
      <TestWrapper>
        <DeviceToggle {...defaultProps} />
      </TestWrapper>
    );

    const buttons = screen.getAllByTestId('cap-button');
    const androidButton = buttons.find(btn => btn.textContent.includes('Android'));
    const iosButton = buttons.find(btn => btn.textContent.includes('iOS'));

    expect(androidButton).toHaveAttribute('data-type', 'primary');
    expect(iosButton).toHaveAttribute('data-type', 'default');
  });

  it('shows iOS as active when specified', () => {
    render(
      <TestWrapper>
        <DeviceToggle {...defaultProps} activeDevice={DEVICE_TYPES.IOS} />
      </TestWrapper>
    );

    const buttons = screen.getAllByTestId('cap-button');
    const androidButton = buttons.find(btn => btn.textContent.includes('Android'));
    const iosButton = buttons.find(btn => btn.textContent.includes('iOS'));

    expect(androidButton).toHaveAttribute('data-type', 'default');
    expect(iosButton).toHaveAttribute('data-type', 'primary');
  });

  it('calls onDeviceChange when Android button is clicked', () => {
    const onDeviceChange = jest.fn();

    render(
      <TestWrapper>
        <DeviceToggle
          {...defaultProps}
          activeDevice={DEVICE_TYPES.IOS}
          onDeviceChange={onDeviceChange}
        />
      </TestWrapper>
    );

    const buttons = screen.getAllByTestId('cap-button');
    const androidButton = buttons.find(btn => btn.textContent.includes('Android'));

    fireEvent.click(androidButton);

    expect(onDeviceChange).toHaveBeenCalledWith(DEVICE_TYPES.ANDROID);
  });

  it('calls onDeviceChange when iOS button is clicked', () => {
    const onDeviceChange = jest.fn();

    render(
      <TestWrapper>
        <DeviceToggle
          {...defaultProps}
          activeDevice={DEVICE_TYPES.ANDROID}
          onDeviceChange={onDeviceChange}
        />
      </TestWrapper>
    );

    const buttons = screen.getAllByTestId('cap-button');
    const iosButton = buttons.find(btn => btn.textContent.includes('iOS'));

    fireEvent.click(iosButton);

    expect(onDeviceChange).toHaveBeenCalledWith(DEVICE_TYPES.IOS);
  });

  it('does not call onDeviceChange when clicking already active device', () => {
    const onDeviceChange = jest.fn();

    render(
      <TestWrapper>
        <DeviceToggle
          {...defaultProps}
          activeDevice={DEVICE_TYPES.ANDROID}
          onDeviceChange={onDeviceChange}
        />
      </TestWrapper>
    );

    const buttons = screen.getAllByTestId('cap-button');
    const androidButton = buttons.find(btn => btn.textContent.includes('Android'));

    fireEvent.click(androidButton);

    expect(onDeviceChange).not.toHaveBeenCalled();
  });

  it('renders checkbox in checked state when keepContentSame is true', () => {
    render(
      <TestWrapper>
        <DeviceToggle {...defaultProps} keepContentSame={true} />
      </TestWrapper>
    );

    const checkbox = screen.getByTestId('cap-checkbox');
    expect(checkbox).toBeChecked();
  });

  it('renders checkbox in unchecked state when keepContentSame is false', () => {
    render(
      <TestWrapper>
        <DeviceToggle {...defaultProps} keepContentSame={false} />
      </TestWrapper>
    );

    const checkbox = screen.getByTestId('cap-checkbox');
    expect(checkbox).not.toBeChecked();
  });

  it('calls onKeepContentSameChange when checkbox is clicked', () => {
    const onKeepContentSameChange = jest.fn();

    render(
      <TestWrapper>
        <DeviceToggle
          {...defaultProps}
          onKeepContentSameChange={onKeepContentSameChange}
        />
      </TestWrapper>
    );

    const checkbox = screen.getByTestId('cap-checkbox');
    fireEvent.click(checkbox);

    expect(onKeepContentSameChange).toHaveBeenCalledWith(true);
  });

  it('handles checkbox change with boolean value', () => {
    const onKeepContentSameChange = jest.fn();

    render(
      <TestWrapper>
        <DeviceToggle
          {...defaultProps}
          keepContentSame={true}
          onKeepContentSameChange={onKeepContentSameChange}
        />
      </TestWrapper>
    );

    const checkbox = screen.getByTestId('cap-checkbox');

    // Simulate direct boolean value (as might come from Cap UI)
    fireEvent.click(checkbox);

    expect(onKeepContentSameChange).toHaveBeenCalledWith(false);
  });

  it('renders device icons correctly', () => {
    render(
      <TestWrapper>
        <DeviceToggle {...defaultProps} />
      </TestWrapper>
    );

    const icons = screen.getAllByTestId('cap-icon');
    expect(icons).toHaveLength(2);

    expect(icons[0]).toHaveAttribute('data-type', 'android');
    expect(icons[1]).toHaveAttribute('data-type', 'ios');
  });

  it('applies custom className', () => {
    const { container } = render(
      <TestWrapper>
        <DeviceToggle {...defaultProps} className="custom-class" />
      </TestWrapper>
    );

    expect(container.firstChild).toHaveClass('device-toggle', 'custom-class');
  });

  it('handles missing callback functions gracefully', () => {
    render(
      <TestWrapper>
        <DeviceToggle
          activeDevice={DEVICE_TYPES.ANDROID}
          keepContentSame={false}
        />
      </TestWrapper>
    );

    const buttons = screen.getAllByTestId('cap-button');
    const iosButton = buttons.find(btn => btn.textContent.includes('iOS'));
    const checkbox = screen.getByTestId('cap-checkbox');

    // Should not throw errors
    fireEvent.click(iosButton);
    fireEvent.change(checkbox, { target: { checked: true } });

    expect(screen.getByText('iOS')).toBeInTheDocument();
  });

  it('renders with proper ARIA attributes', () => {
    render(
      <TestWrapper>
        <DeviceToggle {...defaultProps} />
      </TestWrapper>
    );

    const deviceToggle = screen.getByText('Android').closest('.device-toggle');
    expect(deviceToggle).toBeInTheDocument();
  });

  it('maintains proper tab order', () => {
    render(
      <TestWrapper>
        <DeviceToggle {...defaultProps} />
      </TestWrapper>
    );

    const buttons = screen.getAllByTestId('cap-button');
    const checkbox = screen.getByTestId('cap-checkbox');

    // All interactive elements should be in the DOM
    expect(buttons).toHaveLength(2);
    expect(checkbox).toBeInTheDocument();
  });
});

