import { shallowMount } from '@vue/test-utils';
import { createTestingPinia } from '@pinia/testing';
import welcomePage from '@/layouts/welcome-page/welcome-page.vue';

// Supporting files
import settleAllPromises from '@/helpers/layout-helper.js';
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
import baseMixin from '@/mixins/base-mixin.js';
import { getMountOptions } from '@/helpers/unit-test-helper.js';
import applicationConfig from '@/constants/application-config';
import { useMainStore } from '@/store';
import navigationScenarios from '@/router/router-constants/navigation-scenarios';
import routerParams from '@/router/router-constants/router-params';
import coverageType from '@/constants/coverage-type';

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

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

/** @ignore */
function setupMocks({
    pageHeaderWidgetHeaderText = {},
    pageFooterWidgetCmsContent = {},
    mountOptionsMockData = {},
    policies = [],
    getCoveragePolicyInfoResponse
}) {
    useMainStore().getCoveragePolicyInfo = jest.fn().mockImplementation(() => Promise.resolve({
        data: getCoveragePolicyInfoResponse || {
            policies: [
                {
                    insureds: [
                        {
                            customerId: 'TEST_ID'
                        }
                    ],
                    vehicles: [
                        {
                            vin: 'TEST_VIN'
                        },
                        {
                            vin: 'TEST_VIN2'
                        }
                    ]
                }
            ]
        }
    }));

    // Mock api responses
    const apiResponses = {
        cmsContent: {
            SiteSubHeaderWidget: pageHeaderWidgetHeaderText,
            SiteHeaderWidget: {
                LogoImage:
                    `${applicationConfig.ISS_DEV_CMS_DOMAIN}/images/default-source/default-album/logos/insuranceLogo.jpg`
            },
            SiteFooterWidget: pageFooterWidgetCmsContent
        },
        policyLookupResponse: {
            policies
        }
    };

    const mockDataMountOptions = {
        ...mountOptionsMockData,
        router: {
            navigate: jest.fn()
        }
    };

    const apiPromise = Promise.resolve(apiResponses);

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

    const mountOptions = getMountOptions(mockDataMountOptions);

    const wrapper = shallowMount(welcomePage, mountOptions);

    wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent;
    wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => '');
    return { wrapper, apiPromise };
}

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

    mountOptions.global.stubs = {
        siteHeader: true,
        recalModal: true,
        contentGroupModal: true,
        alert: true
    };
    mountOptions.global.plugins = [createTestingPinia({
        initialState: {
            main: mainInitialState
        }
    })];
    mountOptions.data = () => (
        initialData
    );

    const apiResponses = {
        supportingItems: []
    };
    const apiPromise = Promise.resolve(apiResponses);
    settleAllPromises.mockImplementation(() => apiPromise);
    fetchCmsContentForPage.mockImplementation(() => Promise.resolve());

    const wrapper = shallowMount(welcomePage, mountOptions);
    return { wrapper };
}

describe('welcome-page.vue', () => {
    test('Should render welcomePage sub-components (policyNumber, policyZipCode, dateOfLoss, damageCause etc.)', async () => {
        // Arrange
        const { wrapper } = setupMocks({});

        // Act
        const policyNumber = wrapper.findComponent({ ref: 'policyNumber' });
        const dateOfLoss = wrapper.findComponent({ ref: 'dateOfLoss' });
        const damageCause = wrapper.findComponent({ ref: 'damageCause' });
        const damageCity = wrapper.findComponent({ ref: 'damageCity' });
        const state = wrapper.findComponent({ ref: 'state' });
        const glassOnlyDamage = wrapper.findComponent({ ref: 'glassOnlyDamage' });
        const phoneNumber = wrapper.findComponent({ ref: 'phoneNumber' });

        // Assert
        expect(policyNumber.exists()).toBe(true);
        expect(dateOfLoss.exists()).toBe(true);
        expect(damageCause.exists()).toBe(true);
        expect(damageCity.exists()).toBe(false);
        expect(state.exists()).toBe(false);
        expect(glassOnlyDamage.exists()).toBe(false);
        expect(phoneNumber.exists()).toBe(true);
    });
    test('Policy zip field should be visible at all times', async () => {
        // Arrange
        const { wrapper } = setupMocks({});

        // Act
        await wrapper.vm.$nextTick();
        const policyZip = wrapper.findComponent({ ref: 'policyZip' });

        // Assert
        expect(policyZip.exists()).toBe(true);
    });
});

describe('navigation', () => {
    describe('When zip code check fails', () => {
        test('Navigation should not happen', async () => {
            // Arrange
            const { wrapper } = setupMocks({});
            wrapper.vm.mainStore.getDuplicateReferrals = jest.fn().mockImplementation(() => Promise.resolve({}));
            wrapper.vm.mainStore.applicationUser.duplicateOrders = [{ test: 'a' }];
            wrapper.vm.mainStore.validateZip = jest.fn().mockImplementation(() => Promise.reject());

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

            // Assert
            expect(wrapper.vm.$router.navigate).toHaveBeenCalledTimes(0);
        });
    });

    describe('When zip code check succeeds', () => {
        test('if duplicates found, navigate to duplicate check page', async () => {
            // Arrange
            const { wrapper } = getMountedComponent({});
            useMainStore().getDuplicateReferrals = jest.fn().mockImplementation(() => Promise.resolve({}));
            useMainStore().applicationUser.duplicateOrders = [{ test: 'a' }];
            wrapper.vm.mainStore.validateZip = jest.fn().mockImplementation(() => Promise.resolve({
                data: {
                    isValid: true
                }
            }));

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

            // Assert
            expect(wrapper.vm.mainStore.getDuplicateReferrals).toHaveBeenCalled();
            expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
                navigationScenarios.CLICKED_FORWARD_WITH_DUPLICATES,
                undefined,
                {},
                { [routerParams.SKIP_SAVE_SESSION]: true }
            );
        });
        test('if policy and vehicles are found but no duplicates, navigate to policy-vehicle page', async () => {
            // Arrange
            const { wrapper } = setupMocks({});
            useMainStore().getDuplicateReferrals = jest.fn().mockImplementation(() => Promise.resolve({}));

            useMainStore().applicationUser.duplicateOrders = [];
            useMainStore().order.insuranceCoverage.coverageType = coverageType.Deductible;
            useMainStore().order.policy.vehicles = [
                { vin: 'TEST_VIN' },
                { vin: 'TEST_VIN2' }
            ];
            wrapper.vm.mainStore.validateZip = jest.fn().mockImplementation(() => Promise.resolve({
                data: {
                    isValid: true
                }
            }));

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

            // Assert
            expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
                navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES,
                undefined,
                {},
                { [routerParams.SKIP_SAVE_SESSION]: true }
            );
        });
        test('if policy is found, but no vehicles and no duplicates, navigate to vehicle-selection page', async () => {
            // Arrange
            const { wrapper } = setupMocks({});
            useMainStore().getDuplicateReferrals = jest.fn().mockImplementation(() => Promise.resolve({}));

            useMainStore().applicationUser.duplicateOrders = [];
            useMainStore().order.insuranceCoverage.coverageType = coverageType.Deductible;
            useMainStore().order.policy.vehicles = [];
            wrapper.vm.mainStore.validateZip = jest.fn().mockImplementation(() => Promise.resolve({
                data: {
                    isValid: true
                }
            }));

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

            // Assert
            expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
                navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES,
                undefined,
                {},
                { [routerParams.SKIP_SAVE_SESSION]: true }
            );
        });
        test('if policy is found, but null vehicles and no duplicates, navigate to vehicle-selection page', async () => {
            // Arrange
            const { wrapper } = setupMocks({});
            useMainStore().getDuplicateReferrals = jest.fn().mockImplementation(() => Promise.resolve({}));

            useMainStore().applicationUser.duplicateOrders = [];
            useMainStore().order.insuranceCoverage.coverageType = coverageType.Deductible;
            useMainStore().order.policy.vehicles = null;

            wrapper.vm.mainStore.validateZip = jest.fn().mockImplementation(() => Promise.resolve({
                data: {
                    isValid: true
                }
            }));

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

            // Assert
            expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
                navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES,
                undefined,
                {},
                { [routerParams.SKIP_SAVE_SESSION]: true }
            );
        });
        test('if policy is not found and no duplicates, navigate to policy-holder-details page', async () => {
            // Arrange
            const { wrapper } = setupMocks({});
            useMainStore().getDuplicateReferrals = jest.fn().mockImplementation(() => Promise.resolve({}));

            useMainStore().order.insuranceCoverage.coverageType = coverageType.NONE;
            useMainStore().applicationUser.duplicateOrders = [];

            wrapper.vm.mainStore.validateZip = jest.fn().mockImplementation(() => Promise.resolve({
                data: {
                    isValid: true
                }
            }));

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

            // Assert
            expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
                navigationScenarios.CLICKED_FORWARD_POLICY_UNVERIFIED,
                undefined,
                {},
                { [routerParams.SKIP_SAVE_SESSION]: true }
            );
        });
        test('getDuplicateReferrals throws rejected promise => navigate called', async () => {
            // Arrange
            const { wrapper } = setupMocks({});
            const error = 'duplicate referrals error';
            useMainStore().getDuplicateReferrals = jest.fn().mockImplementation(() => Promise.reject(error));
            wrapper.vm.mainStore.validateZip = jest.fn().mockImplementation(() => Promise.resolve({
                data: {
                    isValid: true
                }
            }));

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

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