import React from 'react';
import { injectIntl } from 'react-intl';
import '@testing-library/jest-dom';
import { Provider } from 'react-redux';
import { configureStore }  from '@capillarytech/vulcan-react-sdk/utils';
import history from '../../../utils/history';
import { initialReducer } from '../../../initialReducer';
import { Viber } from '../index';
import { render, screen, fireEvent, waitFor } from '../../../utils/test-utils';
import { largeText, templateDetailsImage, templateDetailsText, templateDetailsVideo, templateDetails_ } from './mockData';
import { metaEntities, getDefaultTags, injectedTags } from '../../Zalo/tests/mockData';

const mockActions = {
  getTemplateDetails: jest.fn(),
  editTemplate: jest.fn(),
  createTemplate: jest.fn(),
  uploadViberAsset: jest.fn(),
  clearViberAsset: jest.fn(),
  clearEditResponse: jest.fn(),
  clearCreateResponse: jest.fn(),
};
const mockGlobalActions = {
  fetchSchemaForEntity: jest.fn(),
};
jest.mock('../../../v2Containers/TagList/index.js', () => ({
  __esModule: true,
  default: (props) => (
    <div className="tag-mock" {...props}>
      TagList
    </div>
  ),
}));

let store;
beforeAll(() => {
  store = configureStore({}, initialReducer, history);
});

const ComponentToRender = injectIntl(Viber);
const renderComponent = (props) =>
  render(
    <Provider store={store}>
      <ComponentToRender {...props} />
    </Provider>,
  );

describe('Test Viber container', () => {
  it('test case for Viber template creation flow', async () => {
    renderComponent({
      actions: mockActions,
      globalActions: mockGlobalActions,
      templateData: {mode: 'create'},
      viber: {
        uploadedAssetData: {},
        createTemplateInProgress: false,
      },
      location: {
        pathname: "/sms/edit",
        query: {
          type: false,
          module: "default",
        },
        search: "",
      },
      isFullMode: true,
      handleClose: jest.fn(),
    });
    const inputBox = await screen.findAllByPlaceholderText(
      'Enter template name',
    );
    // Re-query input reference between changes: CapInput's error wrapper toggles
    // status classes which can detach the underlying input ref between renders.
    fireEvent.change(inputBox[0], { target: { value: 'Hello, welcome' } });
    fireEvent.change(screen.getAllByPlaceholderText('Enter template name')[0], { target: { value: '' } });
    fireEvent.change(screen.getAllByPlaceholderText('Enter template name')[0], { target: { value: 'temp title' } });
    const imageRadio = screen.getByRole('radio', {name: /image/i});
    fireEvent.click(imageRadio);
    const textRadio = screen.getByRole('radio', {name: /text/i});
    fireEvent.click(textRadio);
    const videoRadio = screen.getByRole('radio', {name: /video/i});
    fireEvent.click(videoRadio);
    fireEvent.click(textRadio);
    const msgBox = screen.getAllByPlaceholderText(/Enter message/i);
    msgBox[0].focus();
    fireEvent.change(msgBox[0], { target: { value: 'temp message' }});
    fireEvent.change(screen.getAllByPlaceholderText(/Enter message/i)[0], { target: { value: '' }});
    fireEvent.change(screen.getAllByPlaceholderText(/Enter message/i)[0], { target: { value: 'test}}' }});
    fireEvent.change(screen.getAllByPlaceholderText(/Enter message/i)[0], { target: { value: largeText }});
    fireEvent.change(screen.getAllByPlaceholderText(/Enter message/i)[0], { target: { value: 'temp message' }});
    fireEvent.change(screen.getAllByPlaceholderText('Enter template name')[0], { target: { value: '' } });
    fireEvent.change(screen.getAllByPlaceholderText('Enter template name')[0], { target: { value: 'temp title' } });
    const ctaRadioBtn = screen.getByRole('radio', {
      name: /call to action create a button that lets customers respond to your messages or take action/i,
    });
    fireEvent.click(ctaRadioBtn);
    const cancelBtn_ = screen.getAllByRole('button', {name: /cancel/i});
    fireEvent.click(cancelBtn_[0]);
    fireEvent.click(ctaRadioBtn);
    const ctaBtnText = await screen.findByPlaceholderText(
      'Enter button text',
    );
    fireEvent.change(ctaBtnText, { target: { value: 'btn text' } });
    const ctaBtnUrl = await screen.findByPlaceholderText(
      'Enter button url',
    );
    fireEvent.change(ctaBtnUrl, { target: { value: 'https://www.test.com' } });
    // Re-query after each change: error-state toggling can swap the input wrapper
    // (CapInput renders a different status node) which detaches the original ref.
    let ctaBtnUrl2 = screen.getByPlaceholderText('Enter button url');
    fireEvent.change(ctaBtnUrl2, { target: { value: 'not url' } });
    ctaBtnUrl2 = screen.getByPlaceholderText('Enter button url');
    fireEvent.change(ctaBtnUrl2, { target: { value: 'https://www.test.com' } });
    const saveBtn = await screen.findByRole('button', {
      name: /save/i,
    });
    await waitFor(() => expect(saveBtn).toBeEnabled());
    fireEvent.click(saveBtn);
    const editCta = await screen.findByLabelText(/edit-cta-icon/i);
    fireEvent.click(editCta);
    const cancelBtn = screen.getAllByRole('button', {name: /cancel/i});
    fireEvent.click(cancelBtn[0]);
    const doneBtn = await screen.findByRole('button', {
      name: /done/i,
    });
    await waitFor(() => expect(doneBtn).toBeEnabled());
    fireEvent.click(doneBtn);
    expect(mockActions.createTemplate).toHaveBeenCalled();
  });
  it('test case for Viber template creation flow for image media type', async () => {
    renderComponent({
      actions: mockActions,
      globalActions: mockGlobalActions,
      templateData: {mode: 'create'},
      viber: {
        uploadedAssetData: {},
        createTemplateInProgress: false,
        templateDetails: templateDetailsImage,
      },
      location: {
        pathname: "/sms/edit",
        query: {
          type: false,
          module: "default",
        },
        search: "",
      },
      isFullMode: true,
      params: { id: 'test'},
      handleClose: jest.fn(),
    });
    const doneBtn = screen.getByRole('button', {
      name: /done/i,
    });
    expect(doneBtn).toBeEnabled();
    fireEvent.click(doneBtn);
    expect(mockActions.editTemplate).toHaveBeenCalled();
  });
  it('test case for Viber template creation flow for image not present', async () => {
    renderComponent({
      actions: mockActions,
      globalActions: mockGlobalActions,
      templateData: {mode: 'create'},
      viber: {
        uploadedAssetData: {},
        createTemplateInProgress: false,
        templateDetails: templateDetailsImage,
      },
      location: {
        pathname: "/sms/edit",
        query: {
          type: false,
          module: "default",
        },
        search: "",
      },
      isFullMode: true,
      params: { id: 'test'},
      handleClose: jest.fn(),
    });
    const reupload = screen.getByRole('button', {
      name: /reupload/i,
    });
    fireEvent.click(reupload);
    const doneBtn = screen.getByRole('button', {
      name: /done/i,
    });
    expect(doneBtn).toBeDisabled();
  });
  it('test case for Viber template creation flow for video media type', async () => {
    renderComponent({
      actions: mockActions,
      globalActions: mockGlobalActions,
      templateData: {mode: 'create'},
      viber: {
        uploadedAssetData: {},
        createTemplateInProgress: false,
        templateDetails: templateDetailsVideo,
      },
      location: {
        pathname: "/sms/edit",
        query: {
          type: false,
          module: "default",
        },
        search: "",
      },
      isFullMode: true,
      params: { id: 'test'},
      handleClose: jest.fn(),
      metaEntities,
      getDefaultTags,
      injectedTags,
    });
    const doneBtn = screen.getByRole('button', {
      name: /done/i,
    });
    expect(doneBtn).toBeEnabled();
    fireEvent.click(doneBtn);
    expect(mockActions.editTemplate).toHaveBeenCalled();
  });
  it('test case for Viber template creation flow for text type', async () => {
    renderComponent({
      actions: mockActions,
      globalActions: mockGlobalActions,
      templateData: {mode: 'create'},
      viber: {
        uploadedAssetData: {},
        createTemplateInProgress: false,
        templateDetails: templateDetailsText,
      },
      location: {
        pathname: "/sms/edit",
        query: {
          type: false,
          module: "default",
        },
        search: "",
      },
      isFullMode: true,
      params: { id: 'test'},
      handleClose: jest.fn(),
      metaEntities,
      getDefaultTags,
      injectedTags,
    });
    const doneBtn = screen.getByRole('button', {
      name: /done/i,
    });
    expect(doneBtn).toBeEnabled();
    fireEvent.click(doneBtn);
    expect(mockActions.editTemplate).toHaveBeenCalled();
  });
  it('test case for Viber template creation flow for video not present', async () => {
    renderComponent({
      actions: mockActions,
      globalActions: mockGlobalActions,
      templateData: {mode: 'create'},
      viber: {
        uploadedAssetData: {},
        createTemplateInProgress: false,
        templateDetails: templateDetailsVideo,
      },
      location: {
        pathname: "/sms/edit",
        query: {
          type: false,
          module: "default",
        },
        search: "",
      },
      params: { id: 'test'},
      handleClose: jest.fn(),
      metaEntities,
      getDefaultTags,
      injectedTags,
    });
    const reupload = screen.getByRole('button', {
      name: /re upload/i,
    });
    fireEvent.click(reupload);
    const doneBtn = screen.getByRole('button', {
      name: /done/i,
    });
    expect(doneBtn).toBeDisabled();
  });
  it('test case for Viber template for error cases', async () => {
    renderComponent({
      actions: mockActions,
      globalActions: mockGlobalActions,
      viber: {
        uploadedAssetData: {},
        createTemplateInProgress: false,
        templateDetails: templateDetails_,
      },
      location: {
        pathname: "/sms/edit",
        query: {
          type: true,
          module: "default",
        },
        search: "",
      },
      isFullMode: true,
      params: { id: 'test'},
      handleClose: jest.fn(),
    });
    const doneBtn = screen.getByRole('button', {
      name: /done/i,
    });
    expect(doneBtn).toBeDisabled();
  });

  it('disables Done while a replacement video asset is uploading (finding 1)', async () => {
    renderComponent({
      actions: mockActions,
      globalActions: mockGlobalActions,
      templateData: { mode: 'create' },
      viber: {
        uploadedAssetData: {},
        createTemplateInProgress: false,
        templateDetails: templateDetailsVideo,
        // a new upload has started after the template was loaded
        assetUploading: true,
      },
      location: {
        pathname: '/sms/edit',
        query: { type: false, module: 'default' },
        search: '',
      },
      isFullMode: true,
      params: { id: 'test' },
      handleClose: jest.fn(),
      metaEntities,
      getDefaultTags,
      injectedTags,
    });
    const doneBtn = screen.getByRole('button', { name: /done/i });
    expect(doneBtn).toBeDisabled();
  });

  it('disables Done while an image asset is uploading (finding 1)', async () => {
    renderComponent({
      actions: mockActions,
      globalActions: mockGlobalActions,
      templateData: { mode: 'create' },
      viber: {
        uploadedAssetData: {},
        createTemplateInProgress: false,
        templateDetails: templateDetailsImage,
        assetUploading: true,
      },
      location: {
        pathname: '/sms/edit',
        query: { type: false, module: 'default' },
        search: '',
      },
      isFullMode: true,
      params: { id: 'test' },
      handleClose: jest.fn(),
    });
    const doneBtn = screen.getByRole('button', { name: /done/i });
    expect(doneBtn).toBeDisabled();
  });

  it('keeps Done enabled when assetUploading is true but media type is text', async () => {
    renderComponent({
      actions: mockActions,
      globalActions: mockGlobalActions,
      templateData: { mode: 'create' },
      viber: {
        uploadedAssetData: {},
        createTemplateInProgress: false,
        templateDetails: templateDetailsText,
        // stale upload flag, but the form has no media so submission is safe
        assetUploading: true,
      },
      location: {
        pathname: '/sms/edit',
        query: { type: false, module: 'default' },
        search: '',
      },
      isFullMode: true,
      params: { id: 'test' },
      handleClose: jest.fn(),
      metaEntities,
      getDefaultTags,
      injectedTags,
    });
    const doneBtn = screen.getByRole('button', { name: /done/i });
    expect(doneBtn).toBeEnabled();
  });
});
