import { shallowMount } from "@vue/test-utils";
import replaceOptionsQuestion from "@/layouts/vehicle-damage/replace-options-question/replace-options-question";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
import { nextTick } from "vue";
import store from "@/store";
jest.mock(
    "@/store",
    () => {
        return {};
    },
    { virtual: true }
);

describe("replace-options-question.vue", () => {
    test("Selected damage option is emitted upon selection.", async () => {
        //Arrange
        const { wrapper } = setupMocks({ modelValueProp: ["Windshield"] });
        const damageToSelect = ["Backseat"];

        //Act
        wrapper.setValue({ modelValue: damageToSelect });
        await wrapper.vm.$nextTick();

        //Assert
        expect(wrapper.emitted()["update:modelValue"][0]).toEqual([{ modelValue: ["Backseat"] }]);
    });
});

describe("replace-options-question.vue", () => {
    test("Answers to display filtered by data from api.", async () => {
        //Arrange
        const { wrapper, cmsContent, replaceOptions } = setupMocks({
            dataFromStoreApi: ["Windshield", "FrontDoor"],
            filterByVehicleCategory: true,
        });

        //Act
        replaceOptionsQuestion.methods.initializeComponent.call(
            wrapper.vm,
            replaceOptions,
            "car-group"
        );

        //Assert
        expect(wrapper.vm.replaceOptions).toStrictEqual(["Windshield", "FrontDoor"]);
    });
});

describe("replace-options-question.vue", () => {
    test("when updateSelectedValues method is called with a single answerToDisplay it will call to update this.selectedReplaceOptions", async () => {
        //Arrange
        const { wrapper, cmsContent, replaceOptions } = setupMocks({
            modelValueProp: [],
        });
        wrapper.setData({
            answersFromCms: [
                {
                    Name: "Stationary",
                },
                {
                    Name: "Slider",
                },
            ],
        });
        wrapper.setData({ replaceOptions: ["Stationary"] });

        //Act
        wrapper.vm.$options.methods.updateSelectedValues.call(wrapper.vm);

        expect(wrapper.vm.selectedValues).toEqual([]);
    });
});

describe("replace-options-question.vue", () => {
    test("when isAvailable is true, will run updateSelectedValues method", async () => {
        //Arrange
        const { wrapper, cmsContent, replaceOptions } = setupMocks({
            isAvailable: false,
            methodsToMock: ["updateSelectedValues"],
        });

        //Act
        wrapper.vm.$options.methods.initializeComponent.call(
            wrapper.vm,
            cmsContent,
            replaceOptions,
            "car-group"
        );
        wrapper.vm.$options.watch.isAvailable.call(wrapper.vm, true);

        //Assert
        expect(replaceOptionsQuestion.methods.updateSelectedValues).toHaveBeenCalled();
        wrapper.unmount();
    });
});

function setupMocks({
    modelValueProp = ["Windshield"],
    isAvailable = true,
    isMultiSelect = false,
    filterByVehicleCategory = false,
    groupName = "damageQuestion",
    cmsQuestionText = "CMS text goes here",
    cmsAnswers = [{ Name: "car-Windshield" }, { Name: "car-BackDoor" }, { Name: "car-FrontDoor" }],
    dataFromStoreApi = [],
    methodsToMock = [],
}) {
    //Mock store
    store.dispatch = jest.fn(() => dataFromStoreApi);
    store.getters = {
        vehicle: { year: 2019, make: "honda", model: "civc", style: "2 Door", category: "CAR" },
    };
    const mountOptions = getMountOptions({
        store: {
            dispatch: store.dispatch,
            getters: store.getters,
        },
    });

    //Mock props
    const mockMixin = {
        methods: {
            getCmsContent: jest.fn(),
        },
    };
    mountOptions.propsData = {
        modelValue: modelValueProp,
        isAvailable: isAvailable,
        isMultiSelect: isMultiSelect,
        filterByVehicleCategory: filterByVehicleCategory,
    };
    mountOptions.mixins = [mockMixin];

    //Mock methods
    methodsToMock.forEach((methodName) => {
        replaceOptionsQuestion.methods[methodName] = jest.fn();
    });

    const wrapper = shallowMount(replaceOptionsQuestion, mountOptions);

    //Mock CMS content
    const cmsContent = {
        groupName: groupName,
        QuestionText: cmsQuestionText,
        Answers: cmsAnswers,
    };
    const replaceOptions = dataFromStoreApi;
    return { wrapper, cmsContent, replaceOptions };
}
