import React from 'react';
import { mountWithIntl, shallowWithIntl } from '../../../../helpers/intl-enzym-test-helpers';
import ButtonsLinksSection from './ButtonsLinksSection';
import CapRow from '@capillarytech/cap-ui-library/CapRow';
import CapHeading from '@capillarytech/cap-ui-library/CapHeading';
import CapRadioGroup from '@capillarytech/cap-ui-library/CapRadioGroup';
import CapInput from '@capillarytech/cap-ui-library/CapInput';
import CapButton from '@capillarytech/cap-ui-library/CapButton';
import { ON_CLICK_BEHAVIOUR_OPTIONS, WEBPUSH_BUTTON_TYPES } from '../../constants';

// Mock ButtonList
jest.mock('./ButtonList', () => {
  const React = require('react');
  return function MockButtonList(props) {
    return (
      <div data-testid="button-list" className="mock-button-list">
        <div>Buttons: {props.buttons?.length || 0}</div>
        <div>Disabled: {props.disabled ? 'true' : 'false'}</div>
        <div>DisableSecondary: {props.disableSecondaryButton ? 'true' : 'false'}</div>
        <div>IsInlineFormVisible: {props.isInlineFormVisible ? 'true' : 'false'}</div>
        {props.renderInlineForm && <div data-testid="inline-form">{props.renderInlineForm()}</div>}
      </div>
    );
  };
});

// Mock ButtonForm
jest.mock('./ButtonForm', () => {
  const React = require('react');
  return function MockButtonForm(props) {
    return (
      <div data-testid="button-form" className="mock-button-form">
        <div>ButtonType: {props.buttonType}</div>
        <div>IsEditMode: {props.isEditMode ? 'true' : 'false'}</div>
        <div>InitialData: {props.initialData ? JSON.stringify(props.initialData) : 'null'}</div>
        <button onClick={props.onSave} data-testid="button-form-save">
          Save
        </button>
        <button onClick={props.onCancel} data-testid="button-form-cancel">
          Cancel
        </button>
      </div>
    );
  };
});

describe('ButtonsLinksSection', () => {
  const mockFormatMessage = jest.fn((message) => message?.defaultMessage || message?.id || message);
  const mockOnClickBehaviourChange = jest.fn();
  const mockOnRedirectUrlChange = jest.fn();

  const mockMessages = {
    buttonsAndLinks: {
      id: 'app.webpush.buttonsAndLinks',
      defaultMessage: 'Buttons and Links',
    },
    onClickBehaviour: {
      id: 'app.webpush.onClickBehaviour',
      defaultMessage: 'On-click Behaviour',
    },
    enterUrl: {
      id: 'app.webpush.enterUrl',
      defaultMessage: 'Enter URL',
    },
    buttons: {
      id: 'app.webpush.buttons',
      defaultMessage: 'Buttons',
    },
    optional: {
      id: 'app.webpush.optional',
      defaultMessage: '(Optional)',
    },
    addButton: {
      id: 'app.webpush.addButton',
      defaultMessage: 'Add Button',
    },
  };

  const createMockButtonState = (overrides = {}) => ({
    buttons: [],
    isAddingButton: false,
    buttonBeingAdded: null,
    editingButtonIndex: null,
    handleAddPrimaryButton: jest.fn(),
    handleAddSecondaryButton: jest.fn(),
    handleButtonSave: jest.fn(),
    handleButtonCancel: jest.fn(),
    handleButtonEdit: jest.fn(),
    handleButtonDelete: jest.fn(),
    handleButtonReorder: jest.fn(),
    isAddFlow: false,
    isEditFlow: false,
    showAddPrimaryButton: false,
    showAddSecondaryButton: false,
    showDisabledSecondaryDuringPrimary: false,
    disableSecondaryAddButton: false,
    ...overrides,
  });

  const defaultProps = {
    onClickBehaviour: ON_CLICK_BEHAVIOUR_OPTIONS.SITE_URL,
    onClickBehaviourOptions: [
      { value: ON_CLICK_BEHAVIOUR_OPTIONS.SITE_URL, label: 'Open Site' },
      { value: ON_CLICK_BEHAVIOUR_OPTIONS.REDIRECT_TO_URL, label: 'Redirect to URL' },
    ],
    onClickBehaviourChange: mockOnClickBehaviourChange,
    redirectUrl: '',
    redirectUrlError: '',
    onRedirectUrlChange: mockOnRedirectUrlChange,
    buttonState: createMockButtonState(),
    formatMessage: mockFormatMessage,
    messages: mockMessages,
  };

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

  describe('Rendering', () => {
    it('should render correctly with default props', () => {
      const wrapper = shallowWithIntl(<ButtonsLinksSection {...defaultProps} />);
      expect(wrapper).toMatchSnapshot();
    });

    it('should render buttons and links section', () => {
      const wrapper = mountWithIntl(<ButtonsLinksSection {...defaultProps} />);
      const section = wrapper.find('.creatives-webpush-buttons-links');
      expect(section.exists()).toBe(true);
    });

    it('should render buttons section', () => {
      const wrapper = mountWithIntl(<ButtonsLinksSection {...defaultProps} />);
      const section = wrapper.find('.creatives-webpush-buttons-section');
      expect(section.exists()).toBe(true);
    });

    it('should render heading for buttons and links', () => {
      const wrapper = mountWithIntl(<ButtonsLinksSection {...defaultProps} />);
      const heading = wrapper.find(CapHeading).find('.webpush-buttons-links');
      expect(heading.exists()).toBe(true);
    });

    it('should render heading for on-click behaviour', () => {
      const wrapper = mountWithIntl(<ButtonsLinksSection {...defaultProps} />);
      const heading = wrapper.find(CapHeading).find('.webpush-on-click-behaviour');
      expect(heading.exists()).toBe(true);
    });

    it('should render CapRadioGroup with correct props', () => {
      const wrapper = mountWithIntl(<ButtonsLinksSection {...defaultProps} />);
      const radioGroup = wrapper.find(CapRadioGroup);
      expect(radioGroup.exists()).toBe(true);
      expect(radioGroup.prop('options')).toEqual(defaultProps.onClickBehaviourOptions);
      expect(radioGroup.prop('value')).toBe(ON_CLICK_BEHAVIOUR_OPTIONS.SITE_URL);
    });
  });

  describe('On-Click Behaviour', () => {
    it('should call onClickBehaviourChange when radio group changes', () => {
      const wrapper = mountWithIntl(<ButtonsLinksSection {...defaultProps} />);
      const radioGroup = wrapper.find(CapRadioGroup);
      radioGroup.prop('onChange')(ON_CLICK_BEHAVIOUR_OPTIONS.REDIRECT_TO_URL);
      expect(mockOnClickBehaviourChange).toHaveBeenCalledWith(ON_CLICK_BEHAVIOUR_OPTIONS.REDIRECT_TO_URL);
    });

    it('should render redirect URL input when REDIRECT_TO_URL is selected', () => {
      const wrapper = mountWithIntl(
        <ButtonsLinksSection
          {...defaultProps}
          onClickBehaviour={ON_CLICK_BEHAVIOUR_OPTIONS.REDIRECT_TO_URL}
          redirectUrl="https://example.com"
        />
      );
      const input = wrapper.find(CapInput).find('#webpush-redirect-url-input');
      expect(input.exists()).toBe(true);
    });

    it('should not render redirect URL input when SITE_URL is selected', () => {
      const wrapper = mountWithIntl(<ButtonsLinksSection {...defaultProps} />);
      const input = wrapper.find(CapInput).find('#webpush-redirect-url-input');
      expect(input.exists()).toBe(false);
    });

    it('should show error status when redirectUrlError is provided', () => {
      const wrapper = mountWithIntl(
        <ButtonsLinksSection
          {...defaultProps}
          onClickBehaviour={ON_CLICK_BEHAVIOUR_OPTIONS.REDIRECT_TO_URL}
          redirectUrlError="Invalid URL"
        />
      );
      const input = wrapper.find(CapInput).find('#webpush-redirect-url-input');
      expect(input.exists()).toBe(true);
    });

    it('should call onRedirectUrlChange when URL input changes', () => {
      const onRedirectUrlChangeMock = jest.fn();
      const wrapper = mountWithIntl(
        <ButtonsLinksSection
          {...defaultProps}
          onClickBehaviour={ON_CLICK_BEHAVIOUR_OPTIONS.REDIRECT_TO_URL}
          onRedirectUrlChange={onRedirectUrlChangeMock}
        />
      );
      const input = wrapper.find('#webpush-redirect-url-input').hostNodes().first();
      expect(input.exists()).toBe(true);

      // antd v6: the DOM input's onChange is antd's internal handler that synthesizes
      // a new event object before invoking the parent onChange. Use Enzyme's `simulate`
      // and assert against the resulting target.value rather than the exact event shape.
      const sampleUrl = 'https://example.com/redirect';
      input.simulate('change', { target: { value: sampleUrl } });

      expect(onRedirectUrlChangeMock).toHaveBeenCalled();
      const callArg = onRedirectUrlChangeMock.mock.calls[0][0];
      expect(callArg && callArg.target && callArg.target.value).toBe(sampleUrl);
    });
  });

  describe('Button List', () => {
    it('should render ButtonList with correct props', () => {
      const buttonState = createMockButtonState({
        buttons: [
          { type: WEBPUSH_BUTTON_TYPES.PRIMARY, text: 'Button 1', url: 'https://example.com/1' },
        ],
      });
      const wrapper = mountWithIntl(
        <ButtonsLinksSection {...defaultProps} buttonState={buttonState} />
      );
      const buttonList = wrapper.find('[data-testid="button-list"]');
      expect(buttonList.exists()).toBe(true);
    });

    it('should pass buttons to ButtonList', () => {
      const buttons = [
        { type: WEBPUSH_BUTTON_TYPES.PRIMARY, text: 'Button 1', url: 'https://example.com/1' },
        { type: WEBPUSH_BUTTON_TYPES.SECONDARY, text: 'Button 2', url: 'https://example.com/2' },
      ];
      const buttonState = createMockButtonState({ buttons });
      const wrapper = mountWithIntl(
        <ButtonsLinksSection {...defaultProps} buttonState={buttonState} />
      );
      const buttonList = wrapper.find('[data-testid="button-list"]');
      expect(buttonList.text()).toContain('Buttons: 2');
    });

    it('should disable ButtonList when isAddFlow is true', () => {
      const buttonState = createMockButtonState({ isAddFlow: true });
      const wrapper = mountWithIntl(
        <ButtonsLinksSection {...defaultProps} buttonState={buttonState} />
      );
      const buttonList = wrapper.find('[data-testid="button-list"]');
      expect(buttonList.text()).toContain('Disabled: true');
    });

    it('should show inline form when isEditFlow is true', () => {
      const buttons = [
        { type: WEBPUSH_BUTTON_TYPES.PRIMARY, text: 'Button 1', url: 'https://example.com/1' },
      ];
      const buttonState = createMockButtonState({
        buttons,
        isEditFlow: true,
        editingButtonIndex: 0,
        buttonBeingAdded: WEBPUSH_BUTTON_TYPES.PRIMARY,
      });
      const wrapper = mountWithIntl(
        <ButtonsLinksSection {...defaultProps} buttonState={buttonState} />
      );
      const buttonList = wrapper.find('[data-testid="button-list"]');
      expect(buttonList.text()).toContain('IsInlineFormVisible: true');
      expect(wrapper.find('[data-testid="inline-form"]').exists()).toBe(true);
    });
  });

  describe('Add Button Flow', () => {
    it('should render ButtonForm when isAddFlow is true', () => {
      const buttonState = createMockButtonState({
        isAddingButton: true,
        isAddFlow: true,
        buttonBeingAdded: WEBPUSH_BUTTON_TYPES.PRIMARY,
      });
      const wrapper = mountWithIntl(
        <ButtonsLinksSection {...defaultProps} buttonState={buttonState} />
      );
      const buttonForm = wrapper.find('[data-testid="button-form"]');
      expect(buttonForm.exists()).toBe(true);
      expect(buttonForm.text()).toContain('ButtonType: primary');
      expect(buttonForm.text()).toContain('IsEditMode: false');
    });

    it('should not render ButtonForm when isAddFlow is false', () => {
      const buttonState = createMockButtonState({ isAddFlow: false });
      const wrapper = mountWithIntl(
        <ButtonsLinksSection {...defaultProps} buttonState={buttonState} />
      );
      const buttonForm = wrapper.find('[data-testid="button-form"]');
      expect(buttonForm.length).toBe(0);
    });

    it('should call handleButtonSave when form save is clicked', () => {
      const handleButtonSave = jest.fn();
      const buttonState = createMockButtonState({
        isAddingButton: true,
        isAddFlow: true,
        buttonBeingAdded: WEBPUSH_BUTTON_TYPES.PRIMARY,
        handleButtonSave,
      });
      const wrapper = mountWithIntl(
        <ButtonsLinksSection {...defaultProps} buttonState={buttonState} />
      );
      const saveButton = wrapper.find('[data-testid="button-form-save"]');
      saveButton.simulate('click');
      expect(handleButtonSave).toHaveBeenCalled();
    });

    it('should call handleButtonCancel when form cancel is clicked', () => {
      const handleButtonCancel = jest.fn();
      const buttonState = createMockButtonState({
        isAddingButton: true,
        isAddFlow: true,
        buttonBeingAdded: WEBPUSH_BUTTON_TYPES.PRIMARY,
        handleButtonCancel,
      });
      const wrapper = mountWithIntl(
        <ButtonsLinksSection {...defaultProps} buttonState={buttonState} />
      );
      const cancelButton = wrapper.find('[data-testid="button-form-cancel"]');
      cancelButton.simulate('click');
      expect(handleButtonCancel).toHaveBeenCalled();
    });
  });

  describe('Add Button Controls', () => {
    it('should render add primary button when showAddPrimaryButton is true', () => {
      const handleAddPrimaryButton = jest.fn();
      const buttonState = createMockButtonState({
        showAddPrimaryButton: true,
        handleAddPrimaryButton,
      });
      const wrapper = mountWithIntl(
        <ButtonsLinksSection {...defaultProps} buttonState={buttonState} />
      );
      const addButton = wrapper.find(CapButton).find('.add-primary-button');
      expect(addButton.exists()).toBe(true);
    });

    it('should render add secondary button when showAddSecondaryButton is true', () => {
      const handleAddSecondaryButton = jest.fn();
      const buttonState = createMockButtonState({
        showAddSecondaryButton: true,
        handleAddSecondaryButton,
      });
      const wrapper = mountWithIntl(
        <ButtonsLinksSection {...defaultProps} buttonState={buttonState} />
      );
      const addButton = wrapper.find(CapButton).find('.add-secondary-button');
      expect(addButton.exists()).toBe(true);
    });

    it('should render disabled secondary button when showDisabledSecondaryDuringPrimary is true', () => {
      const buttonState = createMockButtonState({
        showDisabledSecondaryDuringPrimary: true,
      });
      const wrapper = mountWithIntl(
        <ButtonsLinksSection {...defaultProps} buttonState={buttonState} />
      );
      const addButton = wrapper.find(CapButton).find('.add-secondary-button');
      expect(addButton.exists()).toBe(true);
    });

    it('should call handleAddPrimaryButton when add primary button is clicked', () => {
      const handleAddPrimaryButton = jest.fn();
      const buttonState = createMockButtonState({
        showAddPrimaryButton: true,
        handleAddPrimaryButton,
      });
      const wrapper = mountWithIntl(
        <ButtonsLinksSection {...defaultProps} buttonState={buttonState} />
      );
      const addButton = wrapper.find('.add-primary-button').hostNodes();
      expect(addButton.exists()).toBe(true);
      
      // Simulate click on the add primary button
      addButton.simulate('click');
      wrapper.update();
      
      // Verify the handler was called
      expect(handleAddPrimaryButton).toHaveBeenCalled();
    });

    it('should call handleAddSecondaryButton when add secondary button is clicked', () => {
      const handleAddSecondaryButton = jest.fn();
      const buttonState = createMockButtonState({
        showAddSecondaryButton: true,
        handleAddSecondaryButton,
      });
      const wrapper = mountWithIntl(
        <ButtonsLinksSection {...defaultProps} buttonState={buttonState} />
      );
      const addButton = wrapper.find('.add-secondary-button').hostNodes();
      expect(addButton.exists()).toBe(true);
      
      // Simulate click on the add secondary button
      addButton.simulate('click');
      wrapper.update();
      
      // Verify the handler was called
      expect(handleAddSecondaryButton).toHaveBeenCalled();
    });

    it('should not render add button controls when all flags are false', () => {
      const buttonState = createMockButtonState({
        showAddPrimaryButton: false,
        showAddSecondaryButton: false,
        showDisabledSecondaryDuringPrimary: false,
      });
      const wrapper = mountWithIntl(
        <ButtonsLinksSection {...defaultProps} buttonState={buttonState} />
      );
      const addControls = wrapper.find('.button-add-controls');
      expect(addControls.exists()).toBe(false);
    });
  });

  describe('Edit Button Flow', () => {
    it('should render ButtonForm with initial data when editing', () => {
      const buttons = [
        { type: WEBPUSH_BUTTON_TYPES.PRIMARY, text: 'Button 1', url: 'https://example.com/1' },
      ];
      const buttonState = createMockButtonState({
        buttons,
        isEditFlow: true,
        editingButtonIndex: 0,
        buttonBeingAdded: WEBPUSH_BUTTON_TYPES.PRIMARY,
      });
      const wrapper = mountWithIntl(
        <ButtonsLinksSection {...defaultProps} buttonState={buttonState} />
      );
      const inlineForm = wrapper.find('[data-testid="inline-form"]');
      expect(inlineForm.exists()).toBe(true);
      const buttonForm = inlineForm.find('[data-testid="button-form"]');
      expect(buttonForm.text()).toContain('IsEditMode: true');
      expect(buttonForm.text()).toContain('InitialData:');
    });
  });

  describe('Default Props', () => {
    it('should use default redirectUrlError when not provided', () => {
      const wrapper = mountWithIntl(
        <ButtonsLinksSection
          onClickBehaviour={ON_CLICK_BEHAVIOUR_OPTIONS.REDIRECT_TO_URL}
          onClickBehaviourOptions={defaultProps.onClickBehaviourOptions}
          onClickBehaviourChange={mockOnClickBehaviourChange}
          redirectUrl=""
          onRedirectUrlChange={mockOnRedirectUrlChange}
          buttonState={createMockButtonState()}
          formatMessage={mockFormatMessage}
          messages={mockMessages}
        />
      );
      const input = wrapper.find(CapInput).find('#webpush-redirect-url-input');
      expect(input.exists()).toBe(true);
    });
  });
});

