// Components
import { shallowMount } from '@vue/test-utils';
import { createTestingPinia } from '@pinia/testing';
import bailoutPage from '@/layouts/bailout-page/bailout-page.vue';

// Supporting Files
import { getMountOptions } from '@/helpers/unit-test-helper.js';
import routerParams from '@/router/router-constants/router-params';
import { useMainStore } from '@/store';
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
import settleAllPromises from '@/helpers/layout-helper.js';
import bailoutCode from '@/constants/bailoutCode';

// Mock fetchCmsContentForPage
jest.mock('@/helpers/cms-content-helper', () => ({
    fetchCmsContentForPage: jest.fn(),
    doesCopyContainRouterLink: jest.fn()
}));

// Mock our module for promises.
jest.mock('@/helpers/layout-helper.js', () => jest.fn());

function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRunAfterInitializingStore = () => {}) {
    const mountOptions = getMountOptions({
        router: {
            navigate: jest.fn(),
            navigateWithSpinner: jest.fn()
        }
    });

    const testingPinia = createTestingPinia({
        initialState: {
            main: {
                applicationUser: {
                    pageData: {
                        'bailout-page': {
                            bailoutCode: bailoutCode.Unknown
                        }
                    }
                },
                ...mainInitialState
            }
        }
    });
    useMainStore(testingPinia);
    methodToRunAfterInitializingStore();

    mountOptions.global.plugins = [testingPinia];
    mountOptions.data = () => (initialData);

    const apiResponses = {
        cmsContent: {}
    };

    settleAllPromises.mockImplementation(() => apiResponses);
    fetchCmsContentForPage.mockImplementation(() => Promise.resolve());

    const wrapper = shallowMount(bailoutPage, mountOptions);
    wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => '');
    wrapper.vm.setCmsContent = jest.fn();
    return { wrapper };
}

describe('Bailout page', () => {
    test('returns the initial data', () => {
        // Arrange
        const firstName = 'Alexander';
        const lastName = 'Hamilton';
        const phoneNumber = '6145550909';
        const emailAddress = 'alexander.hamilton45@gmail.com';
        const mainInitialState = {
            order: {
                customer: {
                    firstName,
                    lastName,
                    emailAddress
                },
                contactInfo: {
                    servicePhone: phoneNumber
                }
            }
        };
        const { wrapper } = getMountedComponent(mainInitialState);

        // Assert
        expect(wrapper.vm.$data).toMatchSnapshot();
    });
    describe('renders', () => {
        test('site header', () => {
            // Arrange
            const wrapper = shallowMount(bailoutPage, getMountOptions());

            // Act
            const siteHeader = wrapper.findComponent({ ref: 'siteHeader' });

            // Assert
            expect(siteHeader.exists()).toBeTruthy();
        });
        test('sub header', () => {
            // Arrange
            const wrapper = shallowMount(bailoutPage, getMountOptions());

            // Act
            const siteSubHeader = wrapper.findComponent({ ref: 'siteSubHeader' });

            // Assert
            expect(siteSubHeader.exists()).toBeTruthy();
        });
        test('first name question', () => {
            // Arrange
            const wrapper = shallowMount(bailoutPage, getMountOptions());

            // Act
            const firstName = wrapper.findComponent({ ref: 'firstName' });

            // Assert
            expect(firstName.exists()).toBeTruthy();
        });
        test('last name question', () => {
            // Arrange
            const wrapper = shallowMount(bailoutPage, getMountOptions());

            // Act
            const lastName = wrapper.findComponent({ ref: 'lastName' });

            // Assert
            expect(lastName.exists()).toBeTruthy();
        });
        test('phone number name question', () => {
            // Arrange
            const wrapper = shallowMount(bailoutPage, getMountOptions());

            // Act
            const phoneNumber = wrapper.findComponent({ ref: 'phoneNumber' });

            // Assert
            expect(phoneNumber.exists()).toBeTruthy();
        });
        test('email question', () => {
            // Arrange
            const wrapper = shallowMount(bailoutPage, getMountOptions());

            // Act
            const email = wrapper.findComponent({ ref: 'emailAddress' });

            // Assert
            expect(email.exists()).toBeTruthy();
        });
        test('footer', () => {
            // Arrange
            const wrapper = shallowMount(bailoutPage, getMountOptions());

            // Act
            const siteFooter = wrapper.findComponent({ ref: 'siteFooter' });

            // Assert
            expect(siteFooter.exists()).toBeTruthy();
        });
    });
    describe('computed', () => {
        describe('subHeaderCmsWidgetName', () => {
            test('returns noTpa widget name when bailout code is BailoutCode.TPANotEnabled', () => {
                // Arrange
                const mainInitialState = {
                    applicationUser: {
                        pageData: {
                            'bailout-page': {
                                bailoutCode: bailoutCode.TPANotEnabled
                            }
                        }
                    }
                };
                const initialData = { };
                const { wrapper } = getMountedComponent(mainInitialState, initialData);
                const expected = 'ContentGroupNoTPAWidget';

                // Act
                const name = wrapper.vm.subHeaderCmsWidgetName;

                // Assert
                expect(name).toBe(expected);
            });
            test('returns notSeeingPreferredShop widget name when bailout code is bailoutCode.DoNotSeeMyShop', () => {
                // Arrange
                const mainInitialState = {
                    applicationUser: {
                        pageData: {
                            'bailout-page': {
                                bailoutCode: bailoutCode.DoNotSeeMyShop
                            }
                        }
                    }
                };
                const initialData = { };
                const { wrapper } = getMountedComponent(mainInitialState, initialData);
                const expected = 'ContentGroupNotSeeingPreferredShop';

                // Act
                const name = wrapper.vm.subHeaderCmsWidgetName;

                // Assert
                expect(name).toBe(expected);
            });
            test('returns default widget name when bailoutCode does not match any other content bailout codes', () => {
                // Arrange
                const mainInitialState = {
                    applicationUser: {
                        pageData: {
                            'bailout-page': {
                                bailoutCode: bailoutCode.Unknown
                            }
                        }
                    }
                };
                const initialData = { };
                const { wrapper } = getMountedComponent(mainInitialState, initialData);
                const expected = 'SiteSubHeaderWidget';

                // Act
                const name = wrapper.vm.subHeaderCmsWidgetName;

                // Assert
                expect(name).toBe(expected);
            });
        });
        describe('subHeaderContentProperty', () => {
            test('returns "SubHeaderText" when bailoutCode does not match any other content bailout codes', () => {
                // Arrange
                const mainInitialState = {
                    applicationUser: {
                        pageData: {
                            'bailout-page': {
                                bailoutCode: bailoutCode.Unknown
                            }
                        }
                    }
                };
                const initialData = { };
                const { wrapper } = getMountedComponent(mainInitialState, initialData);
                const expected = 'SubHeaderText';

                // Act
                const name = wrapper.vm.subHeaderContentProperty;

                // Assert
                expect(name).toBe(expected);
            });
            test('returns "HeaderText" when bailoutCode is bailoutCode.TPANotEnabled', () => {
                // Arrange
                const mainInitialState = {
                    applicationUser: {
                        pageData: {
                            'bailout-page': {
                                bailoutCode: bailoutCode.TPANotEnabled
                            }
                        }
                    }
                };
                const initialData = { };
                const { wrapper } = getMountedComponent(mainInitialState, initialData);
                const expected = 'HeaderText';

                // Act
                const name = wrapper.vm.subHeaderContentProperty;

                // Assert
                expect(name).toBe(expected);
            });
            test('returns "HeaderText" when bailoutCode is bailoutCode.DoNotSeeMyShop', () => {
                // Arrange
                const mainInitialState = {
                    applicationUser: {
                        pageData: {
                            'bailout-page': {
                                bailoutCode: bailoutCode.DoNotSeeMyShop
                            }
                        }
                    }
                };
                const initialData = { };
                const { wrapper } = getMountedComponent(mainInitialState, initialData);
                const expected = 'HeaderText';

                // Act
                const name = wrapper.vm.subHeaderContentProperty;

                // Assert
                expect(name).toBe(expected);
            });
        });
        describe('subContentProperty', () => {
            test('returns "SecondaryText" when bailoutCode does not match any other content bailout codes', () => {
                // Arrange
                const mainInitialState = {
                    applicationUser: {
                        pageData: {
                            'bailout-page': {
                                bailoutCode: bailoutCode.Unknown
                            }
                        }
                    }
                };
                const initialData = { };
                const { wrapper } = getMountedComponent(mainInitialState, initialData);
                const expected = 'SecondaryText';

                // Act
                const name = wrapper.vm.subContentProperty;

                // Assert
                expect(name).toBe(expected);
            });
            test('returns "BodyText" when bailoutCode is bailoutCode.TPANotEnabled', () => {
                // Arrange
                const mainInitialState = {
                    applicationUser: {
                        pageData: {
                            'bailout-page': {
                                bailoutCode: bailoutCode.TPANotEnabled
                            }
                        }
                    }
                };
                const initialData = { };
                const { wrapper } = getMountedComponent(mainInitialState, initialData);
                const expected = 'BodyText';

                // Act
                const name = wrapper.vm.subContentProperty;

                // Assert
                expect(name).toBe(expected);
            });
            test('returns "BodyText" when bailoutCode is bailoutCode.DoNotSeeMyShop', () => {
                // Arrange
                const mainInitialState = {
                    applicationUser: {
                        pageData: {
                            'bailout-page': {
                                bailoutCode: bailoutCode.DoNotSeeMyShop
                            }
                        }
                    }
                };
                const initialData = { };
                const { wrapper } = getMountedComponent(mainInitialState, initialData);
                const expected = 'BodyText';

                // Act
                const name = wrapper.vm.subContentProperty;

                // Assert
                expect(name).toBe(expected);
            });
        });
        describe('stripRteStyle', () => {
            test('returns false when bailoutCode does not match any other content bailout codes', () => {
                // Arrange
                const mainInitialState = {
                    applicationUser: {
                        pageData: {
                            'bailout-page': {
                                bailoutCode: bailoutCode.Unknown
                            }
                        }
                    }
                };
                const initialData = { };
                const { wrapper } = getMountedComponent(mainInitialState, initialData);
                const expected = false;

                // Act
                const flag = wrapper.vm.stripRteStyle;

                // Assert
                expect(flag).toBe(expected);
            });
            test('returns true when bailoutCode is bailoutCode.TPANotEnabled', () => {
                // Arrange
                const mainInitialState = {
                    applicationUser: {
                        pageData: {
                            'bailout-page': {
                                bailoutCode: bailoutCode.TPANotEnabled
                            }
                        }
                    }
                };
                const initialData = { };
                const { wrapper } = getMountedComponent(mainInitialState, initialData);
                const expected = true;

                // Act
                const flag = wrapper.vm.stripRteStyle;

                // Assert
                expect(flag).toBe(expected);
            });
            test('returns true when  when bailoutCode is bailoutCode.DoNotSeeMyShop', () => {
                // Arrange
                const mainInitialState = {
                    applicationUser: {
                        pageData: {
                            'bailout-page': {
                                bailoutCode: bailoutCode.DoNotSeeMyShop
                            }
                        }
                    }
                };
                const initialData = { };
                const { wrapper } = getMountedComponent(mainInitialState, initialData);
                const expected = true;

                // Act
                const flag = wrapper.vm.stripRteStyle;

                // Assert
                expect(flag).toBe(expected);
            });
        });
    });
    describe('method', () => {
        describe('backButtonAction', () => {
            test('should navigate with CLICKED_BACK_PREVIOUS scenario', () => {
                // Arrange
                const { wrapper } = getMountedComponent();

                // Act
                wrapper.vm.backButtonAction();

                // Assert
                expect(wrapper.vm.$router.navigateWithSpinner).toHaveBeenCalledWith(
                    wrapper.vm.navigationScenarios.CLICKED_BACK_PREVIOUS,
                    wrapper.vm.$route
                );
            });
        });
        describe('forwardButtonAction', () => {
            test('should navigate to the next route', async () => {
                // Arrange
                const { wrapper } = getMountedComponent();

                // Act
                await wrapper.vm.forwardButtonAction();

                // Assert
                expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
                    wrapper.vm.navigationScenarios.CLICKED_FORWARD,
                    wrapper.vm.$route,
                    {},
                    { [routerParams.SKIP_SAVE_SESSION]: true }
                );
            });
        });
        describe('getBailoutPageModelFromStore', () => {
            test('should return expected bailout page model', () => {
                // Arrange
                const firstName = 'Jake';
                const lastName = 'From State Farm';
                const phoneNumber = '4215558234';
                const emailAddress = 'jake.from.state.farm993@yahoo.com';
                const mainInitialState = {
                    order: {
                        customer: {
                            firstName,
                            lastName,
                            emailAddress
                        },
                        contactInfo: {
                            servicePhone: phoneNumber
                        }
                    }
                };
                const { wrapper } = getMountedComponent(mainInitialState);

                // Act
                const pageModel = wrapper.vm.getBailoutPageModelFromStore();

                // Assert
                expect(pageModel).toEqual({
                    firstName,
                    lastName,
                    phoneNumber,
                    email: emailAddress
                });
            });
        });
    });
});
