import React from 'react';
import { injectIntl } from 'react-intl';
import '@testing-library/jest-dom';
import { render, screen, fireEvent } from '../../../utils/test-utils';
import { CapWhatsappCarouselButton } from '../index';
import {
  INITIAL_CAROUSEL_PHONE_NUMBER_DATA,
  INITIAL_CAROUSEL_URL_DATA,
  URL,
} from '../constant';
import { HOST_TWILIO } from "../../../v2Containers/Whatsapp/constants";

const setCarouselData = jest.fn();

const initializeComponent = (
  carouselData = [],
  isEditFlow = false,
  hostName = HOST_TWILIO,
  carouselIndex = 0
) => {
  const Component = injectIntl(CapWhatsappCarouselButton);
  return render(
    <Component
      carouselData={carouselData}
      setCarouselData={setCarouselData}
      carouselIndex={carouselIndex}
      hostName={hostName}
      isEditFlow={isEditFlow}
      tags={[]}
      injectedTags={{}}
      selectedOfferDetails={[]}
    />,
  );
};

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

  it('renders initial phone number button type', () => {
    initializeComponent([{
      buttons: [INITIAL_CAROUSEL_PHONE_NUMBER_DATA]
    }]);
    
    expect(screen.getByText('Button type')).toBeInTheDocument();
    expect(screen.getByText('Button text')).toBeInTheDocument();
    expect(screen.getAllByText('Phone number')).toHaveLength(2);
    expect(screen.getByRole('button', { name: /save/i })).toBeDisabled();
  });

  it('handles button text change', () => {
    initializeComponent([{
      buttons: [INITIAL_CAROUSEL_PHONE_NUMBER_DATA]
    }]);

    const buttonTextInput = screen.getByPlaceholderText('Enter button text');
    fireEvent.change(buttonTextInput, { target: { value: 'Call now' } });

    expect(setCarouselData).toHaveBeenCalledWith([{
      buttons: [{
        ...INITIAL_CAROUSEL_PHONE_NUMBER_DATA,
        text: 'Call now'
      }]
    }]);
  });

  it('handles phone number change', () => {
    initializeComponent([{
      buttons: [INITIAL_CAROUSEL_PHONE_NUMBER_DATA]
    }]);

    const phoneInput = screen.getByPlaceholderText('Enter phone number');
    fireEvent.change(phoneInput, { target: { value: '9112345678' } });
    expect(screen.getByText('Phone')).toBeInTheDocument();
  });

  it('handles URL type button with static URL', () => {
    initializeComponent([{
      buttons: [INITIAL_CAROUSEL_URL_DATA]
    }]);

    const urlInput = screen.getByPlaceholderText('Enter website URL');
    fireEvent.change(urlInput, { 
      target: { value: 'https://www.example.com' }
    });

    expect(setCarouselData).toHaveBeenCalled();
  });

  it('handles URL type button with dynamic URL', () => {
    const urlData = {
      ...INITIAL_CAROUSEL_URL_DATA,
      urlType: 'DYNAMIC_URL'
    };
    
    initializeComponent([{
      buttons: [urlData]
    }]);

    const urlInput = screen.getByPlaceholderText('Enter URL, variable is added by default');
    fireEvent.change(urlInput, { 
      target: { value: 'https://www.example.com/{{1}}' }
    });

    expect(setCarouselData).toHaveBeenCalled();
  });

  it('shows saved button state', () => {
    initializeComponent([{
      buttons: [{
        ...INITIAL_CAROUSEL_PHONE_NUMBER_DATA,
        text: 'Call us',
        phone_number: '9112345678',
        isSaved: true
      }]
    }]);

    expect(screen.getByText('Call us')).toBeInTheDocument();
    expect(screen.getByText('9112345678')).toBeInTheDocument();
  });

  it('handles add button click', () => {
    initializeComponent([{
      buttons: [{
        ...INITIAL_CAROUSEL_PHONE_NUMBER_DATA,
        text: 'Call us',
        phone_number: '9112345678',
        isSaved: true
      }]
    }]);

    const addButton = screen.getByRole('button', { name: /add button/i });
    fireEvent.click(addButton);

    expect(setCarouselData).toHaveBeenCalled();
  });

  it('handles delete button click', () => {
    // CapIcon renders as <i class="cap-icon-v2 cap-icon-v2-delete">, not a <button>
    const { container } = initializeComponent([{
      buttons: [
        {
          ...INITIAL_CAROUSEL_PHONE_NUMBER_DATA,
          text: 'Call us',
          phone_number: '9112345678',
          isSaved: true
        },
        {
          ...INITIAL_CAROUSEL_URL_DATA,
          text: 'Visit us',
          url: 'https://example.com',
          isSaved: true
        }
      ]
    }]);

    const deleteIcons = container.querySelectorAll('.cap-icon-v2-delete');
    expect(deleteIcons.length).toBeGreaterThan(0);
    fireEvent.click(deleteIcons[0]);

    expect(setCarouselData).toHaveBeenCalledTimes(1);
  });

  // Additional test case for delete button disabled state
  it('delete button should be disabled when only one button exists', () => {
    // disabled CapIcon adds a `disabled`-suffixed class and ignores onClick
    const { container } = initializeComponent([{
      buttons: [
        {
          ...INITIAL_CAROUSEL_PHONE_NUMBER_DATA,
          text: 'Call us',
          phone_number: '9112345678',
          isSaved: true
        }
      ]
    }]);

    const deleteIcons = container.querySelectorAll('.cap-icon-v2-delete');
    expect(deleteIcons.length).toBe(1);
    fireEvent.click(deleteIcons[0]);
    expect(setCarouselData).not.toHaveBeenCalled();
  });

  it('handles edit mode', () => {
    initializeComponent([{
      buttons: [{
        ...INITIAL_CAROUSEL_URL_DATA,
        text: 'Visit us',
        url: 'https://example.com/{{1}}',
        urlType: 'DYNAMIC_URL',
        isSaved: true,
        isEditFlow: true,
      }]
    }]);

    expect(screen.getByText('Visit us')).toBeInTheDocument();
    expect(screen.getByText('https://example.com/{{1}}')).toBeInTheDocument();
  });

  it('validates invalid button text', () => {
    initializeComponent([{
      buttons: [INITIAL_CAROUSEL_PHONE_NUMBER_DATA]
    }]);

    const buttonTextInput = screen.getByPlaceholderText('Enter button text');
    fireEvent.change(buttonTextInput, { target: { value: '!@#$' } });

    expect(setCarouselData).toHaveBeenCalledWith(expect.arrayContaining([
      expect.objectContaining({
        buttons: expect.arrayContaining([
          expect.objectContaining({
            textError: expect.any(String)
          })
        ])
      })
    ]));
  });

  it('validates invalid URL', () => {
    initializeComponent([{
      buttons: [INITIAL_CAROUSEL_URL_DATA]
    }]);

    const urlInput = screen.getByPlaceholderText('Enter website URL');
    fireEvent.change(urlInput, { target: { value: 'invalid-url' } });

    expect(setCarouselData).toHaveBeenCalledWith(expect.arrayContaining([
      expect.objectContaining({
        buttons: expect.arrayContaining([
          expect.objectContaining({
            urlError: expect.any(String)
          })
        ])
      })
    ]));
  });

  describe('carousel-scoped updates (only current card is updated)', () => {
    it('handleButtonType only updates the carousel at carouselIndex', () => {
      const card0 = {
        bodyText: '',
        buttons: [{ ...INITIAL_CAROUSEL_PHONE_NUMBER_DATA, text: 'Card 0' }],
      };
      const card1 = {
        bodyText: '',
        buttons: [{ ...INITIAL_CAROUSEL_PHONE_NUMBER_DATA, text: 'Card 1' }],
      };
      const carouselData = [card0, card1];

      initializeComponent(carouselData, false, HOST_TWILIO, 0);

      const radios = screen.getAllByRole('radio');
      const urlRadio = radios.find((r) => r.value === URL) || radios[1];
      if (urlRadio) fireEvent.click(urlRadio);

      expect(setCarouselData).toHaveBeenCalledWith(expect.any(Array));
      const updated = setCarouselData.mock.calls[0][0];
      expect(updated).toHaveLength(2);
      expect(updated[0].buttons[0]).toMatchObject(INITIAL_CAROUSEL_URL_DATA);
      expect(updated[1]).toEqual(card1);
    });

    it('handleDeleteButton only removes button from the carousel at carouselIndex', () => {
      const card0 = {
        bodyText: '',
        buttons: [
          { ...INITIAL_CAROUSEL_PHONE_NUMBER_DATA, text: 'A', isSaved: true },
          { ...INITIAL_CAROUSEL_URL_DATA, text: 'B', isSaved: true },
        ],
      };
      const card1 = {
        bodyText: '',
        buttons: [
          { ...INITIAL_CAROUSEL_PHONE_NUMBER_DATA, text: 'C', isSaved: true },
          { ...INITIAL_CAROUSEL_URL_DATA, text: 'D', isSaved: true },
        ],
      };
      const carouselData = [card0, card1];

      const { container } = initializeComponent(carouselData, false, HOST_TWILIO, 0);

      const deleteIconBtns = container.querySelectorAll('.cap-icon-v2-delete');
      expect(deleteIconBtns.length).toBeGreaterThanOrEqual(2);
      fireEvent.click(deleteIconBtns[1]);

      expect(setCarouselData).toHaveBeenCalledTimes(1);
      const setter = setCarouselData.mock.calls[0][0];
      expect(typeof setter).toBe('function');
      const result = setter(carouselData);
      expect(result[0].buttons).toHaveLength(1);
      expect(result[0].buttons[0].text).toBe('A');
      expect(result[1].buttons).toHaveLength(2);
      expect(result[1].buttons[0].text).toBe('C');
      expect(result[1].buttons[1].text).toBe('D');
    });

    it('addCarouselButton only adds button to the carousel at carouselIndex', () => {
      const card0 = {
        bodyText: '',
        buttons: [{
          ...INITIAL_CAROUSEL_PHONE_NUMBER_DATA,
          text: 'Call us',
          phone_number: '9112345678',
          isSaved: true,
        }],
      };
      const card1 = {
        bodyText: '',
        buttons: [{ ...INITIAL_CAROUSEL_PHONE_NUMBER_DATA, text: 'Other' }],
      };
      const carouselData = [card0, card1];

      initializeComponent(carouselData, false, HOST_TWILIO, 0);

      const addButton = screen.getByRole('button', { name: /add button/i });
      fireEvent.click(addButton);

      expect(setCarouselData).toHaveBeenCalledWith(expect.any(Array));
      const updated = setCarouselData.mock.calls[0][0];
      expect(updated).toHaveLength(2);
      expect(updated[0].buttons).toHaveLength(2);
      expect(updated[0].buttons[0].text).toBe('Call us');
      expect(updated[0].buttons[1]).toMatchObject(INITIAL_CAROUSEL_PHONE_NUMBER_DATA);
      expect(updated[0].buttons[1]).not.toBe(INITIAL_CAROUSEL_PHONE_NUMBER_DATA);
      expect(updated[1]).toEqual(card1);
    });

    it('addCarouselButton adds a new button object (clone) so state is not shared', () => {
      const carouselData = [{
        bodyText: '',
        buttons: [{
          ...INITIAL_CAROUSEL_PHONE_NUMBER_DATA,
          text: 'Saved',
          isSaved: true,
        }],
      }];

      initializeComponent(carouselData, false, HOST_TWILIO, 0);

      const addButton = screen.getByRole('button', { name: /add button/i });
      fireEvent.click(addButton);

      const updated = setCarouselData.mock.calls[0][0];
      const addedButton = updated[0].buttons[1];
      expect(addedButton).toMatchObject({
        buttonType: 'PHONE_NUMBER',
        text: '',
        phone_number: '',
        isSaved: false,
      });
      expect(addedButton).not.toBe(INITIAL_CAROUSEL_PHONE_NUMBER_DATA);
    });
  });
});