import React from 'react';
import { IntlProvider, injectIntl } from '@edx/frontend-platform/i18n';
import { initializeMockApp } from '@edx/frontend-platform';
import { render, waitFor, fireEvent } from '@testing-library/react';

import GradingScale from './GradingScale';

const gradeCutoffs = { A: 0.9, B: 0.8, C: 0.7 };

const gradeLetters = ['A', 'B', 'C', 'D'];

const sortedGrades = [
  { current: 100, previous: 49 },
  { current: 49, previous: 41 },
  { current: 32, previous: 20 },
  { current: 20, previous: 0 },
];

const RootWrapper = (viewOnly = { viewOnly: false }) => (
  <IntlProvider locale="en" messages={{}}>
    <GradingScale
      intl={injectIntl}
      gradeCutoffs={gradeCutoffs}
      gradeLetters={gradeLetters}
      sortedGrades={sortedGrades}
      resetDataRef={{ current: false }}
      showSavePrompt={jest.fn()}
      setShowSuccessAlert={jest.fn()}
      setGradingData={jest.fn()}
      setOverrideInternetConnectionAlert={jest.fn()}
      setEligibleGrade={jest.fn()}
      {...viewOnly}
    />
  </IntlProvider>
);

describe('<GradingScale />', () => {
  beforeEach(() => {
    initializeMockApp({
      authenticatedUser: {
        userId: 3,
        username: 'abc123',
        administrator: true,
        roles: [],
      },
    });
  });

  it('renders grading scale ticks', async () => {
    const { getAllByTestId } = render(<RootWrapper />);
    await waitFor(() => {
      const ticks = getAllByTestId('grading-scale-tick');
      expect(ticks).toHaveLength(11); // 0 to 100, inclusive, with step 10
    });
  });

  it('renders grading scale segments', async () => {
    const { getAllByTestId } = render(<RootWrapper />);
    await waitFor(() => {
      const segments = getAllByTestId('grading-scale-segment');
      expect(segments).toHaveLength(5);
    });
  });

  it('should add a new grading segment when "Add new grading segment" button is clicked', async () => {
    const { debug, getAllByTestId } = render(<RootWrapper />);
    await waitFor(() => {
      const addNewSegmentBtn = getAllByTestId('grading-scale-btn-add-segment');
      expect(addNewSegmentBtn[0]).toBeInTheDocument();
      fireEvent.click(addNewSegmentBtn[0]);
      const segments = getAllByTestId('grading-scale-segment');
      expect(segments).toHaveLength(6);
      debug(addNewSegmentBtn);
    });
  });

  it('should not disable new grading segment button when viewOnly=false', async () => {
    const { getAllByTestId } = render(<RootWrapper />);
    await waitFor(() => {
      const addNewSegmentBtn = getAllByTestId('grading-scale-btn-add-segment');
      expect(addNewSegmentBtn).toHaveLength(1);
      expect(addNewSegmentBtn[0]).toBeInTheDocument();
      expect(addNewSegmentBtn[0].disabled).toBe(false);
    });
  });

  it('should disable new grading segment button when viewOnly', async () => {
    const { getAllByTestId } = render(<RootWrapper viewOnly />);
    await waitFor(() => {
      const addNewSegmentBtn = getAllByTestId('grading-scale-btn-add-segment');
      expect(addNewSegmentBtn).toHaveLength(1);
      expect(addNewSegmentBtn[0]).toBeInTheDocument();
      expect(addNewSegmentBtn[0].disabled).toBe(true);
    });
  });

  it('should remove grading segment when "Remove" button is clicked', async () => {
    const { getAllByTestId } = render(<RootWrapper />);
    await waitFor(() => {
      const segments = getAllByTestId('grading-scale-segment');
      const removeSegmentBtn = getAllByTestId('grading-scale-btn-remove');
      fireEvent.click(removeSegmentBtn[1]);
      expect(segments).toHaveLength(5);
    });
  });

  it('should update segment input value', async () => {
    const { getAllByTestId } = render(<RootWrapper />);
    await waitFor(() => {
      const segmentInputs = getAllByTestId('grading-scale-segment-input');
      expect(segmentInputs).toHaveLength(5);
      const segmentInput = segmentInputs[1];
      fireEvent.change(segmentInput, { target: { value: 'Test' } });
      expect(segmentInput).toHaveValue('Test');
    });
  });

  it('should render GradingScale component with short grade cutoffs and sorted grades', async () => {
    const shortGradeCutoffs = { Pass: 0.9 };
    const shortSortedGrades = [
      { current: 100, previous: 49 },
      { current: 20, previous: 0 },
    ];
    const { getAllByTestId } = render(
      <IntlProvider locale="en" messages={{}}>
        <GradingScale
          intl={injectIntl}
          gradeCutoffs={shortGradeCutoffs}
          gradeLetters={['A']}
          sortedGrades={shortSortedGrades}
          resetDataRef={{ current: false }}
          showSavePrompt={jest.fn()}
          setShowSuccessAlert={jest.fn()}
          setGradingData={jest.fn()}
          setOverrideInternetConnectionAlert={jest.fn()}
          setEligibleGrade={jest.fn()}
        />
      </IntlProvider>,
    );
    await waitFor(() => {
      const segmentInputs = getAllByTestId('grading-scale-segment-input');
      expect(segmentInputs[0]).toHaveValue('Fail');
      fireEvent.change(segmentInputs[1], { target: { value: 'Test' } });
      expect(segmentInputs[1]).toHaveValue('Test');
    });
  });
});
