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

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

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

    it('renders the footer buttons', () => {
        renderComponent();
        const backButton = screen.getByText('Back');
        const nextButton = screen.getByText('Next');

        expect(backButton).toBeInTheDocument();
        expect(nextButton).toBeInTheDocument();
    });

    describe('Back button', () => {
        it('renders the previous Contract General Info 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.GENERAL_INFORMATION
            );
        });
    });

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

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

        afterEach(jest.restoreAllMocks);

        it(`replaces the "Next" button when ${AbacusContractLifecycleScheduleRenewalType.CONTINUOUSLY_ACTIVE} is selected`, () => {
            const contractLifecycleSchedules = [
                {
                    renewalType:
                        AbacusContractLifecycleScheduleRenewalType.CONTINUOUSLY_ACTIVE,
                },
            ];

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

            const createButton = screen.getByText('Create');
            const nextButton = screen.queryByText('Next');

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

        it(`replaces the "Next" button when ${AbacusContractLifecycleScheduleRenewalType.RENEW_PERIODICALLY} is selected and "Same Renewal Rules" is checked`, () => {
            const contractLifecycleSchedules = [
                {
                    renewalType:
                        AbacusContractLifecycleScheduleRenewalType.RENEW_PERIODICALLY,
                },
            ];

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

            const checkbox = screen.getByTestId('same-renewal-rules-checkbox');
            const createButton = screen.getByText('Create');
            const nextButton = screen.queryByText('Next');

            expect(checkbox).toBeChecked();
            expect(createButton).toBeInTheDocument();
            expect(nextButton).not.toBeInTheDocument();
            expect(createButton).toBeDisabled();
        });

        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 and "Same Renewal Rules" is checked`, () => {
            const contractLifecycle = { lifecycleTermStart: '2024-01-01' };
            const contractLifecycleSchedules = [
                {
                    renewalType:
                        AbacusContractLifecycleScheduleRenewalType.RENEW_PERIODICALLY,
                    renewalOffsetDetailInterval: 1,
                    terminationNoticeDetailInterval: 1,
                },
            ];

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

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

            expect(checkbox).toBeChecked();
            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(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 checkbox = screen.getByTestId('same-renewal-rules-checkbox');
            const createButton = screen.getByText('Create');

            fireEvent.click(createButton);

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

        it('saves contract lifecycle and contract lifecycle schedules when clicked', async () => {
            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).toHaveBeenCalled();
        });

        it(`saves ${AbacusContractLifecycleScheduleRenewalType.RENEW_PERIODICALLY} contract lifecycle schedules when clicked and "Same Renewal Rules" is checked`, () => {
            const contractLifecycle = { lifecycleTermStart: '2024-01-01' };
            const contractLifecycleSchedules = [
                {
                    renewalType:
                        AbacusContractLifecycleScheduleRenewalType.RENEW_PERIODICALLY,
                    renewalOffsetDetailInterval: 1,
                    terminationNoticeDetailInterval: 1,
                },
            ];

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

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

            fireEvent.click(createButton);

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

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

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

        afterEach(jest.restoreAllMocks);

        it('renders by default', () => {
            renderComponent();

            const nextButton = screen.getByText('Next');

            expect(nextButton).toBeInTheDocument();
        });

        it(`is present when the ${AbacusContractLifecycleScheduleRenewalType.RENEW_AFTER_CERTAIN_DATE} Renewal Rule is selected`, () => {
            const contractLifecycleSchedules = [
                {
                    renewalType:
                        AbacusContractLifecycleScheduleRenewalType.RENEW_AFTER_CERTAIN_DATE,
                },
            ];

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

            const nextButton = screen.getByText('Next');

            expect(nextButton).toBeInTheDocument();
            expect(nextButton).toBeDisabled();
        });

        it(`replaces the "Create" button when ${AbacusContractLifecycleScheduleRenewalType.RENEW_PERIODICALLY} is selected and "Same Renewal Rules" is unchecked`, () => {
            const contractLifecycleSchedules = [
                {
                    renewalType:
                        AbacusContractLifecycleScheduleRenewalType.RENEW_PERIODICALLY,
                },
            ];

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

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

            expect(createButton).toBeInTheDocument();

            fireEvent.click(checkbox);

            const nextButton = screen.getByText('Next');

            expect(checkbox).not.toBeChecked();
            expect(nextButton).toBeInTheDocument();
            expect(nextButton).toBeDisabled();
        });

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

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

            const nextButton = screen.getByText('Next');

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

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

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

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

            const nextButton = screen.getByText('Next');

            expect(checkbox).not.toBeChecked();
            expect(nextButton).toBeInTheDocument();
            expect(nextButton).not.toBeDisabled();
        });

        it('renders the next Subsequent Period form when clicked', () => {
            const contractLifecycle = { lifecycleTermStart: '2024-01-01' };
            const contractLifecycleSchedules = [
                {
                    renewalType:
                        AbacusContractLifecycleScheduleRenewalType.RENEW_AFTER_CERTAIN_DATE,
                    scheduleEnd: '2030-12-31',
                    terminationNoticeDetailInterval: 1,
                },
            ];

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

            const nextButton = screen.getByText('Next');
            fireEvent.click(nextButton);

            expect(formValidationSpy).toHaveBeenCalled();
            expect(defaultProps.setModalScreen).toHaveBeenCalledWith(
                CONTRACT_LIFECYCLE_MODAL_SCREENS.SUBSEQUENT_PERIOD
            );
        });
    });
});
