import { mount } from '@vue/test-utils';
import crypto from 'crypto';
import serviceZipModalQuestion from '@/layouts/schedule-page/service-location/service-zip-modal-question/service-zip-modal-question.vue';

global.crypto = crypto;

jest.mock('@/digital-components/textbox-question/textbox-question', () => ({
    getCmsContent: jest.fn((widgetName, cmsFieldName) => widgetName[cmsFieldName])
}));

jest.mock('@/digital-components/modal/modal', () => ({
    methods: {
        closeModal: jest.fn()
    }
}));

const mockGetServiceabilityDetails = () => {
    const serviceabilityDetails = {
        isGlassServiceableInshop: true,
        isRecalibrationServiceableInshop: true,
        isGlassServiceableMobile: true,
        isRecalibrationServiceableMobile: true
    };

    return Promise.resolve(serviceabilityDetails);
};

const mockGetZipCodeData = (mockServiceZipCode) => {
    if (mockServiceZipCode === '43235') {
        return {
            containsMilitaryBase: false,
            isValid: true,
            state: 'OH',
            zipCodeCtu: '01820'
        };
    }

    if (mockServiceZipCode === '61606') {
        return {
            containsMilitaryBase: false,
            isValid: true,
            state: 'IL',
            zipCodeCtu: '01526'
        };
    }

    return {
        containsMilitaryBase: false,
        isValid: false,
        state: null,
        zipCodeCtu: null
    };
};

jest.mock(
    '@/helpers/service-location-helper',
    () => ({
        getServiceabilityDetails: jest.fn((mockServiceZipCode) => mockGetServiceabilityDetails(mockServiceZipCode)),
        getZipCodeData: jest.fn((mockServiceZipCode) => mockGetZipCodeData(mockServiceZipCode))
    })
);

const linkWidgetName = 'linkWidgetName';
const modalWidgetName = 'modalWidgetName';

const mockLinkCmsContent = {
    BodyText: 'Sample link body text here.'
};

const mockModalCmsContent = {
    FooterText: 'Sample modal footer text here.'
};

const mockMixin = {
    methods: {
        getCmsContent: jest.fn((widgetName, cmsFieldName) => {
            if (widgetName === linkWidgetName) {
                return mockLinkCmsContent[cmsFieldName];
            }

            if (widgetName === modalWidgetName) {
                return mockModalCmsContent[cmsFieldName];
            }
            return null;
        })
    }
};

describe('service-zip-modal-question.vue', () => {
    it('Initial state on load with existing location info', async () => {
        // Arrange
        const serviceZipCodeQuestion = {
            state: 'OH',
            zipCode: '43235'
        };

        const wrapper = mount(serviceZipModalQuestion, {
            mixins: [mockMixin],
            props: {
                modelValue: serviceZipCodeQuestion,
                linkWidgetName,
                modalWidgetName
            },
            attachTo: document.body
        });

        // Assert
        expect(wrapper.html()).not.toEqual(expect.stringContaining(mockLinkCmsContent.BodyText));
    });

    it('Should emit update:modelValue on setZipCode for a valid, serviceable zip', async () => {
        // Arrange
        const serviceZipCodeQuestion = {
            state: 'IL',
            zipCode: '61606'
        };

        const zip = '43235';

        const wrapper = mount(serviceZipModalQuestion, {
            mixins: [mockMixin],
            props: {
                modelValue: serviceZipCodeQuestion,
                mobileFeePart: {},
                modalWidgetName
            },
            attachTo: document.body
        });

        // Act
        wrapper.vm.internalModel.zipCode = zip;

        await wrapper.vm.setZipCode();

        const expectedEmit = [[{ state: 'OH', zipCode: '43235' }]];

        // Assert
        expect(wrapper.emitted('update:modelValue')).toEqual(expectedEmit);
    });

    it('Should not emit update:modelValue on setZipCode for an invalid zip', async () => {
        // Arrange
        const serviceZipCodeQuestion = {
            state: 'IL',
            zipCode: '61606'
        };

        const zip = '';

        const wrapper = mount(serviceZipModalQuestion, {
            mixins: [mockMixin],
            props: {
                modelValue: serviceZipCodeQuestion,
                modalWidgetName
            },
            attachTo: document.body
        });

        // Act
        wrapper.vm.internalModel.zipCode = zip;
        await wrapper.vm.setZipCode();

        // Assert
        expect(wrapper.emitted('update:modelValue')).not.toBeTruthy();
    });

    it('Should display invalid zip alerts for invalid ip inputs', async () => {
        // Arrange
        const serviceZipCodeQuestion = {
            state: 'IL',
            zipCode: '61606'
        };

        const zip = '11111';

        const wrapper = mount(serviceZipModalQuestion, {
            mixins: [mockMixin],
            props: {
                modelValue: serviceZipCodeQuestion,
                modalWidgetName
            },
            attachTo: document.body
        });

        // Act
        wrapper.vm.internalModel.zipCode = zip;
        await wrapper.vm.setZipCode();

        // Assert
        expect(wrapper.vm.displayInvalidZipAlert).toBe(true);
    });

    it('Should reset all alerts on onModalClosed', async () => {
        // Arrange
        const serviceZipCodeQuestion = {
            state: 'IL',
            zipCode: '61606'
        };

        const zip = '';

        const wrapper = mount(serviceZipModalQuestion, {
            mixins: [mockMixin],
            props: {
                modelValue: serviceZipCodeQuestion,
                modalWidgetName
            },
            attachTo: document.body
        });

        // Act
        wrapper.vm.internalModel.zipCode = zip;
        await wrapper.vm.setZipCode();
        wrapper.vm.onModalClosed();

        // Assert
        expect(wrapper.vm.displayInvalidZipAlert).toBe(false);
    });

    it('Should prepopulate the zip on onModalOpened', async () => {
        // Arrange
        const serviceZipCodeQuestion = {
            state: 'IL',
            zipCode: '61606'
        };

        const zip = '123';

        const wrapper = mount(serviceZipModalQuestion, {
            mixins: [mockMixin],
            props: {
                modelValue: serviceZipCodeQuestion,
                modalWidgetName
            },
            attachTo: document.body
        });

        // Act
        wrapper.vm.internalModel.zipCode = zip;
        wrapper.vm.onModalOpened();

        // Assert
        expect(wrapper.vm.internalModel.zipCode).toEqual('61606');
    });
});
