// Components
import mobileAddressQuestions from "@/layouts/mobile-details/mobile-address-questions/mobile-address-questions.vue";

// Supporting Files
import { mount, shallowMount } from "@vue/test-utils";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
import { storeMutations } from "@/constants/store-mutations";
import store from "@/store";

describe("initial state", () => {
    test("Should show all the address field", () => {
        // Arrange
        const { wrapper } = setupMocks({});

        // Assert
        const streetAddressField = wrapper.findComponent({ ref: "streetAddress" });
        const cityField = wrapper.findComponent({ ref: "city" });
        const stateField = wrapper.findComponent({ ref: "state" });
        const zipCodeField = wrapper.findComponent({ ref: "zipCode" });

        expect(streetAddressField.exists()).toBe(true);
        expect(streetAddressField.isVisible()).toBe(true);
        expect(cityField.exists()).toBe(true);
        expect(cityField.isVisible()).toBe(true);
        expect(stateField.exists()).toBe(true);
        expect(stateField.isVisible()).toBe(true);
        expect(zipCodeField.exists()).toBe(true);
        expect(zipCodeField.isVisible()).toBe(true);
    });

    test("Should render mobileAddressQuestions sub-components (textbox-questions and dropdown-questions)", async () => {
        // Arrange
        const { wrapper } = setupMocks({});

        // Act
        const streetAddress = wrapper.findComponent({ ref: "streetAddress" });
        const city = wrapper.findComponent({ ref: "city" });
        const state = wrapper.findComponent({ ref: "state" });
        const zipCode = wrapper.findComponent({ ref: "zipCode" });

        // Assert
        expect(streetAddress.exists()).toBe(true);
        expect(city.exists()).toBe(true);
        expect(state.exists()).toBe(true);
        expect(zipCode.exists()).toBe(true);
    });

    test("Should render apartmentNumberOrBusinessName textbox-question when captureApartmentNumberOrBusinessName = true", async () => {
        // Arrange
        const { wrapper } = setupMocks({
            props: {
                modelValue: {
                    streetAddress: "",
                    apartmentNumberOrBusinessName: "",
                    city: "",
                    state: "",
                    zipCode: "",
                },
                captureApartmentNumberOrBusinessName: true,
            },
        });

        // Act
        const streetAddress = wrapper.findComponent({ ref: "streetAddress" });
        const apartmentNumberOrBusinessName = wrapper.findComponent({
            ref: "apartmentNumberOrBusinessName",
        });
        const city = wrapper.findComponent({ ref: "city" });
        const state = wrapper.findComponent({ ref: "state" });
        const zipCode = wrapper.findComponent({ ref: "zipCode" });

        // Assert
        expect(streetAddress.exists()).toBe(true);
        expect(apartmentNumberOrBusinessName.exists()).toBe(true);
        expect(apartmentNumberOrBusinessName.isVisible()).toBe(true);
        expect(city.exists()).toBe(true);
        expect(state.exists()).toBe(true);
        expect(zipCode.exists()).toBe(true);
    });

    test("Should *not* render apartmentNumberOrBusinessName textbox-question when captureApartmentNumberOrBusinessName = false", async () => {
        // Arrange
        const { wrapper } = setupMocks({
            props: {
                modelValue: {
                    streetAddress: "",
                    apartmentNumberOrBusinessName: "",
                    city: "",
                    state: "",
                    zipCode: "",
                },
                captureApartmentNumberOrBusinessName: false,
            },
        });

        // Act
        const streetAddress = wrapper.findComponent({ ref: "streetAddress" });
        const apartmentNumberOrBusinessName = wrapper.findComponent({
            ref: "apartmentNumberOrBusinessName",
        });
        const city = wrapper.findComponent({ ref: "city" });
        const state = wrapper.findComponent({ ref: "state" });
        const zipCode = wrapper.findComponent({ ref: "zipCode" });

        // Assert
        expect(streetAddress.exists()).toBe(true);
        expect(apartmentNumberOrBusinessName.exists()).toBe(true);
        expect(apartmentNumberOrBusinessName.isVisible()).toBe(false);
        expect(city.exists()).toBe(true);
        expect(state.exists()).toBe(true);
        expect(zipCode.exists()).toBe(true);
    });
});

describe("happy paths", () => {
    test("full street address is passed in => address fields are displayed", async () => {
        // Arrange/Act
        const { wrapper } = setupMocks({
            props: {
                modelValue: {
                    streetAddress: "12345 Test Road",
                    city: "Tests",
                    state: "OH",
                    zipCode: "12312",
                },
            },
        });

        await wrapper.vm.$nextTick();

        // Assert
        const cityField = wrapper.findComponent({ ref: "city" });
        const stateField = wrapper.findComponent({ ref: "state" });
        const zipField = wrapper.findComponent({ ref: "zipCode" });
        expect(cityField.exists()).toBeTruthy();
        expect(cityField.isVisible()).toBeTruthy();
        expect(stateField.exists()).toBeTruthy();
        expect(cityField.isVisible()).toBeTruthy();
        expect(zipField.exists()).toBeTruthy();
        expect(cityField.isVisible()).toBeTruthy();
    });
});

function setupMocks({
    mountOptions,
    props,
    isShallowMount = true,
    querySelectorFunction,
    geocoderResult = ["1234 Test Street"],
    matchFound = false,
}) {
    store.commit(storeMutations.RESET_STATE);

    const resultingMountOptions = getMountOptions({
        ...mountOptions,
        router: {
            navigate: jest.fn(),
            navigate: jest.fn(),
        },
        loadScript: jest.fn().mockResolvedValue(),
    });

    if (props) resultingMountOptions.propsData = props;

    if (isShallowMount) {
        resultingMountOptions.global.stubs = {
            ...(resultingMountOptions.global.stubs ?? {}),
            textboxQuestion: {
                template: `<span></span>`,
                methods: {
                    handleChange: jest.fn(),
                },
            },
            dropdownQuestion: {
                template: `<span></span>`,
                methods: {
                    handleChange: jest.fn(),
                },
            },
        };
    }

    const wrapper = isShallowMount
        ? shallowMount(mobileAddressQuestions, resultingMountOptions)
        : mount(mobileAddressQuestions, resultingMountOptions);

    document.querySelector = jest.fn().mockImplementation((query) => {
        let result = null;
        if (query == ".pac-container") result = document.createElement("div");
        else if (querySelectorFunction) {
            result = querySelectorFunction(query);
        }

        return result ?? null;
    });

    return { wrapper };
}
