import React from 'react';
import { fireEvent, screen } from '@testing-library/react';
import { renderInAppContext } from '@theorchard/suite-testing';
import * as contractMutations from 'src/apollo/mutations/contract';
import {
    DELETED_CONTRACT_ERROR_MSG,
    DELETED_CONTRACT_MSG,
} from 'src/apollo/type-constants/contract';
import {
    ContractDeleteModal,
    ContractDeleteModalPropsTypes,
} from 'src/components/contract-detail/contract-delete-modal';
import { getContractList } from 'src/urls/frontend-royalties';

const mockHistoryPush = jest.fn();

jest.mock('react-router-dom', () => ({
    ...jest.requireActual('react-router-dom'),
    useParams: () => ({ contractId: '123' }),
    useHistory: () => ({ push: mockHistoryPush }),
}));

describe('<ContractDeleteModal />', () => {
    const render = (props: ContractDeleteModalPropsTypes) =>
        renderInAppContext(<ContractDeleteModal {...props} />);

    const deleteContract = jest.fn().mockResolvedValue({
        data: { deleted: true },
        loading: false,
    });

    beforeEach(() =>
        jest
            .spyOn(contractMutations, 'useDeleteContract')
            .mockReturnValue(deleteContract)
    );

    afterEach(jest.restoreAllMocks);

    const props: ContractDeleteModalPropsTypes = {
        isContractDeleteModalOpen: true,
        onRequestCloseDeleteModal: jest.fn(),
    };

    it('renders the contract delete modal', () => {
        render(props);

        expect(screen.getByTestId('ContractDeleteModal')).toBeDefined();
    });

    it('renders the modal content', () => {
        render(props);

        expect(
            screen.getByText(
                'Once this contract is deleted, you will no longer be able to ' +
                    'access it. This action is permanent and cannot be undone.'
            )
        ).toBeDefined();
    });

    it('renders a success toast when deleting and redirects', async () => {
        render(props);

        const contractDeleteButton = screen.getByRole('button', {
            name: 'Delete contract',
        });

        fireEvent.click(contractDeleteButton);

        const toast = await screen.findByTestId('Toast-0');
        expect(toast).toBeDefined();
        expect(toast).toHaveTextContent(DELETED_CONTRACT_MSG);
        expect(mockHistoryPush).toHaveBeenCalledWith(getContractList);
    });

    it('renders an error toast when failing to delete', async () => {
        const mockDeleteContractError = jest.fn().mockRejectedValue({});

        jest.spyOn(contractMutations, 'useDeleteContract').mockReturnValue(
            mockDeleteContractError
        );

        render(props);

        const contractDeleteButton = screen.getByRole('button', {
            name: 'Delete contract',
        });

        fireEvent.click(contractDeleteButton);

        const toast = await screen.findByTestId('Toast-0');
        expect(toast).toBeDefined();
        expect(toast).toHaveTextContent(DELETED_CONTRACT_ERROR_MSG);
    });

    it('closes modal when isContractDeleteModalOpen is false', () => {
        render({ ...props, isContractDeleteModalOpen: false });
        expect(screen.queryByTestId('ContractDelete')).toBeNull();
    });
});
