// Components
import partQuestions from "@/layouts/part-questions/part-questions";

// Supporting Files
import { shallowMount } from "@vue/test-utils";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
import store from "@/store";
import { storeActions } from "@/constants/store-actions";
import { storeMutations } from "@/constants/store-mutations";
import { settleAllPromises } from "@/helpers/layout-helper.js";
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import baseMixin from "../../mixins/base-mixin";
import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin";
import { nextTick } from "vue";

// Mock our module for promises.
jest.mock("@/helpers/layout-helper.js", () => ({
    settleAllPromises: jest.fn(),
}));

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

jest.mock(
    "@/store",
    () => {
        return {};
    },
    { virtual: true }
);

jest.mock("@/helpers/heritage-integration/navigation-helper", () => ({
    navigateToHeritageFunnel: jest.fn(),
}));

const baseStoreGettersPageData = () => {
    return {
        partsOrQuestions: [
            {
                parts: null,
                partQuestions: [
                    {
                        questionSequence: 1,
                        questionText:
                            "Is your vehicle equipped with the Panoramic Sunroof which can be identified by having a glass panel over the rear seats?",
                        answers: [
                            {
                                answerResult: "",
                                answerText: "Yes",
                                nextQuestionSequence: 2,
                            },
                            {
                                answerResult: "",
                                answerText: "No",
                                nextQuestionSequence: 3,
                            },
                        ],
                    },
                ],
                glassLocation: "Windshield",
                glassName: "Single",
                answerKey: "Windshield-Single",
                answerData: null,
            },
        ],
    };
};
const baseStoreGettersDamage = () => {
    return {
        partsQuestionAnswers: [
            {
                glassLocation: "Windshield",
                glassName: "Single",
                result: "FW04848",
                answeredQuestions: [
                    {
                        questionText:
                            "Is your vehicle equipped with the Panoramic Sunroof which can be identified by having a glass panel over the rear seats?",
                        selectedAnswer: "1|nextQuestion|3|Yes",
                        selectedAnswerText: "Yes",
                        questionNum: 1,
                    },
                    {
                        questionText:
                            "Is your vehicle equipped with a heated windshield that melts snow and ice from underneath the windshield wiper blades?",
                        selectedAnswer: "1|nextQuestion|3|Yes",
                        selectedAnswerText: "Yes",
                        questionNum: 2,
                    },
                ],
            },
        ],
    };
};
store.getters = {
    pageData: baseStoreGettersPageData,
    damage: baseStoreGettersDamage,
    order: {},
};
store.commit = jest.fn();

describe("partQuestions.vue...", () => {
    describe("method arePagePrerequisitesValid...", () => {
        test("Should return true for valid page requisites if pageData exists", () => {
            // Arrange
            const { wrapper } = setupMocks({});

            // Act
            const result = wrapper.vm.arePagePrerequisitesValid();

            //Assert
            expect(result).toBe(true);

            wrapper.unmount();
        });

        test("Should return false for valid page requisites if partsOrQuestions in pageData is missing", () => {
            // Arrange
            const { wrapper } = setupMocks({});
            store.getters.pageData = jest.fn(() => {
                return undefined;
            });

            // Act
            const result = wrapper.vm.arePagePrerequisitesValid();

            //Assert
            expect(result).toBeFalsy();

            wrapper.unmount();
        });

        test("Should be at least one item in partsOrQuestions", () => {
            // Arrange
            store.getters = {
                pageData: jest.fn(() => {
                    return {
                        partsOrQuestions: [],
                    };
                }),
                damage: baseStoreGettersDamage,
                order: {},
            };
            const { wrapper } = setupMocks({});

            // Act
            const result = wrapper.vm.arePagePrerequisitesValid();

            //Assert
            expect(result).toBeFalsy();

            wrapper.unmount();
        });
    });

    describe("watch on selectedAnswers should be set up...", () => {
        test("Should trigger handleCompletedQuestionChainAnswers if watched data changes", async () => {
            // Arrange
            store.getters = {
                pageData: baseStoreGettersPageData,
                damage: baseStoreGettersDamage,
                order: {},
            };
            const { wrapper } = setupMocks({});
            wrapper.vm.handleCompletedQuestionChainAnswers = jest.fn();
            const spy = jest.spyOn(wrapper.vm, "handleCompletedQuestionChainAnswers");

            // Act
            wrapper.setData({
                selectedAnswers: {
                    "Windshield-Single": {
                        answerResult: "FW04848",
                        answeredQuestions: [
                            {
                                questionText: "One?",
                                selectedAnswer: "1|nextQuestion|3|Yes",
                                selectedAnswerText: "Yes",
                                questionNum: 1,
                            },
                            {
                                questionText: "Two?",
                                selectedAnswer: "1|nextQuestion|3|Yes",
                                selectedAnswerText: "Yes",
                                questionNum: 2,
                            },
                        ],
                        index: 0,
                    },
                },
            });

            await nextTick();

            wrapper.setData({
                selectedAnswers: {
                    "Windshield-Single": {
                        answerResult: "NEW-ANSWER",
                        answeredQuestions: [
                            {
                                questionText: "One?",
                                selectedAnswerText: "Yes",
                                questionNum: 1,
                            },
                            {
                                questionText: "Two?",
                                selectedAnswerText: "Yes",
                                questionNum: 2,
                            },
                        ],
                        index: 0,
                    },
                },
            });

            //Assert
            expect(spy).toHaveBeenCalled();

            wrapper.unmount();
        });
    });

    describe("forwardButtonAction", () => {
        test("Should clear out answerData", async () => {
            // Arrange
            store.getters.payment = {
                insuranceCoverage: null,
            };
            const { wrapper } = setupMocks({});

            await wrapper.setData({
                questionsData: [
                    {
                        glassLocation: "fbfWindshield",
                        glassName: "fbfSingle",
                        answerData: {
                            answerResult: "FW04848",
                            answeredQuestions: [],
                        },
                    },
                ],
            });

            wrapper.vm.dispatchStoreAction = jest.fn(() => {
                return {
                    data: {
                        glassPieceParts: [],
                    },
                };
            });
            wrapper.vm.dispatchStoreActionWithLogging = jest.fn(() => {
                return {
                    data: {
                        glassPieceParts: [],
                    },
                };
            });

            // Act
            wrapper.vm.forwardButtonAction();

            await nextTick();

            //Assert
            expect(wrapper.vm.questionsData[0].answerData).toEqual({});

            wrapper.unmount();
        });

        test("Should save to Vuex store", async () => {
            // Arrange
            const { wrapper } = setupMocks({});

            wrapper.vm.questionsData = [
                {
                    glassLocation: "Windshield",
                    glassName: "Single",
                    answerData: {
                        answerResult: "FW04848",
                        answeredQuestions: [],
                    },
                },
            ];
            wrapper.vm.dispatchStoreAction = jest.fn(() => {
                return {
                    data: {
                        glassPieceParts: [],
                    },
                };
            });
            wrapper.vm.dispatchStoreActionWithLogging = jest.fn(() => {
                return {
                    data: {
                        glassPieceParts: [],
                    },
                };
            });
            const spy = jest.spyOn(wrapper.vm, "dispatchStoreAction");

            // Act
            wrapper.vm.forwardButtonAction();

            await nextTick();

            //Assert
            expect(spy).toHaveBeenNthCalledWith(
                1,
                "savePartQuestionAnswers",
                [
                    {
                        answeredQuestions: [],
                        glassLocation: "Windshield",
                        glassName: "Single",
                        isSuppressedPart: undefined,
                        result: "FW04848",
                    },
                ],
                false
            );

            wrapper.unmount();
        });

        test("Should call GET_PARTS API", async () => {
            // Arrange
            const { wrapper } = setupMocks({});

            wrapper.vm.questionsData = [
                {
                    glassLocation: "Windshield",
                    glassName: "Single",
                    answerData: {
                        answerResult: "FW04848",
                        answeredQuestions: [],
                    },
                },
            ];
            wrapper.vm.dispatchStoreAction = jest.fn(() => {
                return {
                    data: {
                        glassPieceParts: [],
                    },
                };
            });
            wrapper.vm.dispatchStoreActionWithLogging = jest.fn(() => {
                return {
                    data: {
                        glassPieceParts: [],
                    },
                };
            });
            const spy = jest.spyOn(wrapper.vm, "dispatchStoreActionWithLogging");

            // Act
            wrapper.vm.forwardButtonAction();

            await nextTick();

            //Assert
            expect(spy).toHaveBeenNthCalledWith(1, "getParts", null, "part-questions");

            wrapper.unmount();
        });

        test("Should trigger navigateForward", async () => {
            // Arrange
            const { wrapper } = setupMocks({});

            wrapper.vm.questionsData = [
                {
                    glassLocation: "Windshield",
                    glassName: "Single",
                    answerData: {
                        answerResult: "FW04848",
                        answeredQuestions: [],
                    },
                },
            ];
            wrapper.vm.dispatchStoreAction = jest.fn(() => {
                return {
                    data: {
                        glassPieceParts: [],
                    },
                };
            });
            wrapper.vm.dispatchStoreActionWithLogging = jest.fn(() => {
                return {
                    data: {
                        glassPieceParts: [],
                    },
                };
            });
            wrapper.vm.navigateForward = jest.fn();

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

            //Assert
            expect(wrapper.vm.navigateForward).toHaveBeenCalled();

            wrapper.unmount();
        });
    });
});

function setupMocks({
    mountOptionsMockData = {
        router: {
            navigate: jest.fn(),
            navigateWithSaving: jest.fn(),
            navigateWithoutSaving: jest.fn(),
        },
        actionList: [
            {
                actionName: storeActions.SAVE_PART_QUESTION_ANSWERS,
                data: {},
            },
            {
                actionName: storeActions.GET_PARTS,
                data: {},
            },
        ],
        store: {
            getters: store.getters,
            commit: store.commit,
        },
        route: {
            query: {
                fmgPage: "part-questions",
            },
        },
        data() {
            return {
                computedSwitcher: [
                    {
                        glassLocation: "Windshield",
                        glassName: "Single",
                        answerData: {
                            answerResult: "FW04848",
                            answeredQuestions: [],
                        },
                    },
                ],
            };
        },
        questionsData: {
            get() {
                return this.computedSwitcher;
            },
            set(val) {
                this.computedSwitcher = val;
            },
        },
    },
}) {
    const mountOptions = getMountOptions({
        ...mountOptionsMockData,
        mixins: [baseMixin, vehicleQuestionsMixin],
    });
    mountOptions["attachTo"] = document.body;

    const wrapper = shallowMount(partQuestions, mountOptions);

    return { wrapper };
}
