// Components
import addressLookup from '@/layouts/address-lookup/address-lookup.vue';

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

jest.mock('@/helpers/damage-helper', () => ({
    isGlassAvailableForCarId: jest.fn().mockImplementation(() => true),
    getDamageString: jest.fn()
}));

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

/** @ignore */
function setupMocks({
    lookupVinbyAddressResponse,
    partsOrQuestions = [],
    isStatePermissible = true,
    vinVehicles = [],
    carId = 'C0000',
    route = null
}) {
    useMainStore().lookupVinByAddress = jest.fn().mockImplementation(() => Promise.resolve({
        data: lookupVinbyAddressResponse || {
            isStatePermissible: true,
            vinVehicles: [
                {
                    vin: 'TEST_VIN',
                    vehicle: {
                        carId: 'CARID'
                    }
                }
            ]
        }
    }));

    useMainStore().getPartsOrQuestions = jest.fn().mockImplementation(() => Promise.resolve({
        data: {
            partsOrQuestions
        }
    }));

    const wrapper = shallowMount(
        addressLookup,
        getMountOptions({
            route: route || undefined,
            router: {
                navigate: jest.fn()
            },
            mainStore: {
                order: {
                    vehicle: {
                        carId,
                        registration: {
                            licensePlate: 'TESTPLATE',
                            zipCode: '12345'
                        }
                    },
                    customer: {
                        emailAddress: 'test@test.com'
                    },
                    serviceLocation: {
                        zipCode: '11111'
                    }
                }
            }

        })
    );

    const apiResponses = {
        vinLookupResponse: {
            isStatePermissible,
            vinVehicles
        }
    };

    settleAllPromises.mockImplementation(() => apiResponses);

    wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => '');
    wrapper.vm.setCmsContent = jest.fn();
    wrapper.vm.$router.navigateWithSpinner = jest.fn();
    wrapper.vm.navigateBack = baseMixin.methods.navigateBack;
    wrapper.vm.$refs.siteFooter.updateButtonText = jest.fn();
    wrapper.vm.$refs.siteFooter.disableForwardButton = jest.fn();
    wrapper.vm.$refs.siteFooter.enableForwardAction = jest.fn();

    return { wrapper };
}

describe('address-lookup.vue', () => {
    describe('page level alerts', () => {
        test('if the address matches a different vehicle display the Matched Different VehicleAlert', async () => {
            // Arrange
            const mockRegistrationAddress = {
                streetAddress: '1234 Main St',
                city: 'Columbus',
                state: 'OH',
                zipCode: '43215'
            };

            const { wrapper } = setupMocks({
                vinVehicles: [
                    {
                        vehicle: {
                            carId: 'C00000',
                            canSafeliteService: true
                        }
                    }
                ]
            });

            useMainStore().order.vehicle.carId = 'CARID2';

            await wrapper.setData({
                customerQuestions: {
                    addressQuestions: mockRegistrationAddress
                }
            });

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

            // Assert
            expect(wrapper.findComponent({ ref: 'alertMatchedDifferentVehicle' }).isVisible()).toBe(true);
        });

        test('if the address matches two identical YMM vehicles, then display Two Identical YMM Vehicle alert', async () => {
            // Arrange
            const mockRegistrationAddress = {
                streetAddress: '1234 Main St',
                city: 'Columbus',
                state: 'OH',
                zipCode: '43215'
            };

            const { wrapper } = setupMocks({
                vinVehicles: [
                    {
                        vehicle: {
                            carId: 'C00000',
                            canSafeliteService: true
                        }
                    }
                ]
            });

            useMainStore().order.vehicle.carId = 'CARID2';

            await wrapper.setData({
                customerQuestions: {
                    addressQuestions: mockRegistrationAddress
                },
                isTwoIdenticalYMMVehicleFound: true
            });

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

            // Assert
            expect(wrapper.findComponent({ ref: 'alertMatchedTwoIdenticalYMMVehicle' }).isVisible()).toBe(true);
        });

        // eslint-disable-next-line max-len
        test(
            'if the looking up VIN by address is not allowed in the state selected display the Vin Lookup By HomeAddress Not Allowed Alert',
            async () => {
            // Arrange
                const mockRegistrationAddress = {
                    streetAddress: '1234 Main St',
                    city: 'Columbus',
                    state: 'OH',
                    zipCode: '43215'
                };

                const { wrapper } = setupMocks({
                    isStatePermissible: false,
                    lookupVinbyAddressResponse: {
                        isStatePermissible: false,
                        vinVehicles: [
                            {
                                vin: 'TEST_VIN',
                                vehicle: {
                                    carId: 'CARID'
                                }
                            },
                            {
                                vin: 'TEST_VIN2',
                                vehicle: {
                                    carId: 'CARID2'
                                }
                            }
                        ]
                    }
                });

                useMainStore().order.vehicle.carId = 'CARID';

                await wrapper.setData({
                    customerQuestions: {
                        addressQuestions: mockRegistrationAddress
                    }
                });

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

                // Assert
                expect(wrapper.findComponent({ ref: 'alertVinLookupsByHomeAddressNotAllowed' }).isVisible()).toBe(true);
            }
        );

        test('if no vehicles found, display Vin Not Found alert', async () => {
            // Arrange
            const mockRegistrationAddress = {
                streetAddress: '1234 Main St',
                city: 'Columbus',
                state: 'OH',
                zipCode: '43215'
            };

            const { wrapper } = setupMocks({
                lookupVinbyAddressResponse: {
                    isStatePermissible: true,
                    vinVehicles: [] // Return no vehicles
                }
            });

            useMainStore().order.vehicle.carId = 'CARID';

            await wrapper.setData({
                customerQuestions: {
                    addressQuestions: mockRegistrationAddress
                }
            });

            wrapper.vm.navigateForward = jest.fn();

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

            // Assert
            expect(wrapper.findComponent({ ref: 'alertVinNotFound' }).isVisible()).toBe(true);
        });
    });

    describe('navigation', () => {
        test('if the back button is clicked, navigate back', async () => {
            // Arrange
            const { wrapper } = setupMocks({
            });

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

            // Assert
            expect(wrapper.vm.$router.navigateWithSpinner).toHaveBeenCalled();
        });

        test('if the car entered matches one of the vehicles found navigate forward', async () => {
            // Arrange
            const mockRegistrationAddress = {
                streetAddress: '1234 Main St',
                city: 'Columbus',
                state: 'OH',
                zipCode: '43215'
            };

            const { wrapper } = setupMocks({
                vinVehicles: [
                    {
                        vehicle: {
                            carId: 'C11111',
                            canSafeliteService: true
                        }
                    }
                ]
            });

            await wrapper.setData({
                previouslyEnteredCarId: 'C11111',
                customerQuestions: {
                    addressQuestions: mockRegistrationAddress
                }
            });

            wrapper.vm.navigateForward = jest.fn();

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

            // Assert
            expect(wrapper.vm.navigateForward).toHaveBeenCalled();
        });

        test('if the car entered does not match any of the multiple vehicles found, navigate to address-vehicles page', async () => {
            // Arrange
            const mockRegistrationAddress = {
                streetAddress: '1234 Main St',
                city: 'Columbus',
                state: 'OH',
                zipCode: '43215'
            };

            const { wrapper } = setupMocks({
                isStatePermissible: true,
                vinVehicles: [
                    {
                        vin: 'TEST_VIN',
                        vehicle: {
                            carId: 'CARID'
                        }
                    },
                    {
                        vin: 'TEST_VIN2',
                        vehicle: {
                            carId: 'CARID2'
                        }
                    }
                ]
            });

            useMainStore().order.vehicle.carId = 'CARID_A';

            const carsFound = [
                {
                    vin: 'TEST_VIN',
                    vehicle: {
                        carId: 'CARID'
                    }
                },
                {
                    vin: 'TEST_VIN2',
                    vehicle: {
                        carId: 'CARID2'
                    }
                }
            ];

            await wrapper.setData({
                customerQuestions: {
                    addressQuestions: mockRegistrationAddress
                }
            });

            wrapper.vm.updateVehicleInfo = jest.fn();

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

            // Assert
            expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
                navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_VEHICLES,
                undefined,
                {},
                {},
                carsFound
            );
        });

        // eslint-disable-next-line max-len
        test(
            'if a different vehicle is found than the one entered and the selected glass is not available for that vehicle, navigate back to vehicle-damage page',
            async () => {
            // Arrange
                const mockRegistrationAddress = {
                    streetAddress: '1234 Main St',
                    city: 'Columbus',
                    state: 'OH',
                    zipCode: '43215'
                };

                const { wrapper } = setupMocks({
                    isStatePermissible: true
                });

                await wrapper.setData({
                    customerQuestions: {
                        addressQuestions: mockRegistrationAddress
                    },
                    isCarIdDifferent: true,
                    isSelectedGlassAvailableForVehicle: false
                });

                useMainStore().order.vehicle.carId = 'CARID';

                const carsFound = [
                    {
                        vin: 'TEST_VIN2',
                        vehicle: {
                            carId: 'C0000'
                        }
                    }
                ];

                // Act
                await wrapper.vm.navigateForward(carsFound);

                // Assert
                expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
                    navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
                    undefined,
                    {},
                    { displayVehicleChangeAlert: true }
                );
            }
        );

        test('single car was found and matches entered vehicle => navigateForwardWithSingleCarMatch', async () => {
            // Arrange

            const carsFound = [
                {
                    vin: 'TEST_VIN_2',
                    vehicle: {
                        carId: 'C0000'
                    }
                }
            ];

            const { wrapper } = setupMocks({}, {});
            wrapper.vm.navigateForwardWithSingleCarMatch = jest.fn();

            useMainStore().order.vehicle.carId = 'C0000';

            // Act
            wrapper.vm.navigateForward(carsFound);

            // Assert
            expect(wrapper.vm.navigateForwardWithSingleCarMatch).toHaveBeenCalledTimes(1);
        });

        test('multiple cars were found and one matches entered vehicle => navigateForwardWithSingleCarMatch', async () => {
            // Arrange
            const carsFound = [
                {
                    vin: 'TEST_VIN_1',
                    vehicle: {
                        carId: 'C0000'
                    }
                },
                {
                    vin: 'TEST_VIN_2',
                    vehicle: {
                        carId: 'CARID2'
                    }
                },
                {
                    vin: 'TEST_VIN_3',
                    vehicle: {
                        carId: 'CARID3'
                    }
                }
            ];

            const { wrapper } = setupMocks({});
            wrapper.vm.navigateForwardWithSingleCarMatch = jest.fn();

            useMainStore().order.vehicle.carId = 'CARID3';

            // Act
            wrapper.vm.navigateForward(carsFound);

            // Assert
            expect(wrapper.vm.navigateForwardWithSingleCarMatch).toHaveBeenCalledTimes(1);
        });

        test('selected vehicle is a non-serviceable big truck, display no service alert', async () => {
            // Arrange
            const mockRegistrationAddress = {
                streetAddress: '1234 Main St',
                city: 'Columbus',
                state: 'OH',
                zipCode: '43215'
            };

            const { wrapper } = setupMocks({
                vinVehicles: [
                    {
                        vehicle: {
                            carId: 'BIGTRUCKCARID',
                            isBigTruck: true,
                            canSafeliteService: false
                        }
                    }
                ]
            });

            useMainStore().order.vehicle.carId = 'BIGTRUCKCARID';

            await wrapper.setData({
                customerQuestions: {
                    addressQuestions: mockRegistrationAddress
                }
            });

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

            // Assert
            expect(wrapper.findComponent({ ref: 'alertNoService' }).isVisible()).toBe(true);
        });
        test('selected vehicle is a serviceable big truck, do not display no service alert', async () => {
            // Arrange
            const mockRegistrationAddress = {
                streetAddress: '1234 Main St',
                city: 'Columbus',
                state: 'OH',
                zipCode: '43215'
            };

            const { wrapper } = setupMocks({
                vinVehicles: [
                    {
                        vehicle: {
                            carId: 'BIGTRUCKCARID2',
                            isBigTruck: true,
                            canSafeliteService: true
                        }
                    }
                ]
            });

            useMainStore().order.vehicle.carId = 'BIGTRUCKCARID2';

            await wrapper.setData({
                customerQuestions: {
                    addressQuestions: mockRegistrationAddress
                }
            });

            // Act
            await wrapper.vm.$nextTick();

            // Assert
            expect(wrapper.findComponent({ ref: 'alertNoService' }).exists()).toBe(false);
        });
    });
});
