/* eslint-env jest */
import { mount } from '@vue/test-utils';
import baseMixin from '@/mixins/base-mixin';
import navigationScenarios from '@/router/router-constants/navigation-scenarios';
import queryStrings from '@/constants/query-strings';
import { GaActions } from '@/constants/analytics';
import vinLookupMethodSelections from '@/constants/vin-lookup-methods';
import { useMainStore } from '@/store';
import { createTestingPinia } from '@pinia/testing';
import { mapStores } from 'pinia';
import { defineRule } from 'vee-validate';
import errorMessages from '@/constants/error-messages';
import globalRules from '@/constants/global-rules';
import { required } from '@/helpers/validation-rules';
import VehicleLookup from '@/layouts/vehicle-lookup/vehicle-lookup.vue';

const pinia = createTestingPinia();
useMainStore(pinia);

const vinLookupMethodsMockData = {
    QuestionText: 'To find the right part, let’s get your VIN.  Or we can look it up for you!',
    Answers: [
        {
            Name: 'ManualVin',
            Text: 'Provide my VIN manually',
            SubText: 'Most specific to your vehicle',
            ImageId: '',
            SubWidgetName: ''
        },
        {
            Name: 'LicensePlate',
            Text: 'Provide my license plate #',
            SubText: 'Most accurate VIN match',
            ImageId: '',
            SubWidgetName: ''
        },
        {
            Name: 'HomeAddress',
            Text: 'Provide my home address',
            SubText: 'Most convenient VIN match',
            ImageId: '',
            SubWidgetName: ''
        }
    ]
};

const siteFooterWidgetMockData = {
    ForwardButtonText: 'Continue'
};

function setupMocks() {
    defineRule(globalRules.OPTION_REQUIRED, required(errorMessages.OPTION_REQUIRED));
    const mockRoute = {
        query: {
            issPage: 'vehicle-lookup'
        }
    };

    const mockRouter = {
        navigate: jest.fn(),
        navigateWithSpinner: jest.fn()
    };

    const mockIsVinbyAddressPermissibleToBeFalse = {
        IsVinbyAddressPermissible: false
    };

    const wrapper = mount(VehicleLookup, {
        data() {
            return {
                selectedVinLookupMethod: null
            };
        },
        global: {
            mixins: [
                {
                    computed: {
                        ...mapStores(useMainStore),
                        GaActions() {
                            return GaActions;
                        },
                        queryStrings() {
                            return queryStrings;
                        },
                        navigationScenarios() {
                            return navigationScenarios;
                        }
                    },
                    methods: {
                        getCmsContent: jest.fn((cmsWidgetName, fieldName) => {
                            if (cmsWidgetName === 'SiteFooterWidget') {
                                if (fieldName === 'ForwardButtonText') {
                                    return siteFooterWidgetMockData.ForwardButtonText;
                                }
                            }

                            if (cmsWidgetName === 'VINLookupMethod') {
                                if (fieldName === 'QuestionText') {
                                    return vinLookupMethodsMockData.QuestionText;
                                }
                                if (fieldName === 'Answers') {
                                    return vinLookupMethodsMockData.Answers;
                                }
                            }

                            return '';
                        }),
                        getFooterInfoBoxHeight: jest.fn(() => 80),
                        getPageNameByQueryString: jest.fn(() => 'vehicle-lookup'),
                        pushEventToGA: jest.fn(),
                        navigateBack: baseMixin.methods.navigateBack
                    }
                }
            ],
            mocks: {
                $route: mockRoute,
                $router: mockRouter
            },
            stubs: {
                SiteHeader: true,
                SiteSubHeader: true
            }
        }
    });

    // wrapper.vm.navigateBack = baseMixin.methods.navigateBack;

    return { mockRoute, mockRouter, wrapper, mockIsVinbyAddressPermissibleToBeFalse };
}

describe('vehicle-lookup.vue', () => {
    test('IsVinbyAddressPermissible to be false', () => {
        const { wrapper, mockIsVinbyAddressPermissibleToBeFalse } = setupMocks();

        const vinLookupMethodsWrapper = wrapper.findComponent({ name: 'vin-lookup-methods' });
        // Not using initializeComponent() because it doesn't trigger reactivity in test.
        const Answers = JSON.parse(JSON.stringify(vinLookupMethodsMockData.Answers));
        if (!mockIsVinbyAddressPermissibleToBeFalse.IsVinbyAddressPermissible) {
            Answers.splice(Answers.indexOf(vinLookupMethodSelections.HOMEADDRESS), 1);
        }
        vinLookupMethodsWrapper.setData({
            questionTextFromCms: vinLookupMethodsMockData.QuestionText,
            answersFromCms: Answers
        });

        const lookupByAddressOptionLabel = wrapper
            .find('[data-test-id="vin-lookup-methods-button-question"] label[for="VinLookupMethods-HomeAddress"]');
        expect(lookupByAddressOptionLabel.exists()).toBe(false);
    });

    test('"Continue" button is disabled when no VIN Lookup method is selected.', () => {
        const { wrapper } = setupMocks();

        const continueButton = wrapper.get('[data-test-id="site-footer-main-button"]');
        expect(continueButton.attributes()['aria-disabled']).toBe('true');
    /**
     * To Do: Review if need to use VeeValidate meta.valid to check whether an element is disabled.
     * The issue if relying on VeeValidate meta is not available inside the script
     * (can only be used inside a template)
     */
    });

    test('"Continue" button is enabled after a VIN Lookup method is selected.', async () => {
        const { wrapper } = setupMocks();

        const vinLookupMethodsWrapper = wrapper.findComponent({ name: 'vin-lookup-methods' });
        // Not using initializeComponent() because it doesn't trigger reactivity in test.
        await vinLookupMethodsWrapper.setData({
            questionTextFromCms: vinLookupMethodsMockData.QuestionText,
            answersFromCms: vinLookupMethodsMockData.Answers
        });

        const lookupByManualVinOptionLabel = wrapper
            .find('[data-test-id="vin-lookup-methods-button-question"] label[for="VinLookupMethods-ManualVin"]');
        await lookupByManualVinOptionLabel.trigger('mousedown');

        const continueButton = wrapper.get('[data-test-id="site-footer-main-button"]');
        expect(continueButton.attributes()['aria-disabled']).toBe('false');
    });

    test('Click the back button, trigger navigate function from Vue Router with CLICKED_BACK parameter.', async () => {
        const { mockRoute, mockRouter, wrapper } = setupMocks();

        await wrapper.get('[data-test-id="site-footer-back-button"]').trigger('click');
        expect(mockRouter.navigateWithSpinner).toHaveBeenCalledTimes(1);
        expect(mockRouter.navigateWithSpinner)
            .toHaveBeenCalledWith(navigationScenarios.CLICKED_BACK, mockRoute);
    });

    test('Select "Provide VIN Manually" then click "Continue". Navigates to "vin-lookup" page.', async () => {
        const { mockRoute, mockRouter, wrapper } = setupMocks();

        const vinLookupMethodsWrapper = wrapper.findComponent({ name: 'vin-lookup-methods' });
        // Not using initializeComponent() because it doesn't trigger reactivity in test.
        await vinLookupMethodsWrapper.setData({
            questionTextFromCms: vinLookupMethodsMockData.QuestionText,
            answersFromCms: vinLookupMethodsMockData.Answers
        });

        const lookupByManualVinOptionLabel = wrapper
            .find('[data-test-id="vin-lookup-methods-button-question"] label[for="VinLookupMethods-ManualVin"]');
        await lookupByManualVinOptionLabel.trigger('mousedown');

        const continueButton = wrapper.get('[data-test-id="site-footer-main-button"]');
        await continueButton.trigger('click');

        expect(mockRouter.navigate).toHaveBeenCalledTimes(1);
        expect(mockRouter.navigate)
            .toHaveBeenCalledWith(navigationScenarios.SELECTED_MANUAL_VIN, mockRoute);
    /**
     * To Do: find a way to confirm that Vue Router really routes to the expected page.
     * Currently just trust that our custom navigate() method does its job properly.
     */
    });

    test('Select "Provide My License Plate Number" then click "Continue". Navigates to "license-plate-lookup" page.', async () => {
        const { mockRoute, mockRouter, wrapper } = setupMocks();

        const vinLookupMethodsWrapper = wrapper.findComponent({ name: 'vin-lookup-methods' });
        // Not using initializeComponent() because it doesn't trigger reactivity in test.
        await vinLookupMethodsWrapper.setData({
            questionTextFromCms: vinLookupMethodsMockData.QuestionText,
            answersFromCms: vinLookupMethodsMockData.Answers
        });

        const lookupByLicensePlateOptionLabel = wrapper
            .find('[data-test-id="vin-lookup-methods-button-question"] label[for="VinLookupMethods-LicensePlate"]');
        await lookupByLicensePlateOptionLabel.trigger('mousedown');

        const continueButton = wrapper.get('[data-test-id="site-footer-main-button"]');
        await continueButton.trigger('click');

        expect(mockRouter.navigate).toHaveBeenCalledTimes(1);
        expect(mockRouter.navigate)
            .toHaveBeenCalledWith(navigationScenarios.SELECTED_LICENSE_PLATE, mockRoute);
    /**
     * To Do: find a way to confirm that Vue Router really routes to the expected page.
     * Currently just trust that our custom navigate() method does its job properly.
     */
    });

    test('Select "Provide My Home Address" then click "Continue". Navigates to "address-lookup" page.', async () => {
        const { mockRoute, mockRouter, wrapper } = setupMocks();

        const vinLookupMethodsWrapper = wrapper.findComponent({ name: 'vin-lookup-methods' });
        // Not using initializeComponent() because it doesn't trigger reactivity in test.
        await vinLookupMethodsWrapper.setData({
            questionTextFromCms: vinLookupMethodsMockData.QuestionText,
            answersFromCms: vinLookupMethodsMockData.Answers
        });

        const lookupByAddressOptionLabel = wrapper
            .find('[data-test-id="vin-lookup-methods-button-question"] label[for="VinLookupMethods-HomeAddress"]');
        await lookupByAddressOptionLabel.trigger('mousedown');

        const continueButton = wrapper.get('[data-test-id="site-footer-main-button"]');
        await continueButton.trigger('click');

        expect(mockRouter.navigate).toHaveBeenCalledTimes(1);
        expect(mockRouter.navigate)
            .toHaveBeenCalledWith(navigationScenarios.SELECTED_HOME_ADDRESS, mockRoute);
    /**
     * To Do: find a way to confirm that Vue Router really routes to the expected page.
     * Currently just trust that our custom navigate() method does its job properly.
     */
    });

    /**
     * To Do: Error message is not displayed when running test
     * but in reality it shows up. Need to find out
     * how to write a test that verifies the error message is displayed.
     */
    // test.only('Error message is diplayed when no selection is made
    // and "Continue" button clicked.', async () => {
    //   const { wrapper } = setupMocks();

    //   const vinLookupMethodsWrapper = wrapper.findComponent({ name: 'vin-lookup-methods' });
    //   // Not using initializeComponent() because it doesn't trigger reactivity in test.
    //   await vinLookupMethodsWrapper.setData({
    //     questionTextFromCms: vinLookupMethodsMockData.QuestionText,
    //     answersFromCms: vinLookupMethodsMockData.Answers,
    //   });

    //   // const lookupByManualVinOptionLabel =
    // // wrapper.find('[data-test-id="vin-lookup-methods-button-question"]
    // //label[for="VinLookupMethods-ManualVin"]');
    //   // await lookupByManualVinOptionLabel.trigger('mousedown');

    //   const continueButton = wrapper.get('[data-test-id="site-footer-main-button"]');
    //   await continueButton.trigger('click');

    //   await flushPromises();
    //   await nextTick();

    //   console.log(vinLookupMethodsWrapper.get('.form-test-error').html());
    //   //const veeValidateForm = wrapper.findComponent()
    //   //console.log(wrapper.emitted());
    //   // console.log(vinLookupMethodsWrapper.html());
    //   // console.log(vinLookupMethodsWrapper.get('.form-test-error').html());
    //   // console.log(vinLookupMethodsWrapper.get('.form-test-error').text());
    //   // expect(vinLookupMethodsWrapper.get('.form-test-error').);
    // });
});
