// Components
import tpaConfirmation from '@/layouts/tpa-confirmation/tpa-confirmation.vue';

// Supporting Files
import { getEnumName, getMountOptions } from '@/helpers/unit-test-helper.js';
import { getDefaultState, useMainStore } from '@/store/index.js';
import settleAllPromises from '@/helpers/layout-helper.js';
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
import { mount } from '@vue/test-utils';
import { createTestingPinia } from '@pinia/testing';
import coverageStatuses from '@/constants/coverage-statuses';
import { deepClone } from '@/helpers/object-helper';

jest.mock('@/helpers/layout-helper.js', () => jest.fn());

jest.mock('@/helpers/cms-content-helper', () => ({
    fetchCmsContentForPage: jest.fn(),
    processIfStatements: jest.fn(),
    doesCopyContainRouterLink: jest.fn(),
    splitCopyOnCMSPlaceHolder: jest.fn().mockImplementation(() => 'test'),
    getRouterLinkRouteFromCopy: jest.fn(),
    getRouterLinkDisplayTextFromCopy: jest.fn(),
    doesCopyContainTextLink: jest.fn()
}));

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

const footerStub = {
    render: () => {},
    methods: {
        updateButtonText: jest.fn()
    }
};

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

    mountOptions.global.stubs = {
        siteFooter: footerStub
    };
    const testingPinia = createTestingPinia({
        initialState: {
            main: mainInitialState
        }
    });
    const store = useMainStore(testingPinia);
    store.order = getDefaultState().order;
    store.hasSubmittedOrder = jest.fn().mockReturnValue(true);
    methodToRun();

    mountOptions.global.plugins = [testingPinia];
    mountOptions.mixins = [mockMixin];
    mountOptions.data = () => (
        initialData
    );

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

    const wrapper = mount(tpaConfirmation, mountOptions);
    return { wrapper };
}

const defaultOrder = {
    serviceLocation: {
        provider: {
            companyName: 'Hershey',
            phoneNumber: '726-117-0377'
        }
    },
    currentDeductible: 479,
    isVerified: false,
    carrierPhoneNumber: '757-277-0388',
    vehicle: {
        imageUrl: 'url for image',
        category: 'car'
    }
};

describe('TPAConfirmation.vue', () => {
    describe('Rendering', () => {
        let wrapper;
        let mockStoreActions;
        beforeEach(() => {
            mockStoreActions = () => {
                useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => defaultOrder);
            };
            wrapper = getMountedComponent({}, {}, mockStoreActions).wrapper;
        });
        test('Should render Site Header', () => {
            // Act
            const siteHeader = wrapper.findComponent({ ref: 'siteHeader' });

            // Assert
            expect(siteHeader.exists()).toBe(true);
        });
        test('Should render Confirmation Body One', () => {
            // Act
            const bodyOne = wrapper.findComponent({ ref: 'tpaConfirmationBodyOne' });

            // Assert
            expect(bodyOne.exists()).toBe(true);
        });
        test('Should render Confirmation Body Two', () => {
            // Act
            const bodyTwo = wrapper.findComponent({ ref: 'tpaConfirmationBodyTwo' });

            // Assert
            expect(bodyTwo.exists()).toBe(true);
        });
        test('Should render Order Details title', () => {
            // Act
            const orderDetailsTitle = wrapper.findComponent({ ref: 'tpaConfirmationOrderDetailsTitle' });

            // Assert
            expect(orderDetailsTitle.exists()).toBe(true);
        });
        test('Should render Order Details body', () => {
            // Act
            const orderDetailsBody = wrapper.findComponent({ ref: 'tpaConfirmationOrderDetailsBody' });

            // Assert
            expect(orderDetailsBody.exists()).toBe(true);
        });
        test('Should render Deductible Box', () => {
            // Act
            const deductibleBox = wrapper.findComponent({ ref: 'deductibleBox' });

            // Assert
            expect(deductibleBox.exists()).toBe(true);
        });
        test('If Advanced flow, should display Site Footer', () => {
            // Arrange
            const carrierReturnUrl = 'testURL';
            const initialStore = {
                issConfig: {
                    successReturnURL: carrierReturnUrl
                }
            };
            wrapper = getMountedComponent(initialStore, {}, mockStoreActions).wrapper;

            // Act
            const siteFooter = wrapper.findComponent({ ref: 'siteFooter' });

            // Assert
            expect(siteFooter.exists()).toBe(true);
        });
        test('If Essential flow, should not display Site Footer', () => {
            // Act
            const siteFooter = wrapper.findComponent({ ref: 'siteFooter' });

            // Assert
            expect(siteFooter.isVisible()).toBe(false);
        });
    });
    describe('Computed properties', () => {
        describe('Deductible Box value', () => {
            test('Should return "Verifying coverage" when isVerified false', () => {
                // Arrange
                const initialStore = {
                    order: {
                        insuranceCoverage: {
                            coverageStatus: coverageStatuses.PENDING
                        }
                    }
                };
                const mockStoreActions = () => {
                    useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => defaultOrder);
                };
                const { wrapper } = getMountedComponent(initialStore, {}, mockStoreActions);
                const expected = 'Verifying coverage';

                // Assert
                expect(wrapper.vm.deductibleBoxValue).toBe(expected);
            });
            test('Should return deductible value when isVerified true', () => {
                // Arrange
                const currentDeductible = '500';
                const initialStore = {
                    order: {
                        insuranceCoverage: {
                            coverageStatus: coverageStatuses.VERIFIED
                        },
                        currentDeductible
                    }
                };
                const order = deepClone(defaultOrder);
                order.isVerified = true;
                const mockStoreActions = () => {
                    useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
                };
                const { wrapper } = getMountedComponent(initialStore, {}, mockStoreActions);
                const notExpected = 'Verifying coverage';

                // Assert
                expect(wrapper.vm.deductibleBoxValue).not.toBe(notExpected);
            });
        });
    });
    describe('Methods', () => {
        describe.only('getCustomValueFromString', () => {
            describe.each([
                [false, false, 0],
                [false, false, 500],
                [false, true, 0],
                [true, true, 500]
            ])('with argument deductibleAboveZero', (expected, isVerified, deductible) => {
                test(`returns ${expected} when coverageStatus is ${getEnumName(coverageStatuses, status)} and currentDeductible is ${deductible}`, () => {
                    // Arrange
                    const order = deepClone(defaultOrder);
                    order.isVerified = isVerified;
                    order.currentDeductible = deductible;
                    const mockStoreActions = () => {
                        useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
                    };
                    const { wrapper } = getMountedComponent({}, {}, mockStoreActions);
                    const argument = 'deductibleAboveZero';

                    // Act
                    const result = wrapper.vm.getCustomValueFromString(argument);

                    // Assert
                    expect(result).toBe(expected);
                });
            });
            describe('with argument zeroDeductible', () => {
                describe.each([
                    [false, false, 0],
                    [false, false, 500],
                    [true, true, 0],
                    [false, true, 500]
                ])('with argument zeroDeductible', (expected, isVerified, deductible) => {
                    test(`returns ${expected} when coverageStatus is ${getEnumName(coverageStatuses, status)} and currentDeductible is ${deductible}`, () => {
                        // Arrange
                        const order = deepClone(defaultOrder);
                        order.isVerified = isVerified;
                        order.currentDeductible = deductible;
                        const mockStoreActions = () => {
                            useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
                        };
                        const { wrapper } = getMountedComponent({}, {}, mockStoreActions);
                        const argument = 'zeroDeductible';

                        // Act
                        const result = wrapper.vm.getCustomValueFromString(argument);

                        // Assert
                        expect(result).toBe(expected);
                    });
                });
            });
            describe('with argument verifyingCoverage', () => {
                describe.each([
                    [true, false],
                    [false, true]
                ])('with argument zeroDeductible', (expected, isVerified) => {
                    test(`returns ${expected} when coverageStatus is ${getEnumName(coverageStatuses, status)}`, () => {
                        // Arrange
                        const order = deepClone(defaultOrder);
                        order.isVerified = isVerified;
                        order.currentDeductible = 123;
                        const mockStoreActions = () => {
                            useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
                        };
                        const { wrapper } = getMountedComponent({}, {}, mockStoreActions);
                        const argument = 'verifyingCoverage';

                        // Act
                        const result = wrapper.vm.getCustomValueFromString(argument);

                        // Assert
                        expect(result).toBe(expected);
                    });
                });
            });
        });
        describe('Navigation', () => {
            const mockStoreActions = () => {
                useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => defaultOrder);
            };
            test('If Advanced flow, forward button action navigates to carrier URL', () => {
                // Arrange
                const carrierReturnUrl = 'testURL';
                const initialStore = {
                    issConfig: {
                        successReturnURL: carrierReturnUrl
                    }
                };
                const { wrapper } = getMountedComponent(initialStore, {}, mockStoreActions);

                // Act
                wrapper.vm.forwardButtonAction();

                // Assert
                expect(wrapper.vm.$router.navigateToExternalUrl).toHaveBeenCalledWith(carrierReturnUrl);
            });
        });
    });
});
