import React from 'react';

import {initializeOrg} from 'app-test/helpers/initializeOrg';
import {mount} from 'enzyme';
import IncidentDetails from 'app/views/incidents/details';
import ProjectsStore from 'app/stores/projectsStore';

describe('IncidentDetails', function() {
  const params = {orgId: 'org-slug', incidentId: '123'};
  const {organization, project, routerContext} = initializeOrg({
    router: {
      params,
    },
  });
  const mockIncident = TestStubs.Incident({projects: [project.slug]});
  let activitiesList;

  const createWrapper = props =>
    mount(<IncidentDetails params={params} {...props} />, routerContext);

  beforeAll(function() {
    ProjectsStore.loadInitialData([project]);
    MockApiClient.addMockResponse({
      url: '/organizations/org-slug/incidents/123/',
      body: mockIncident,
    });

    // For @mentions
    MockApiClient.addMockResponse({
      url: '/organizations/org-slug/users/',
      body: [],
    });

    MockApiClient.addMockResponse({
      url: '/organizations/org-slug/incidents/123/suspects/',
      body: [TestStubs.IncidentSuspectCommit()],
    });
    MockApiClient.addMockResponse({
      url: '/organizations/org-slug/incidents/456/',
      statusCode: 404,
    });
    MockApiClient.addMockResponse({
      url: '/organizations/org-slug/incidents/456/suspects/',
      body: [],
    });
    activitiesList = MockApiClient.addMockResponse({
      url: `/organizations/${organization.slug}/incidents/${
        mockIncident.identifier
      }/activity/`,
      body: [TestStubs.IncidentActivity()],
    });
  });

  afterAll(function() {
    MockApiClient.clearMockResponses();
  });

  beforeEach(function() {
    activitiesList.mockClear();
  });

  it('loads incident', async function() {
    const wrapper = createWrapper();
    expect(wrapper.find('IncidentTitle').text()).toBe('Loading');
    expect(wrapper.find('SubscribeButton').prop('disabled')).toBe(true);

    await tick();
    wrapper.update();

    expect(wrapper.find('IncidentTitle').text()).toBe('Too many Chrome errors');
    expect(
      wrapper
        .find('ItemValue')
        .at(3)
        .text()
    ).toBe('100');
    expect(
      wrapper
        .find('ItemValue')
        .at(2)
        .text()
    ).toBe('20');

    expect(wrapper.find('SuspectItem')).toHaveLength(1);
    expect(
      wrapper
        .find('SuspectItem')
        .at(0)
        .find('MessageOverflow')
        .text()
    ).toBe('feat: Do something to raven/base.py');
  });

  it('handles invalid incident', async function() {
    const wrapper = createWrapper({params: {orgId: 'org-slug', incidentId: '456'}});
    await tick();
    wrapper.update();

    // Activity will also have a LoadingError
    expect(wrapper.find('LoadingError')).toHaveLength(2);
  });

  it('changes status to closed and fetches new activities', async function() {
    const updateStatus = MockApiClient.addMockResponse({
      url: '/organizations/org-slug/incidents/123/',
      method: 'PUT',
      body: TestStubs.Incident({
        status: 2,
      }),
    });

    const wrapper = createWrapper();

    await tick();
    wrapper.update();

    expect(activitiesList).toHaveBeenCalledTimes(1);

    expect(wrapper.find('Status').text()).toBe('Open');
    wrapper.find('[data-test-id="status-dropdown"] DropdownButton').simulate('click');
    wrapper
      .find('[data-test-id="status-dropdown"] MenuItem a')
      .at(0)
      .simulate('click');

    await tick();

    expect(updateStatus).toHaveBeenCalledWith(
      '/organizations/org-slug/incidents/123/',
      expect.objectContaining({
        data: {status: 2},
      })
    );

    // Refresh activities list since status changes also creates an activity
    expect(activitiesList).toHaveBeenCalledTimes(2);
    expect(wrapper.find('Status').text()).toBe('Closed');
  });

  it('toggles subscribe status with Subscribe button', async function() {
    const wrapper = createWrapper();

    await tick();
    wrapper.update();

    const subscribe = MockApiClient.addMockResponse({
      url: '/organizations/org-slug/incidents/123/subscriptions/',
      method: 'POST',
    });
    const unsubscribe = MockApiClient.addMockResponse({
      url: '/organizations/org-slug/incidents/123/subscriptions/',
      method: 'DELETE',
    });

    // Should be subscribed, so button should show "Unsubscribe"
    expect(wrapper.find('SubscribeButton Content').text()).toBe('Unsubscribe');

    // Click to unsubscribe
    wrapper.find('SubscribeButton').simulate('click');
    expect(unsubscribe).toHaveBeenCalled();
    expect(subscribe).not.toHaveBeenCalled();
    expect(wrapper.find('SubscribeButton Content').text()).toBe('Subscribe');

    // Click again to re-subscribe
    wrapper.find('SubscribeButton').simulate('click');
    expect(subscribe).toHaveBeenCalled();
  });

  it('loads related incidents', async function() {
    MockApiClient.addMockResponse({
      url: '/issues/1/',
      body: TestStubs.Group({
        id: '1',
        organization,
      }),
    });
    MockApiClient.addMockResponse({
      url: '/issues/2/',
      body: TestStubs.Group({
        id: '2',
        organization,
      }),
    });
    MockApiClient.addMockResponse({
      url: '/organizations/org-slug/incidents/123/',
      body: {
        ...mockIncident,

        groups: ['1', '2'],
      },
    });

    const wrapper = createWrapper();

    await tick();
    wrapper.update();

    expect(wrapper.find('RelatedItem')).toHaveLength(2);

    expect(
      wrapper
        .find('RelatedItem Title')
        .at(0)
        .text()
    ).toBe('RequestErrorfetchData(app/components/group/suggestedOwners)');

    expect(
      wrapper
        .find('RelatedItem GroupShortId')
        .at(0)
        .text()
    ).toBe('JAVASCRIPT-6QS');
  });

  it('renders incident without issues', async function() {
    MockApiClient.addMockResponse({
      url: '/organizations/org-slug/incidents/123/',
      body: {
        ...mockIncident,
        groups: [],
      },
    });

    const wrapper = createWrapper();

    expect(wrapper.find('RelatedIssues Placeholder')).toHaveLength(1);

    await tick();
    wrapper.update();

    expect(wrapper.find('RelatedItem')).toHaveLength(0);
    expect(wrapper.find('RelatedIssues Placeholder')).toHaveLength(0);
  });
});