import React from 'react';
import { fireEvent, screen, waitFor } from '@testing-library/react';
import { renderInAppContext } from '@theorchard/suite-testing';
import { createContractTermResponse } from 'src/__fixtures__/graphql/contract-term';
import * as storeList from 'src/__fixtures__/graphql/store-list-response.json';
import {
    transactionTypes,
    transactionTypeGroups,
} from 'src/__fixtures__/graphql/transaction-types';
import * as contractTermMutation from 'src/apollo/mutations/contract-term';
import * as contractTermQuery from 'src/apollo/queries/contract-term';
import * as storesQuery from 'src/apollo/queries/stores';
import * as transactionTypeQueries from 'src/apollo/queries/transaction-types';
import ContractTerms from 'src/components/contract-terms-form/contract-terms';
import * as contractTermValidation from 'src/utils/form-validations/contract-term-form-validation';
import type { GetStoresQuery } from 'src/apollo/queries/__generated__/stores';

jest.mock('react-router-dom', () => ({
    ...jest.requireActual('react-router-dom'),
    useParams: jest
        .fn()
        .mockReturnValue({ contractId: 123, termType: 'terms' }),
}));

describe('<ContractTerms> tests', () => {
    const addContractTerm = jest.fn().mockResolvedValue({
        data: createContractTermResponse,
        error: undefined,
        loading: false,
    });

    const render = () => renderInAppContext(<ContractTerms />);

    afterEach(jest.restoreAllMocks);

    beforeEach(() => {
        jest.spyOn(
            contractTermMutation,
            'useCreateContractTerm'
        ).mockReturnValue(addContractTerm);
        jest.spyOn(
            transactionTypeQueries,
            'useTransactionTypes'
        ).mockReturnValue({ data: transactionTypes, loading: false });
        jest.spyOn(
            transactionTypeQueries,
            'useTransactionTypeGroups'
        ).mockReturnValue({ data: transactionTypeGroups, loading: false });
        jest.spyOn(storesQuery, 'useStoreList').mockReturnValue({
            data: storeList as GetStoresQuery,
            loading: false,
        });
        jest.spyOn(contractTermQuery, 'useContractTerm').mockReturnValue({
            data: undefined,
            error: undefined,
            loading: false,
        });
    });

    it('renders <ContractBaseTerms>', () => {
        render();
        expect(screen.getByText('Base Terms')).toBeDefined();

        const saveButton = screen.getByRole('button', { name: 'Save' });
        expect(saveButton).toBeDefined();

        const cancelButton = screen.getByRole('button', { name: 'Cancel' });
        expect(cancelButton).toBeDefined();
    });

    it('displays validation error when present', () => {
        const formValidationSpy = jest
            .spyOn(contractTermValidation, 'contractTermFormValidation')
            .mockReturnValue(['Say please']);
        render();

        const saveButton = screen.getByRole('button', { name: 'Save' });
        fireEvent.click(saveButton);

        expect(formValidationSpy).toHaveBeenCalled();
        expect(screen.getByText('Say please')).toBeDefined();
    });

    it('saves contract term and contract term conditions', async () => {
        jest.spyOn(
            contractTermValidation,
            'contractTermFormValidation'
        ).mockReturnValue([]);
        jest.spyOn(
            contractTermValidation,
            'areBaseTermLabelsRemoved'
        ).mockReturnValue(false);
        render();

        const saveButton = screen.getByRole('button', { name: 'Save' });
        fireEvent.click(saveButton);

        await waitFor(() => {
            expect(addContractTerm).toHaveBeenCalled();
        });
        // TODO: through testcase, tried to select the label from the dropdown,
        // but the condition row does not appear on the label selection. And because of this
        // unable to set the termRate value and request to addContractTermConditions fails.
        // expect(addContractTermConditions).toHaveBeenCalled();
    });
});
