// Components
import calendarOptions from '@/constants/calendar-options';

// Supporting Files
import { shallowMount, mount } from '@vue/test-utils';
import { getMountOptions } from '@/helpers/unit-test-helper.js';
import { useMainStore } from '@/store';
import addToCalendar from '@/layouts/order-confirmation/add-to-calendar/add-to-calendar.vue';
import { createTestingPinia } from '@pinia/testing';

const appointmentText = 'Appointment content';
function setupMocks({ customMountOptions }) {
    const mountOptions = getMountOptions({
        ...customMountOptions
    });
    mountOptions.mixins = [
        {
            methods: {
                getCmsContent: jest.fn().mockImplementation(() => appointmentText)
            }
        }
    ];
    const wrapper = shallowMount(addToCalendar, mountOptions);
    wrapper.vm.$refs.calendarModalQuestion.openModal = jest.fn();
    return { wrapper };
}

const calendarModalQuestionStub = {
    render: () => {}
};

const mockMixin = {
    methods: {
        getCmsContent: jest.fn().mockImplementation(() => appointmentText)
    }
};

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

    mountOptions.global.stubs = {
        calendarModalQuestion: calendarModalQuestionStub
    };

    const testingPinia = createTestingPinia({
        initialState: {
            main: mainInitialState
        }
    });
    useMainStore(testingPinia);
    methodToRun();

    mountOptions.global.mixins[0].methods.getSettingValue = jest.fn(() => 'false');
    mountOptions.global.plugins = [testingPinia];
    mountOptions.mixins = [mixin];
    mountOptions.data = () => (
        initialData
    );

    const wrapper = shallowMount(addToCalendar, mountOptions);
    wrapper.vm.$refs.calendarModalQuestion.openModal = jest.fn();
    return { wrapper };
}

beforeEach(() => {
    jest.restoreAllMocks();
    jest.clearAllMocks();
    useMainStore().submittedOrder = {
        schedule: {
            date: '2019-01-01',
            startTime: '09:00',
            endTime: '10:00',
            routeCode: '000'
        },
        lineItems: {
            glassParts: [
                {
                    partNumber: 'ABC123'
                }
            ],
            supportingItems: []
        },
        serviceLocation: {
            address: '',
            address2: null,
            city: '',
            state: 'AZ',
            appointmentType: 'Inshop',
            zipCode: '12345',
            zipCodeCtu: '01234',
            provider: {
                providerNumber: '123',
                address: {
                    streetAddress: 'test1',
                    city: 'test',
                    state: 'AZ',
                    zipCode: '12345',
                    zipCodeCtu: '01234'
                }
            }
        },
        damage: {
            isRepair: false
        },
        referralNumber: '1234567',
        payment: {
            isInsurance: true
        }
    };
});
afterEach(() => {
    useMainStore().submittedOrder = {};
    jest.restoreAllMocks();
    jest.clearAllMocks();
});

const sessionStorage = {
    schedule: {
        date: '2019-01-01',
        startTime: '09:00',
        endTime: '10:00',
        routeCode: '000'
    },
    lineItems: {
        glassParts: [
            {
                partNumber: 'ABC123'
            }
        ],
        supportingItems: []
    },
    serviceLocation: {
        address: '',
        address2: null,
        city: '',
        state: 'AZ',
        appointmentType: 'Inshop',
        zipCode: '12345',
        zipCodeCtu: '01234',
        provider: {
            providerNumber: '123',
            address: {
                streetAddress: 'test1',
                city: 'test',
                state: 'AZ',
                zipCode: '12345',
                zipCodeCtu: '01234'
            }
        }
    },
    damage: {
        isRepair: false
    },
    referralNumber: '1234567',
    payment: {
        isInsurance: true
    }
};

describe('Add-to-calendar methods...', () => {
    test('Add-to-calendar should trigger openModal method', () => {
        // Arrange
        const { wrapper } = setupMocks({
            customMountOptions: {
                propsData: {
                    appointment: {
                        RefrrlSeqNum: '123456',
                        StartDate: new Date(2023, 9, 11, 12, 0, 0),
                        EndDate: new Date(2023, 9, 11, 13, 0, 0),
                        Subject: 'Meeting with John',
                        Location: 'Conference Room',
                        Body: 'Discuss the project progress',
                        IsHTML: true,
                        Duration: '1220'
                    }
                }
            }
        });

        // Act
        wrapper.vm.openCalendarModal();

        // Assert
        expect(wrapper.vm.$refs.calendarModalQuestion.openModal).toBeCalled();
    });

    test('getCalendarData should return expected model value.', () => {
        // Arrange
        const type = calendarOptions.OUTLOOKCOM;
        const { wrapper } = setupMocks({
            customMountOptions: {
                propsData: {
                    appointment: {
                        RefrrlSeqNum: '123456',
                        StartDate: new Date(2023, 9, 11, 12, 0, 0),
                        EndDate: new Date(2023, 9, 11, 13, 0, 0),
                        Subject: 'Meeting with John',
                        Location: 'Conference Room',
                        Body: 'Discuss the project progress',
                        IsHTML: true,
                        Duration: '1220'
                    }
                }
            }
        });

        // Act
        const testValue = wrapper.vm.getCalendarData(type);

        // Assert
        expect(testValue.name).toEqual(calendarOptions.OUTLOOKCOM);
    });

    test('setCalendarAppointment should call getAppointment method for iCAL and Outlook.', () => {
        // Arrange
        const newValue = { name: calendarOptions.OUTLOOK };
        const { wrapper } = setupMocks({
            customMountOptions: {
                propsData: {
                    appointment: {
                        RefrrlSeqNum: '123456',
                        StartDate: new Date(2023, 9, 11, 12, 0, 0),
                        EndDate: new Date(2023, 9, 11, 13, 0, 0),
                        Subject: 'Meeting with John',
                        Location: 'Conference Room',
                        Body: 'Discuss the project progress',
                        IsHTML: true,
                        Duration: '1220'
                    }
                }
            }
        });
        wrapper.vm.getAppointment = jest.fn();
        // Act
        wrapper.vm.setCalendarAppointment(newValue);

        // Assert
        expect(wrapper.vm.getAppointment).toHaveBeenCalled();
    });
    test('setCalendarAppointment should call window.open for Google, yahoo and Outlook.com.', () => {
        // Arrange
        const newValue = { name: calendarOptions.GOOGLE };
        const { wrapper } = setupMocks({
            customMountOptions: {
                propsData: {
                    appointment: {
                        RefrrlSeqNum: '123456',
                        StartDate: new Date(2023, 9, 11, 12, 0, 0),
                        EndDate: new Date(2023, 9, 11, 13, 0, 0),
                        Subject: 'Meeting with John',
                        Location: 'Conference Room',
                        Body: 'Discuss the project progress',
                        IsHTML: true,
                        Duration: '1220'
                    }
                }
            }
        });
        window.open = jest.fn();

        // Act
        wrapper.vm.setCalendarAppointment(newValue);

        // Assert
        expect(window.open).toHaveBeenCalledTimes(1);
    });
});
