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 { TOOLTIP_SAME_RENEWAL_RULES } from 'src/apollo/type-constants/contract';
import { CONTRACT_TYPES } from 'src/constants';
import {
    CurrentPeriodFormFields,
    CurrentPeriodFormFieldsPropTypes,
} from '../current-period-form-fields';

describe('<CurrentPeriodFormFields />', () => {
    const defaultProps: CurrentPeriodFormFieldsPropTypes = {
        contractLifecycle: {},
        contractType: CONTRACT_TYPES.DISTRIBUTION,
        currentSchedule: {
            renewalType: '',
        },
        defaultFormValues: {
            renewalType: '',
        },
        errors: {},
        isCollectionPeriodVisible: false,
        isDisabled: false,
        isEditForm: false,
        isSameRenewalRulesChecked: true,
        setContractLifecycle: jest.fn(),
        setContractLifecycleSchedules: jest.fn(),
        setErrors: jest.fn(),
        setIsCollectionPeriodVisible: jest.fn(),
        setIsSameRenewalRulesChecked: jest.fn(),
        subsequentSchedule: undefined,
    };

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

    describe('Continuously Active renewal rule', () => {
        it('renders the Termination Notice Period when selected', () => {
            const currentSchedule = {
                renewalType:
                    AbacusContractLifecycleScheduleRenewalType.CONTINUOUSLY_ACTIVE as string,
            };
            renderComponent({ ...defaultProps, currentSchedule });

            const terminationNoticeLabel = screen.queryByText(
                'Termination Notice Period'
            );
            const terminationNoticeInput = screen.queryByTestId(
                'termination-notice-interval'
            );
            const terminationNoticeType = screen.queryByTestId(
                'termination-notice-type'
            );

            expect(terminationNoticeLabel).toBeInTheDocument();
            expect(terminationNoticeInput).toBeInTheDocument();
            expect(terminationNoticeType).toBeInTheDocument();
        });
    });

    describe('Renew After Certain Date renewal rule', () => {
        beforeEach(() => {
            const currentSchedule = {
                renewalType:
                    AbacusContractLifecycleScheduleRenewalType.RENEW_AFTER_CERTAIN_DATE as string,
            };
            renderComponent({ ...defaultProps, currentSchedule });
        });

        it('renders the Current Period End Date when selected', () => {
            const endDateLabel = screen.getByText('Current Period End Date');
            const endDatePicker = screen.getByTestId('end-date-picker');

            expect(endDateLabel).toBeInTheDocument();
            expect(endDatePicker).toBeInTheDocument();
            expect(endDatePicker.textContent).toEqual('YYYY-MM-DD');
        });

        it('renders the Termination Notice Period when selected', () => {
            const terminationNoticeLabel = screen.queryByText(
                'Termination Notice Period'
            );
            const terminationNoticeInput = screen.queryByTestId(
                'termination-notice-interval'
            );
            const terminationNoticeType = screen.queryByTestId(
                'termination-notice-type'
            );

            expect(terminationNoticeLabel).toBeInTheDocument();
            expect(terminationNoticeInput).toBeInTheDocument();
            expect(terminationNoticeType).toBeInTheDocument();
        });
    });

    describe('Renew Periodically renewal rule', () => {
        beforeEach(() => {
            const currentSchedule = {
                renewalType:
                    AbacusContractLifecycleScheduleRenewalType.RENEW_PERIODICALLY as string,
            };
            renderComponent({ ...defaultProps, currentSchedule });
        });

        it('renders Renew After when selected', () => {
            const renewAfterLabel = screen.getByText('Renew After');
            const renewAfterInput = screen.getByTestId(
                'renewal-offset-interval'
            );
            const renewAfterType = screen.getByTestId('renewal-offset-type');

            expect(renewAfterLabel).toBeInTheDocument();
            expect(renewAfterInput).toBeInTheDocument();
            expect(renewAfterType).toBeInTheDocument();
            expect(renewAfterInput.innerHTML).toContain('e.g. 1');
            expect(renewAfterType.textContent).toEqual('MonthsYears');
        });

        it('renders the Same Renewal Rules checkbox when selected', () => {
            const checkbox = screen.getByTestId('same-renewal-rules-checkbox');

            expect(checkbox).toBeInTheDocument();
            expect(checkbox).toBeChecked();
            expect(checkbox.nextSibling?.textContent).toEqual(
                'Use the same renewal rules for subsequent periods'
            );
        });

        it('renders the Termination Notice Period when selected', () => {
            const terminationNoticeLabel = screen.queryByText(
                'Termination Notice Period'
            );
            const terminationNoticeInput = screen.queryByTestId(
                'termination-notice-interval'
            );
            const terminationNoticeType = screen.queryByTestId(
                'termination-notice-type'
            );

            expect(terminationNoticeLabel).toBeInTheDocument();
            expect(terminationNoticeInput).toBeInTheDocument();
            expect(terminationNoticeType).toBeInTheDocument();
        });
    });

    describe('Same Renewal Rules checkbox', () => {
        it('is hidden on render', () => {
            renderComponent();

            const checkbox = screen.queryByTestId(
                'same-renewal-rules-checkbox'
            );

            expect(checkbox).not.toBeInTheDocument();
        });

        it(`renders when the ${AbacusContractLifecycleScheduleRenewalType.RENEW_PERIODICALLY} Renewal Rule is selected`, () => {
            const currentSchedule = {
                renewalType:
                    AbacusContractLifecycleScheduleRenewalType.RENEW_PERIODICALLY as string,
            };
            renderComponent({ ...defaultProps, currentSchedule });

            const checkbox = screen.getByTestId('same-renewal-rules-checkbox');

            expect(checkbox).toBeInTheDocument();
            expect(checkbox).toBeChecked();
            expect(checkbox.nextSibling?.textContent).toEqual(
                'Use the same renewal rules for subsequent periods'
            );
        });

        it('displays a tooltip message on hover', async () => {
            const currentSchedule = {
                renewalType:
                    AbacusContractLifecycleScheduleRenewalType.RENEW_PERIODICALLY as string,
            };
            renderComponent({ ...defaultProps, currentSchedule });

            const checkbox = screen.getByTestId('same-renewal-rules-checkbox');
            fireEvent.mouseOver(checkbox);

            const tooltip = await screen.findByText(content =>
                content.startsWith(TOOLTIP_SAME_RENEWAL_RULES.split('\n\n')[0])
            );

            expect(tooltip).toBeInTheDocument();
            expect(tooltip.textContent).toEqual(TOOLTIP_SAME_RENEWAL_RULES);
        });

        it(`does not render when the ${AbacusContractLifecycleScheduleRenewalType.CONTINUOUSLY_ACTIVE} Renewal Rule is selected`, () => {
            const currentSchedule = {
                renewalType:
                    AbacusContractLifecycleScheduleRenewalType.CONTINUOUSLY_ACTIVE as string,
            };
            renderComponent({ ...defaultProps, currentSchedule });

            const checkbox = screen.queryByTestId(
                'same-renewal-rules-checkbox'
            );

            expect(checkbox).not.toBeInTheDocument();
        });

        it(`does not render when the ${AbacusContractLifecycleScheduleRenewalType.RENEW_AFTER_CERTAIN_DATE} Renewal Rule is selected`, () => {
            const currentSchedule = {
                renewalType:
                    AbacusContractLifecycleScheduleRenewalType.RENEW_AFTER_CERTAIN_DATE as string,
            };
            renderComponent({ ...defaultProps, currentSchedule });

            const checkbox = screen.queryByTestId(
                'same-renewal-rules-checkbox'
            );

            expect(checkbox).not.toBeInTheDocument();
        });

        it('does not render when the form is for editing', () => {
            const propsForEditForm = {
                contractLifecycle: {},
                currentSchedule: {
                    contractLifecycleScheduleId: '1',
                    renewalType:
                        AbacusContractLifecycleScheduleRenewalType.RENEW_PERIODICALLY as string,
                },
                defaultFormValues: {
                    renewalType: '',
                },
                errors: {},
                isEditForm: true,
                setContractLifecycle: jest.fn(),
                setContractLifecycleSchedules: jest.fn(),
                setErrors: jest.fn(),
            };
            renderComponent(propsForEditForm);

            const checkbox = screen.queryByTestId(
                'same-renewal-rules-checkbox'
            );

            expect(checkbox).not.toBeInTheDocument();
        });
    });

    describe('Collection Period', () => {
        it('renders when editing a neighbouring rights contract', () => {
            renderComponent({
                ...defaultProps,
                contractType: CONTRACT_TYPES.NEIGHBOURING_RIGHTS,
                isEditForm: true,
            });

            const collectionPeriodSwitch = screen.getByTestId(
                'collection-period-switch'
            );

            expect(collectionPeriodSwitch).toBeInTheDocument();
            expect(collectionPeriodSwitch.nextSibling?.textContent).toEqual(
                'There is a collection period'
            );
        });

        it('does not render when editing a distribution contract', () => {
            renderComponent({ ...defaultProps, isEditForm: true });

            const collectionPeriodSwitch = screen.queryByTestId(
                'collection-period-switch'
            );

            expect(collectionPeriodSwitch).not.toBeInTheDocument();
        });

        it('does not render when creating a distribution contract', () => {
            renderComponent();

            const collectionPeriodSwitch = screen.queryByTestId(
                'collection-period-switch'
            );

            expect(collectionPeriodSwitch).not.toBeInTheDocument();
        });

        it('does not render when creating a neighbouring rights contract', () => {
            renderComponent({
                ...defaultProps,
                contractType: CONTRACT_TYPES.NEIGHBOURING_RIGHTS,
            });

            const collectionPeriodSwitch = screen.queryByTestId(
                'collection-period-switch'
            );

            expect(collectionPeriodSwitch).not.toBeInTheDocument();
        });
    });
});
