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_LIFECYCLE_MODAL_SCREENS,
    CONTRACT_RENEWAL_TYPES_SELECT,
} from 'src/apollo/type-constants/contract';
import {
    ContractLifecycleSubsequentPeriod,
    ContractLifecycleSubsequentPeriodPropTypes,
} from 'src/components/contract-lifecycle-create/contract-lifecycle-subsequent-period';
import * as formValidation from 'src/utils/form-validations/contract-form-validation';

describe('<ContractLifecycleSubsequentPeriod/>', () => {
    const defaultProps: ContractLifecycleSubsequentPeriodPropTypes = {
        contractLifecycle: {},
        contractLifecycleSchedules: [],
        saveHandler: jest.fn(),
        setContractLifecycleSchedules: jest.fn(),
        setServerError: jest.fn(),
        setModalScreen: jest.fn(),
        isVisible: true,
    };

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

    it('renders the screen/form title, description, and footer buttons', () => {
        renderComponent();

        const backButton = screen.getByText('Back');
        const createButton = screen.getByText('Create');

        expect(backButton).toBeInTheDocument();
        expect(createButton).toBeInTheDocument();
        expect(createButton).toBeDisabled();
    });

    describe('Renewal Rules', () => {
        it(`renders the renewal rules dropdown without the ${AbacusContractLifecycleScheduleRenewalType.RENEW_AFTER_CERTAIN_DATE} option`, async () => {
            const renewalTypes = CONTRACT_RENEWAL_TYPES_SELECT.map(
                option => option.label
            );

            renderComponent();

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

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

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

    describe('Back button', () => {
        it('renders the previous Current Period form when clicked', () => {
            renderComponent();

            const backButton = screen.getByText('Back');
            fireEvent.click(backButton);

            expect(defaultProps.setServerError).toHaveBeenCalledWith(null);
            expect(defaultProps.setModalScreen).toHaveBeenCalledWith(
                CONTRACT_LIFECYCLE_MODAL_SCREENS.CURRENT_PERIOD
            );
        });
    });

    describe('Create button', () => {
        let formValidationSpy: any;

        beforeEach(() => {
            formValidationSpy = jest
                .spyOn(
                    formValidation,
                    'contractLifecycleScheduleFormValidation'
                )
                .mockReturnValue({});
        });

        afterEach(jest.restoreAllMocks);

        it(`enables when required ${AbacusContractLifecycleScheduleRenewalType.CONTINUOUSLY_ACTIVE} fields are present`, () => {
            const contractLifecycle = { lifecycleTermStart: '2024-01-01' };
            const contractLifecycleSchedules = [
                {},
                {
                    renewalType:
                        AbacusContractLifecycleScheduleRenewalType.CONTINUOUSLY_ACTIVE,
                    terminationNoticeDetailInterval: 1,
                },
            ];

            renderComponent({
                ...defaultProps,
                contractLifecycle,
                contractLifecycleSchedules,
            });

            const createButton = screen.getByText('Create');

            expect(createButton).toBeInTheDocument();
            expect(createButton).not.toBeDisabled();
        });

        it(`enables when required ${AbacusContractLifecycleScheduleRenewalType.RENEW_PERIODICALLY} fields are present`, () => {
            const contractLifecycle = { lifecycleTermStart: '2024-01-01' };
            const contractLifecycleSchedules = [
                {},
                {
                    renewalType:
                        AbacusContractLifecycleScheduleRenewalType.RENEW_PERIODICALLY,
                    renewalOffsetDetailInterval: 1,
                    terminationNoticeDetailInterval: 1,
                },
            ];

            renderComponent({
                ...defaultProps,
                contractLifecycle,
                contractLifecycleSchedules,
            });

            const createButton = screen.getByText('Create');

            expect(createButton).toBeInTheDocument();
            expect(createButton).not.toBeDisabled();
        });

        it(`enables when required ${AbacusContractLifecycleScheduleRenewalType.RENEW_PERIODICALLY} fields are present`, () => {
            const contractLifecycleSchedules = [
                {},
                {
                    renewalType:
                        AbacusContractLifecycleScheduleRenewalType.RENEW_PERIODICALLY,
                    renewalOffsetDetailInterval: 1,
                    terminationNoticeDetailInterval: 1,
                },
            ];
            const subsequentPeriodProps = {
                ...defaultProps,
                contractLifecycleSchedules,
                modalScreen: CONTRACT_LIFECYCLE_MODAL_SCREENS.SUBSEQUENT_PERIOD,
            };

            renderComponent(subsequentPeriodProps);

            const createButton = screen.getByText('Create');

            expect(createButton).toBeInTheDocument();
            expect(createButton).not.toBeDisabled();
        });

        it(`does not save ${AbacusContractLifecycleScheduleRenewalType.CONTINUOUSLY_ACTIVE} data when form is invalid`, () => {
            formValidationSpy = jest
                .spyOn(
                    formValidation,
                    'contractLifecycleScheduleFormValidation'
                )
                .mockReturnValue({
                    terminationNoticeDetailInterval: 'i am an error',
                });

            const contractLifecycle = { lifecycleTermStart: '2024-01-01' };
            const contractLifecycleSchedules = [
                {},
                {
                    renewalType:
                        AbacusContractLifecycleScheduleRenewalType.CONTINUOUSLY_ACTIVE,
                    terminationNoticeDetailInterval: '-1',
                },
            ];

            renderComponent({
                ...defaultProps,
                contractLifecycle,
                contractLifecycleSchedules,
            });

            const createButton = screen.getByText('Create');
            fireEvent.click(createButton);

            expect(createButton).toBeDisabled();
            expect(formValidationSpy).toHaveBeenCalled();
            expect(defaultProps.saveHandler).not.toHaveBeenCalled();
            expect(screen.getByText('i am an error')).toBeInTheDocument();
        });

        it(`does not save ${AbacusContractLifecycleScheduleRenewalType.RENEW_PERIODICALLY} data when form is invalid`, () => {
            formValidationSpy = jest
                .spyOn(
                    formValidation,
                    'contractLifecycleScheduleFormValidation'
                )
                .mockReturnValue({
                    renewalOffsetDetailInterval: 'i am an error',
                });

            const contractLifecycle = { lifecycleTermStart: '2024-01-01' };
            const contractLifecycleSchedules = [
                {},
                {
                    renewalType:
                        AbacusContractLifecycleScheduleRenewalType.RENEW_PERIODICALLY,
                    terminationNoticeDetailInterval: '2',
                    renewalOffsetDetailInterval: '-1',
                },
            ];

            renderComponent({
                ...defaultProps,
                contractLifecycle,
                contractLifecycleSchedules,
            });

            const createButton = screen.getByText('Create');

            fireEvent.click(createButton);

            expect(createButton).toBeDisabled();
            expect(formValidationSpy).toHaveBeenCalled();
            expect(defaultProps.saveHandler).not.toHaveBeenCalled();
            expect(screen.getByText('i am an error')).toBeInTheDocument();
        });

        it('saves contract lifecycle schedule data when clicked', () => {
            const contractLifecycleSchedules = [
                {},
                {
                    renewalType:
                        AbacusContractLifecycleScheduleRenewalType.RENEW_PERIODICALLY,
                    renewalOffsetDetailInterval: 1,
                    terminationNoticeDetailInterval: 1,
                },
            ];
            const subsequentPeriodProps = {
                ...defaultProps,
                contractLifecycleSchedules,
                modalScreen: CONTRACT_LIFECYCLE_MODAL_SCREENS.SUBSEQUENT_PERIOD,
            };

            renderComponent(subsequentPeriodProps);

            const createButton = screen.getByText('Create');
            fireEvent.click(createButton);

            expect(createButton).toBeDisabled();
            expect(formValidationSpy).toHaveBeenCalled();
            expect(defaultProps.saveHandler).toHaveBeenCalled();
        });
    });
});
