import React from 'react';
import { fireEvent, screen } from '@testing-library/react';
import { renderInAppContext } from '@theorchard/suite-testing';
import { AbacusContractLifecycleScheduleRenewalType } from 'src/apollo/definitions/globalTypes';
import {
    CONTRACT_RENEWAL_TYPES_SELECT,
    TOOLTIP_RENEWAL_RULES,
} from 'src/apollo/type-constants/contract';
import {
    RenewalTypeSelectPropTypes,
    RenewalTypeSelect,
} from 'src/components/contract-lifecycle-shared/renewal-type-select';

describe('<RenewalTypeSelect/>', () => {
    const defaultProps: RenewalTypeSelectPropTypes = {
        contractLifecycleSchedule: {
            renewalType: null,
        },
        errors: {},
        handleFormChange: jest.fn(),
        isDisabled: false,
        isEditForm: false,
        renewalTypeOptions: CONTRACT_RENEWAL_TYPES_SELECT,
    };

    const renderComponent = (
        props: RenewalTypeSelectPropTypes = defaultProps
    ) => renderInAppContext(<RenewalTypeSelect {...props} />);

    it('shows the renewal type options when clicked', async () => {
        renderComponent();
        const renewalTypes = defaultProps.renewalTypeOptions.map(
            option => option.label
        );

        const renewalTypeSelect = screen.getByText('Select Renewal Rules');
        fireEvent.click(renewalTypeSelect);

        const continuouslyActive = await screen.findByText(
            `${renewalTypes[0]}`
        );
        const renewAfterCertainDate = await screen.findByText(
            `${renewalTypes[1]}`
        );
        const renewPeriodically = await screen.findByText(`${renewalTypes[2]}`);

        expect(continuouslyActive).toBeInTheDocument();
        expect(renewAfterCertainDate).toBeInTheDocument();
        expect(renewPeriodically).toBeInTheDocument();
    });

    it('displays the selected renewalType if present', () => {
        const contractLifecycleSchedule = {
            renewalType: `${AbacusContractLifecycleScheduleRenewalType.CONTINUOUSLY_ACTIVE}`,
        };

        renderComponent({ ...defaultProps, contractLifecycleSchedule });

        const renewalTypeSelect = screen.getByTestId('renewal-type-select');
        expect(renewalTypeSelect).toBeInTheDocument();
        expect(renewalTypeSelect.textContent).toEqual(
            CONTRACT_RENEWAL_TYPES_SELECT[0].label
        );
    });

    it('updates the renewalType when a renewal rule is selected', async () => {
        renderComponent();

        const renewalTypeSelect = screen.getByText('Select Renewal Rules');
        fireEvent.click(renewalTypeSelect);

        const continuouslyActive = await screen.findByText(
            `${CONTRACT_RENEWAL_TYPES_SELECT[0].label}`
        );
        fireEvent.click(continuouslyActive);

        expect(defaultProps.handleFormChange).toHaveBeenCalledWith(
            'renewalType',
            CONTRACT_RENEWAL_TYPES_SELECT[0].value
        );
    });

    it('displays an error when present', () => {
        const errors = { renewalType: 'i am an error' };

        renderComponent({ ...defaultProps, errors });

        const renewalTypeSelect = screen.getByTestId('renewal-type-select');
        const error = screen.getByText(errors.renewalType);

        expect(renewalTypeSelect.classList).toContain('error');
        expect(error).toBeInTheDocument();
    });

    it('renders disabled when specified', () => {
        renderComponent({ ...defaultProps, isDisabled: true });

        const renewalTypeSelect = screen.getByTestId('SuiteSelectInput');
        expect(renewalTypeSelect.className).toContain('disabled');
    });

    describe('create form', () => {
        it('renders with placeholder text', () => {
            renderComponent();

            const renewalTypeSelect = screen.getByTestId('renewal-type-select');

            expect(renewalTypeSelect).toBeInTheDocument();
            expect(renewalTypeSelect.textContent).toEqual(
                'Select Renewal Rules'
            );
        });

        it('displays a tooltip message on hover', async () => {
            renderComponent();

            const renewalTypeSelect = screen.getByTestId('renewal-type-select');
            fireEvent.mouseOver(renewalTypeSelect);

            const tooltip = await screen.findByText(TOOLTIP_RENEWAL_RULES);
            expect(tooltip).toBeInTheDocument();
        });

        it('displays a tooltip explaining the Renewal Rules on hover of each option', async () => {
            renderComponent();
            const renewalTypes = defaultProps.renewalTypeOptions.map(
                option => option.label
            );
            const descriptions = defaultProps.renewalTypeOptions.map(
                option => option.description
            );

            const renewalTypeSelect = screen.getByText('Select Renewal Rules');
            fireEvent.click(renewalTypeSelect);

            const continuouslyActive = await screen.findByText(
                `${renewalTypes[0]}`
            );
            fireEvent.mouseOver(continuouslyActive);
            const continuouslyActiveTooltip = await screen.findByText(
                `${descriptions[0]}`
            );
            expect(continuouslyActiveTooltip).toBeInTheDocument();

            const renewAfterCertainDate = await screen.findByText(
                `${renewalTypes[1]}`
            );
            fireEvent.mouseOver(renewAfterCertainDate);
            const renewAfterCertainDateTooltip = await screen.findByText(
                `${descriptions[1]}`
            );
            expect(renewAfterCertainDateTooltip).toBeInTheDocument();

            const renewPeriodically = await screen.findByText(
                `${renewalTypes[2]}`
            );
            fireEvent.mouseOver(renewPeriodically);
            const renewPeriodicallyTooltip = await screen.findByText(
                `${descriptions[2]}`
            );
            expect(renewPeriodicallyTooltip).toBeInTheDocument();
        });
    });

    describe('edit form', () => {
        it('displays the current renewalType', () => {
            const contractLifecycleSchedule = {
                contractLifecycleScheduleId: '1',
                renewalType: `${AbacusContractLifecycleScheduleRenewalType.CONTINUOUSLY_ACTIVE}`,
            };

            renderComponent({
                ...defaultProps,
                contractLifecycleSchedule,
                isEditForm: true,
            });

            const renewalTypeSelect = screen.getByTestId('renewal-type-select');
            expect(renewalTypeSelect).toBeInTheDocument();
            expect(renewalTypeSelect.textContent).toEqual(
                CONTRACT_RENEWAL_TYPES_SELECT[0].label
            );
        });

        it('does not display a tooltip message on hover', () => {
            renderComponent({ ...defaultProps, isEditForm: true });

            const renewalTypeSelect = screen.getByTestId('renewal-type-select');
            fireEvent.mouseOver(renewalTypeSelect);

            const tooltip = screen.queryByText(TOOLTIP_RENEWAL_RULES);
            expect(tooltip).not.toBeInTheDocument();
        });

        it('does not display a tooltip explaining the Renewal Rules on hover of each option', async () => {
            renderComponent({ ...defaultProps, isEditForm: true });

            const renewalTypes = defaultProps.renewalTypeOptions.map(
                option => option.label
            );
            const descriptions = defaultProps.renewalTypeOptions.map(
                option => option.description
            );

            const renewalTypeSelect = screen.getByText('Select Renewal Rules');
            fireEvent.click(renewalTypeSelect);

            const continuouslyActive = await screen.findByText(
                `${renewalTypes[0]}`
            );
            fireEvent.mouseOver(continuouslyActive);
            const continuouslyActiveTooltip = screen.queryByText(
                `${descriptions[0]}`
            );
            expect(continuouslyActiveTooltip).not.toBeInTheDocument();

            const renewAfterCertainDate = await screen.findByText(
                `${renewalTypes[1]}`
            );
            fireEvent.mouseOver(renewAfterCertainDate);
            const renewAfterCertainDateTooltip = screen.queryByText(
                `${descriptions[1]}`
            );
            expect(renewAfterCertainDateTooltip).not.toBeInTheDocument();

            const renewPeriodically = await screen.findByText(
                `${renewalTypes[2]}`
            );
            fireEvent.mouseOver(renewPeriodically);
            const renewPeriodicallyTooltip = screen.queryByText(
                `${descriptions[2]}`
            );
            expect(renewPeriodicallyTooltip).not.toBeInTheDocument();
        });
    });
});
