/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
import React from 'react';
import { mount } from 'enzyme';
import { render, screen } from 'spec/helpers/testing-library';
import userEvent from '@testing-library/user-event';
import fetchMock from 'fetch-mock';

import ModalTrigger from 'src/components/ModalTrigger';
import RefreshIntervalModal from 'src/dashboard/components/RefreshIntervalModal';
import HeaderActionsDropdown from 'src/dashboard/components/Header/HeaderActionsDropdown';
import Alert from 'src/components/Alert';
import { supersetTheme, ThemeProvider } from '@superset-ui/core';

describe('RefreshIntervalModal - Enzyme', () => {
  const getMountWrapper = (props: any) =>
    mount(<RefreshIntervalModal {...props} />, {
      wrappingComponent: ThemeProvider,
      wrappingComponentProps: {
        theme: supersetTheme,
      },
    });
  const mockedProps = {
    triggerNode: <i className="fa fa-edit" />,
    refreshFrequency: 10,
    onChange: jest.fn(),
    editMode: true,
  };
  it('should show warning message', () => {
    const props = {
      ...mockedProps,
      refreshLimit: 3600,
      refreshWarning: 'Show warning',
    };

    const wrapper = getMountWrapper(props);
    wrapper.find('span[role="button"]').simulate('click');

    // @ts-ignore (for handleFrequencyChange)
    wrapper.instance().handleFrequencyChange(30);
    wrapper.update();
    expect(wrapper.find(ModalTrigger).find(Alert)).toExist();

    // @ts-ignore (for handleFrequencyChange)
    wrapper.instance().handleFrequencyChange(3601);
    wrapper.update();
    expect(wrapper.find(ModalTrigger).find(Alert)).not.toExist();
    wrapper.unmount();
  });
});

const createProps = () => ({
  addSuccessToast: jest.fn(),
  addDangerToast: jest.fn(),
  customCss:
    '.header-with-actions .right-button-panel .ant-dropdown-trigger{margin-left: 100px;}',
  dashboardId: 1,
  dashboardInfo: {
    id: 1,
    dash_edit_perm: true,
    dash_save_perm: true,
    userId: '1',
    metadata: {},
    common: {
      conf: {},
    },
  },
  dashboardTitle: 'Title',
  editMode: false,
  expandedSlices: {},
  forceRefreshAllCharts: jest.fn(),
  hasUnsavedChanges: false,
  isLoading: false,
  layout: {},
  dataMask: {},
  onChange: jest.fn(),
  onSave: jest.fn(),
  refreshFrequency: 0,
  setRefreshFrequency: jest.fn(),
  shouldPersistRefreshFrequency: false,
  showPropertiesModal: jest.fn(),
  startPeriodicRender: jest.fn(),
  updateCss: jest.fn(),
  userCanEdit: false,
  userCanSave: false,
  userCanShare: false,
  lastModifiedTime: 0,
  isDropdownVisible: true,
});

const editModeOnProps = {
  ...createProps(),
  editMode: true,
};

const setup = (overrides?: any) => (
  <div className="dashboard-header">
    <HeaderActionsDropdown {...editModeOnProps} {...overrides} />
  </div>
);

fetchMock.get('glob:*/csstemplateasyncmodelview/api/read', {});

const openRefreshIntervalModal = async () => {
  const autoRefreshOption = screen.getByText('Set auto-refresh interval');
  userEvent.click(autoRefreshOption);
};

const displayOptions = async () => {
  // Click default refresh interval option to display other options
  userEvent.click(screen.getByText(/don't refresh/i));
};

const defaultRefreshIntervalModalProps = {
  triggerNode: <i className="fa fa-edit" />,
  refreshFrequency: 0,
  onChange: jest.fn(),
  editMode: true,
  addSuccessToast: jest.fn(),
};

describe('RefreshIntervalModal - RTL', () => {
  it('is valid', () => {
    expect(
      React.isValidElement(
        <RefreshIntervalModal {...defaultRefreshIntervalModalProps} />,
      ),
    ).toBe(true);
  });

  it('renders refresh interval modal', async () => {
    render(setup(editModeOnProps));
    await openRefreshIntervalModal();

    // Assert that modal exists by checking for the modal title
    expect(screen.getByText('Refresh interval')).toBeVisible();
  });

  it('renders refresh interval options', async () => {
    render(setup(editModeOnProps));
    await openRefreshIntervalModal();
    await displayOptions();

    // Assert that both "Don't refresh" instances exist
    // - There will be two at this point, the default option and the dropdown option
    const dontRefreshInstances = screen.getAllByText(/don't refresh/i);
    expect(dontRefreshInstances).toHaveLength(2);
    dontRefreshInstances.forEach(option => {
      expect(option).toBeInTheDocument();
    });

    // Assert that all the other options exist
    const options = [
      screen.getByText(/10 seconds/i),
      screen.getByText(/30 seconds/i),
      screen.getByText(/1 minute/i),
      screen.getByText(/5 minutes/i),
      screen.getByText(/30 minutes/i),
      screen.getByText(/1 hour/i),
      screen.getByText(/6 hours/i),
      screen.getByText(/12 hours/i),
      screen.getByText(/24 hours/i),
    ];
    options.forEach(option => {
      expect(option).toBeInTheDocument();
    });
  });

  it('should change selected value', async () => {
    render(setup(editModeOnProps));
    await openRefreshIntervalModal();

    // Initial selected value should be "Don't refresh"
    const selectedValue = screen.getByText(/don't refresh/i);
    expect(selectedValue.title).toMatch(/don't refresh/i);

    // Display options and select "10 seconds"
    await displayOptions();
    userEvent.click(screen.getByText(/10 seconds/i));

    // Selected value should now be "10 seconds"
    expect(selectedValue.title).toMatch(/10 seconds/i);
    expect(selectedValue.title).not.toMatch(/don't refresh/i);
  });

  it('should save a newly-selected value', async () => {
    render(setup(editModeOnProps));
    await openRefreshIntervalModal();
    await displayOptions();

    screen.logTestingPlaygroundURL();
    // Select a new interval and click save
    userEvent.click(screen.getByText(/10 seconds/i));
    userEvent.click(screen.getByRole('button', { name: /save/i }));

    expect(editModeOnProps.setRefreshFrequency).toHaveBeenCalled();
    expect(editModeOnProps.setRefreshFrequency).toHaveBeenCalledWith(
      10,
      editModeOnProps.editMode,
    );
    expect(editModeOnProps.addSuccessToast).toHaveBeenCalled();
  });

  it('should show warning message', async () => {
    // TODO (lyndsiWilliams): This test is incomplete
    const warningProps = {
      ...editModeOnProps,
      refreshLimit: 3600,
      refreshWarning: 'Show warning',
    };

    render(setup(warningProps));
    await openRefreshIntervalModal();
    await displayOptions();

    userEvent.click(screen.getByText(/30 seconds/i));
    userEvent.click(screen.getByRole('button', { name: /save/i }));

    // screen.debug(screen.getByRole('alert'));
    expect.anything();
  });
});
