import React from 'react';
import { screen } from '@testing-library/react';
import { createIdentity, renderInAppContext } from '@theorchard/suite-testing';
import cloneDeep from 'lodash-es/cloneDeep';
import * as contractListResponse from 'src/__fixtures__/graphql/contract-list-response.json';
import * as contractQuery from 'src/apollo/queries/contract';
import { ContractList } from 'src/components/contract-list/contract-list';
import { ABACUS_PROFILE, USER_FEATURES } from 'src/constants';
import { createNewContractWithLifecycle } from 'src/urls/frontend-royalties';
import type { GetContractsListQuery } from 'src/apollo/queries/contract/__generated__/get-contracts-list';

describe('<ContractList>', () => {
    const features = {
        [USER_FEATURES.ABACUS_CONTRACT_PAGE_FILTERS]: false,
    };

    let contractListQuerySpy: any;

    afterEach(jest.restoreAllMocks);

    beforeEach(() => {
        contractListQuerySpy = jest
            .spyOn(contractQuery, 'useContractList')
            .mockReturnValue({
                data: contractListResponse as GetContractsListQuery,
                error: undefined,
                loading: false,
            });
    });

    const render = (features: { [x: number]: boolean }) =>
        renderInAppContext(<ContractList />, {
            identity: createIdentity({ features, profileType: ABACUS_PROFILE }),
        });

    it('renders', () => {
        const { container } = render(features);
        expect(container).toBeDefined();
    });

    it('requests a list of contracts on render', () => {
        render(features);
        expect(contractListQuerySpy).toHaveBeenCalled();
    });

    it('includes correct create contract link', () => {
        render(features);
        expect(screen.getByText('New Contract')).toBeDefined();
        const links = screen.getAllByRole('link');
        expect(links[0].getAttribute('href')).toEqual(
            createNewContractWithLifecycle
        );
    });

    it('includes bulk entity edit button when FF is on', () => {
        const enabled_features = cloneDeep(features);
        enabled_features[USER_FEATURES.ABACUS_BULK_ENTITY_UPDATE] = true;

        render(enabled_features);
        expect(screen.getByText('Bulk Edit')).toBeDefined();
    });

    it('not includes bulk entity edit button when FF is false', () => {
        const enabled_features = cloneDeep(features);
        enabled_features[USER_FEATURES.ABACUS_BULK_ENTITY_UPDATE] = false;

        render(enabled_features);
        expect(screen.queryByText('Bulk Edit')).toBeNull();
    });

    it('renders a list of contracts', () => {
        render(features);
        const gridTable = screen.getByTestId('sectionTable');
        expect(gridTable).toHaveTextContent('Test Contract 1');
        expect(gridTable).toHaveTextContent('Test Contract 5');
    });

    it('renders contract search filter', () => {
        render(features);
        expect(
            screen.getByPlaceholderText('Filter by Contract Name or ID')
        ).toBeDefined();
        expect(screen.queryByText('Clear Filters')).toBeNull();
    });

    it('renders contract type filter when FF is enabled', () => {
        const enabled_features = cloneDeep(features);
        enabled_features[USER_FEATURES.ABACUS_CONTRACT_PAGE_FILTERS] = true;

        render(enabled_features);
        expect(screen.getByTestId('contractType')).toBeDefined();
    });

    it('renders Included/Excluded in Run filter when FF is enabled', () => {
        const enabled_features = cloneDeep(features);
        enabled_features[USER_FEATURES.ABACUS_CONTRACT_PAGE_FILTERS] = true;

        render(enabled_features);
        expect(screen.getByTestId('includedOrExcluded')).toBeDefined();
    });

    it('renders Contract Status filter when FF is enabled', () => {
        const enabled_features = cloneDeep(features);
        enabled_features[USER_FEATURES.ABACUS_CONTRACT_PAGE_FILTERS] = true;

        render(enabled_features);
        expect(screen.getByTestId('contractStatus')).toBeDefined();
    });

    it('renders Run Controller filter when FF is enabled', () => {
        const enabled_features = cloneDeep(features);
        enabled_features[USER_FEATURES.ABACUS_CONTRACT_PAGE_FILTERS] = true;

        render(enabled_features);
        expect(screen.getByTestId('runControllerSelect')).toBeDefined();
    });

    it('renders included/excluded from run data', () => {
        render(features);
        const gridTable: HTMLElement = screen.getByTestId('sectionTable');
        expect(gridTable).toHaveTextContent('Included');
        expect(gridTable).toHaveTextContent('Excluded');
    });

    it('renders the status components', () => {
        render(features);
        const statuses: HTMLElement[] = screen.queryAllByTestId('Status');
        expect(statuses).toBeDefined();
    });

    it('renders each of the contract status text formatted', () => {
        render(features);
        const gridTable: HTMLElement = screen.getByTestId('sectionTable');
        expect(gridTable).toHaveTextContent('Not Yet Active');
        expect(gridTable).toHaveTextContent('Active');
        expect(gridTable).toHaveTextContent('To Be Terminated');
        expect(gridTable).toHaveTextContent('Terminated');
        expect(gridTable).toHaveTextContent('Collection Period');
    });

    it('renders run controller data', () => {
        render(features);
        const gridTable: HTMLElement = screen.getByTestId('sectionTable');
        expect(gridTable).toHaveTextContent('Test Run Controller');
    });
});
