import { shallowMount } from "@vue/test-utils";
import { getMountOptions } from "@/helpers/unit-test-helper.js";

import optInReview from "@/layouts/payment-method/review-dropdown/review-sections/opt-in-review/opt-in-review";

const testConstants = {
    cms: {
        header: {
            text: "Text Message Updates",
        },
        bodyText: {
            text: "We'll send appointment updates to {custom:SMSNUMBER}",
        },
        processedBodyText: {
            text: "We'll send appointment updates to 111-111-1111",
        },
    },
    customer: {
        phoneNumber: "111-111-1111",
    },
    displayContent: {
        processedBodyText: "We'll send appointment updates to 111-111-1111",
    },
};

let cmsContent;

describe("Opt-In Review Block", () => {
    beforeEach(() => {
        cmsContent = {
            OptInWidget: {
                HeaderText: testConstants.cms.header.text,
                BodyText: testConstants.cms.bodyText.text,
            },
        };
    });

    test("Should display header text from cms", async () => {
        // Arrange
        let props = generateDefaultProps();

        const { wrapper } = setupMocks({
            propsData: props,
        });

        // Act
        await wrapper.vm.$nextTick();

        // Assert
        expect(wrapper.vm.header).toEqual(testConstants.cms.header.text);
    });

    test("Should render correct display content with phone number replacement", async () => {
        // Arrange
        let props = generateDefaultProps();

        const { wrapper } = setupMocks({
            propsData: props,
        });

        // Act
        await wrapper.vm.$nextTick();

        // Assert
        expect(wrapper.vm.displayContent).toEqual([testConstants.displayContent.processedBodyText]);
    });

    test("Should return customer phone number", async () => {
        // Arrange
        let props = generateDefaultProps();

        const { wrapper } = setupMocks({
            propsData: props,
        });

        // Act
        await wrapper.vm.$nextTick();

        // Assert
        expect(wrapper.vm.phoneNumber).toEqual(testConstants.customer.phoneNumber);
    });

    test("Should emit edit-clicked when editClicked method is called", async () => {
        // Arrange
        let props = generateDefaultProps();

        const { wrapper } = setupMocks({
            propsData: props,
        });

        // Act
        wrapper.vm.editClicked();
        await wrapper.vm.$nextTick();

        // Assert
        expect(wrapper.emitted("edit-clicked")).toBeTruthy();
    });

    test("Should handle missing customer gracefully", async () => {
        // Arrange
        let props = generateDefaultProps();
        props.customer = null;

        const { wrapper } = setupMocks({
            propsData: props,
        });

        // Act
        await wrapper.vm.$nextTick();

        // Assert
        expect(wrapper.vm.phoneNumber).toBeUndefined();
    });
});

function generateDefaultProps() {
    return {
        cmsWidgetName: "OptInWidget",
        customer: {
            phoneNumber: testConstants.customer.phoneNumber,
        },
    };
}

function setupMocks(customMountOptions) {
    const mountOptions = getMountOptions(customMountOptions);

    const mockMixin = {
        methods: {
            getCmsContent: jest.fn((widgetName, cmsFieldName) => {
                return cmsContent?.[widgetName]?.[cmsFieldName] ?? "";
            }),
        },
    };

    mountOptions.global.mixins = [mockMixin];

    const wrapper = shallowMount(optInReview, mountOptions);
    wrapper.vm.setCmsContent = jest.fn();
    return { wrapper };
}
