// Components
import vehicleParts from '@/layouts/vehicle-parts/vehicle-parts.vue';
import glassPartQuestion from '@/layouts/vehicle-parts/glass-part-question/glass-part-question.vue';

// Supporting Files
import settleAllPromises from '@/helpers/layout-helper.js';
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
import { shallowMount } from '@vue/test-utils';
import { getMountOptions } from '@/helpers/unit-test-helper.js';
import { nextTick } from 'vue';
import baseMixin from '@/mixins/base-mixin.js';
import { useMainStore } from '@/store';
import navigationScenarios from '@/router/router-constants/navigation-scenarios';
import applicationConfig from '@/constants/application-config';

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

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

useMainStore().getters = {
    pageData: jest.fn(),
    damage: {
        isRepair: false
    }
};

const basePartResponse = {
    partsOrQuestions: [
        {
            glassName: 'Stationary',
            glassLocation: 'Rear',
            parts: [
                {
                    partNumber: 'DB12209GTYN',
                    description: 'heated glass, solar, 1 hole',
                    color: 'Green Tint',
                    requiresRecalibration: false,
                    requiresCapabilityQuestions: false,
                    childParts: null
                },
                {
                    partNumber: 'DB12209YPYNOEM',
                    description: 'heated glass, solar, 1 hole',
                    color: 'Gray Tint Privacy',
                    requiresRecalibration: false,
                    requiresCapabilityQuestions: false,
                    childParts: null
                }
            ],
            partQuestions: null
        }
    ]
};

/** @ignore */
function setupMocks({ pageHeaderWidgetHeaderText = {}, mountOptionsMockData = {} }) {
    // Mock api responses
    const apiResponses = {
        cmsContent: {
            SiteSubHeaderWidget: pageHeaderWidgetHeaderText,
            FunnelHeaderWidget: {
                LogoImage:
                    `${applicationConfig.ISS_DEV_CMS_DOMAIN}/images/default-source/default-album/logos/insuranceLogo.jpg`
            },
            ColorQuestionWidget: 'Please choose your rear window tint color',
            FeatureQuestionWidget: 'Ok no choose features',
            AlertWidget: {
                BodyText: 'Please choose your tint color',
                HeadlineText: 'Just a few more steps to go'
            }
        }
    };

    const store = useMainStore();
    const actionResult = [];
    store.getCapabilityQuestions.mockImplementation(() => Promise.resolve({ data: actionResult }));

    const apiPromise = Promise.resolve(apiResponses);

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

    const mountOptions = getMountOptions(mountOptionsMockData);
    const wrapper = shallowMount(vehicleParts, mountOptions);

    const partQuestionRearWrapper = wrapper.findComponent({ name: 'glassPartQuestion' });
    partQuestionRearWrapper.vm.initializeComponent = glassPartQuestion.methods.initializeComponent;

    wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent;

    return { wrapper, apiPromise };
}

describe('vehicle-parts.vue', () => {
    test('Set cms content called on load', async () => {
        // Arrange
        useMainStore().pageData = jest.fn();
        useMainStore().pageData.mockReturnValue(basePartResponse);
        useMainStore().lineItems = { glassParts: null };

        const { wrapper, apiPromise } = setupMocks({
            mountOptionsMockData: {
                router: {
                    navigate: jest.fn()
                },
                route: {
                    query: {
                        issPage: 'vehicle-parts'
                    }
                },
                useMainStore: {
                    getters: useMainStore().getters
                }
            }
        });

        // Act
        vehicleParts.beforeRouteEnter.call(
            wrapper.vm,
            { query: { issPage: 'vehicle-parts' } },
            undefined,
            (c) => c(wrapper.vm)
        );
        wrapper.vm.setCmsContent = jest.fn();

        // Assert
        apiPromise.finally(() => {
            expect(wrapper.vm.setCmsContent).toHaveBeenCalled();
        });
    });

    test('PageData / isRepair populated in Vuex. arePagePrerequisitesValid should be true ', async () => {
        // Arrange
        useMainStore().pageData = jest.fn();
        useMainStore().pageData.mockReturnValue(basePartResponse);
        useMainStore().lineItems = { glassParts: null };
        useMainStore().damage.isRepair = false;

        const { wrapper } = setupMocks({
            mountOptionsMockData: {
                router: {
                    navigate: jest.fn()
                },
                route: {
                    query: {
                        issPage: 'vehicle-parts'
                    }
                }
            }
        });

        // Act
        vehicleParts.beforeRouteEnter.call(
            wrapper.vm,
            { query: { issPage: 'vehicle-parts' } },
            undefined,
            (c) => c(wrapper.vm)
        );

        const arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
        await nextTick();

        // Assert
        expect(arePagePrerequisitesValid).toBe(true);
    });

    test('Initial data, should populate this.selectedGlassParts', async () => {
        // Arrange
        useMainStore().pageData = jest.fn();
        useMainStore().pageData.mockReturnValue(basePartResponse);
        useMainStore().lineItems = { glassParts: [{ partNumber: 'DB12209YPYNOEM' }] };

        const { wrapper } = setupMocks({
            mountOptionsMockData: {
                router: {
                    navigate: jest.fn()
                },
                route: {
                    query: {
                        issPage: 'vehicle-parts'
                    }
                }
            }
        });

        // Act
        vehicleParts.beforeRouteEnter.call(
            wrapper.vm,
            { query: { issPage: 'vehicle-parts' } },
            undefined,
            (c) => c(wrapper.vm)
        );

        await nextTick();

        // Assert
        expect(wrapper.vm.selectedGlassParts).toEqual({
            'Rear-Stationary': {
                partNumber: 'DB12209YPYNOEM',
                description: 'heated glass, solar, 1 hole',
                color: 'Gray Tint Privacy',
                requiresRecalibration: false,
                requiresCapabilityQuestions: false,
                childParts: null
            }
        });
    });

    test('User had part questions > navigateBack triggers a router.navigateWithoutSaving change with correct scenario', async () => {
        // Arrange
        const { wrapper } = setupMocks({
            mountOptionsMockData: {
                router: {
                    navigateWithSpinner: jest.fn()
                },
                route: {
                    query: {
                        issPage: 'vehicle-parts'
                    }
                }
            }
        });

        // Act
        vehicleParts.beforeRouteEnter.call(
            wrapper.vm,
            { query: { issPage: 'vehicle-parts' } },
            undefined,
            (c) => c(wrapper.vm)
        );

        wrapper.vm.navigateBackByVehicleQuestions();

        // Assert
        expect(wrapper.vm.$router.navigateWithSpinner).toHaveBeenCalledWith(
            navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS,
            wrapper.vm.$route
        );
    });

    test('User did not have part questions > navigateBack triggers a router.navigate change with correct scenario', async () => {
        // Arrange
        const { wrapper } = setupMocks({
            mountOptionsMockData: {
                router: {
                    navigateWithSpinner: jest.fn()
                },
                route: {
                    query: {
                        issPage: 'vehicle-parts'
                    }
                }
            }
        });

        // Act
        vehicleParts.beforeRouteEnter.call(
            wrapper.vm,
            { query: { issPage: 'vehicle-parts' } },
            undefined,
            (c) => c(wrapper.vm)
        );

        wrapper.vm.navigateBackByVehicleQuestions();

        // Assert
        expect(wrapper.vm.$router.navigateWithSpinner).toHaveBeenCalledWith(
            navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS,
            wrapper.vm.$route
        );
    });

    test('ForwardButtonAction triggers a router.navigate change if there are child part questions', async () => {
        // Arrange
        useMainStore().pageData = jest.fn();
        useMainStore().pageData.mockReturnValue({
            partsOrQuestions: [
                {
                    glassName: 'Single',
                    glassLocation: 'Windshield',
                    parts: [
                        {
                            partNumber: 'FW03861GTYN',
                            description:
                                'rain sensor, heated glass, auto dimming mirror, solar, 3rd visor band, condensation sensor',
                            color: 'Green Tint',
                            requiresRecalibration: false,
                            requiresCapabilityQuestions: false,
                            recalibrationType: null,
                            childParts: null,
                            childPartQuestions: [
                                {
                                    questionSequence: 1,
                                    questionText:
                                        'Does the rubber seal around your windshield have a chrome strip running through it?',
                                    answers: [
                                        {
                                            answerResult: 'WKT D1106 C',
                                            answerText: 'Yes',
                                            nextQuestionSequence: null
                                        },
                                        {
                                            answerResult: 'WKT D1106 B',
                                            answerText: 'No',
                                            nextQuestionSequence: null
                                        }
                                    ]
                                }
                            ]
                        }
                    ],
                    partQuestions: null
                }
            ]
        });
        useMainStore().lineItems = { glassParts: {} };

        const { wrapper } = setupMocks({
            mountOptionsMockData: {
                router: {
                    navigate: jest.fn()
                },
                route: {
                    query: {
                        issPage: 'vehicle-parts'
                    }
                }
            }
        });

        wrapper.setData({
            selectedGlassParts: { 'Rear-Stationary': { partNumber: 'FW03861GTYN' } }
        });

        // Act
        vehicleParts.beforeRouteEnter.call(
            wrapper.vm,
            { query: { issPage: 'vehicle-parts' } },
            undefined,
            (c) => c(wrapper.vm)
        );

        await wrapper.vm.forwardButtonAction();

        // Assert
        expect(wrapper.vm.$router.navigate).toHaveBeenCalled();
        expect(wrapper.vm.$router.navigate)
            .toHaveBeenCalledWith(
                'CLICKED_FORWARD_WITH_MOLDING_QUESTIONS',
                { query: { issPage: 'vehicle-parts' } },
                {},
                {},
                expect.anything()
            );
    });

    test('ForwardButtonAction triggers a router.navigate change if there are capability questions', async () => {
        // Arrange
        useMainStore().pageData = jest.fn();
        useMainStore().pageData.mockReturnValue({
            partsOrQuestions: [
                {
                    glassName: 'Single',
                    glassLocation: 'Windshield',
                    parts: [
                        {
                            partNumber: 'DB12209GTYN',
                            description: 'heated glass, solar, 1 hole',
                            color: 'Green Tint',
                            requiresRecalibration: false,
                            requiresCapabilityQuestions: true,
                            childParts: null
                        }
                    ],
                    partQuestions: null
                }
            ]
        });
        useMainStore().lineItems = { glassParts: {} };
        useMainStore().vehicle = { carId: 'TEST_CAR_ID' };

        const { wrapper } = setupMocks({
            mountOptionsMockData: {
                router: {
                    navigate: jest.fn()
                },
                route: {
                    query: {
                        issPage: 'vehicle-parts'
                    }
                },
                actionList: [
                    {
                        actionName: 'getCapabilityQuestions',
                        data: []
                    }
                ]
            }
        });

        wrapper.setData({
            selectedGlassParts: { 'Rear-Stationary': { partNumber: 'DB12209GTYN' } }
        });

        // Act
        vehicleParts.beforeRouteEnter.call(
            wrapper.vm,
            { query: { issPage: 'vehicle-parts' } },
            undefined,
            (c) => c(wrapper.vm)
        );

        await wrapper.vm.forwardButtonAction();

        // Assert
        expect(wrapper.vm.$router.navigate).toHaveBeenCalled();
        expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
            'CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS',
            { query: { issPage: 'vehicle-parts' } },
            {},
            {},
            expect.anything()
        );
    });
});
