import React from 'react';
import { screen } from '@testing-library/react';
import { createIdentity, renderInAppContext } from '@theorchard/suite-testing';
import { contractDetails as mockContract } from 'src/__fixtures__/graphql/contract-details';
import { NO_NR_TERMS } from 'src/apollo/type-constants/contract';
import {
    NrContractTerms,
    NrContractTermsPropType,
} from 'src/components/contract-detail/nr-contract-terms';
import { ABACUS_PROFILE, CONTRACT_TERM_TYPES } from 'src/constants';
import { ContractTermContext } from 'src/contexts/contract-term-context';
import { initialTermsState } from 'src/reducers/contract-term/contract-terms-details-reducer';
import { createNrTerms } from 'src/urls/frontend-royalties';

const componentInContext = (
    props: NrContractTermsPropType,
    contextValues: any
) => (
    <ContractTermContext.Provider value={contextValues}>
        <NrContractTerms {...props} />
    </ContractTermContext.Provider>
);

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

describe('<NrContractTerms>', () => {
    const identity = createIdentity({ profileType: ABACUS_PROFILE });
    const defaultProps: NrContractTermsPropType = { isButtonEnabled: true };
    const defaultState = {
        ...initialTermsState,
        stores: { 1: 'Spotify', 2: '121 Music' },
        transactionTypes: {
            1: { txnTypeCode: 'DR', txnTypeName: 'Downloaded Ringtones' },
            2: { txnTypeCode: 'EQ', txnTypeName: 'Equity' },
        },
    };
    const contextValues = { state: defaultState, dispatch: jest.fn() };
    const render = (props: any, contextValues: any) =>
        renderInAppContext(componentInContext(props, contextValues), {
            identity,
        });

    it('renders', () => {
        render(defaultProps, contextValues);
        expect(screen.getByText('Terms')).toBeDefined();
    });

    it('shows a message when no terms have been added', () => {
        render(defaultProps, contextValues);
        expect(screen.getByText(NO_NR_TERMS)).toBeDefined();
    });

    it('renders Add button', () => {
        render(defaultProps, contextValues);
        const addButton = screen.getByText('Add');
        expect(addButton).toBeDefined();
    });

    it('renders the Add button as enabled when the contract has contributors', () => {
        render(defaultProps, contextValues);
        const addButton = screen.getByText('Add');
        expect(addButton).not.toHaveAttribute('disabled');
    });

    it('renders the Add button as disabled when the contract has no contributors', () => {
        const noContributorProps = { isButtonEnabled: false };
        render(noContributorProps, contextValues);
        const addButton = screen.getByText('Add');
        expect(addButton).toHaveAttribute('disabled');
    });

    it('redirects to Nr contract term form page when Add button is clicked', () => {
        render(defaultProps, contextValues);
        const addButton = screen.getByRole('link');
        expect(addButton.getAttribute('href')).toEqual(createNrTerms(123));
    });

    it('renders added terms', () => {
        const nrTerms = mockContract.abacusContract.contractTerms.filter(
            term =>
                term.termType === CONTRACT_TERM_TYPES.CONTRIBUTOR_SCHEDULE ||
                term.termType === CONTRACT_TERM_TYPES.CONTRIBUTION_SCHEDULE
        );
        const state = {
            ...defaultState,
            contractTerms: {
                nrTerms,
            },
        };
        const contextValues = { state, dispatch: jest.fn() };
        render(defaultProps, contextValues);
        const termsBlocks = screen.getAllByTestId('NRTermsBlock');
        expect(termsBlocks).toBeDefined();
        expect(termsBlocks.length).toEqual(nrTerms.length);
    });
});

describe('<NrContractTerms> when feature flag is enabled', () => {
    const identity = createIdentity({ profileType: ABACUS_PROFILE });
    const defaultProps: NrContractTermsPropType = {
        isButtonEnabled: true,
        isFeatureNrContractPageRedesignEnabled: true,
    };
    const defaultState = {
        ...initialTermsState,
        stores: { 1: 'Spotify', 2: '121 Music' },
        transactionTypes: {
            1: { txnTypeCode: 'DR', txnTypeName: 'Downloaded Ringtones' },
            2: { txnTypeCode: 'EQ', txnTypeName: 'Equity' },
        },
    };
    const contextValues = { state: defaultState, dispatch: jest.fn() };
    const render = (props: any, contextValues: any) =>
        renderInAppContext(componentInContext(props, contextValues), {
            identity,
        });

    it('renders', () => {
        render(defaultProps, contextValues);
        expect(screen.getByText('Terms')).toBeDefined();
        expect(screen.getAllByTestId('SuiteSection')).toBeDefined();
    });

    it('shows a message when no terms have been added', () => {
        render(defaultProps, contextValues);
        expect(screen.getByText(NO_NR_TERMS)).toBeDefined();
    });

    it('renders Add button', () => {
        render(defaultProps, contextValues);
        const addButton = screen.getByText('+ Add');
        expect(addButton).toBeDefined();
    });

    it('renders the Add button as enabled when the contract has contributors', () => {
        render(defaultProps, contextValues);
        const addButton = screen.getByText('+ Add');
        expect(addButton).not.toHaveAttribute('disabled');
    });

    it('renders the Add button as disabled when the contract has no contributors', () => {
        const noContributorProps = {
            isButtonEnabled: false,
            isFeatureNrContractPageRedesignEnabled: true,
        };
        render(noContributorProps, contextValues);
        const addButton = screen.getByTestId('nr-terms-addButton');
        expect(addButton).toHaveAttribute('disabled');
    });

    it('redirects to Nr contract term form page when Add button is clicked', () => {
        render(defaultProps, contextValues);
        const addButton = screen.getByRole('link');
        expect(addButton.getAttribute('href')).toEqual(createNrTerms(123));
    });

    it('renders added terms', () => {
        const nrTerms = mockContract.abacusContract.contractTerms.filter(
            term =>
                term.termType === CONTRACT_TERM_TYPES.CONTRIBUTOR_SCHEDULE ||
                term.termType === CONTRACT_TERM_TYPES.CONTRIBUTION_SCHEDULE
        );
        const state = {
            ...defaultState,
            contractTerms: {
                nrTerms,
            },
        };
        const contextValues = { state, dispatch: jest.fn() };
        render(defaultProps, contextValues);

        const termsBlocks = screen.getAllByTestId('GridTable');
        expect(termsBlocks).toBeDefined();
        expect(termsBlocks.length).toEqual(nrTerms.length);
    });
});
