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

import parityDamageReview from "@/layouts/payment-method/review-dropdown/review-sections/parity-damage-review/parity-damage-review";

// Mock the damage helper
jest.mock("@/helpers/damage-helper", () => ({
    getDamageInfoWordingText: jest.fn(),
}));

const testConstants = {
    cms: {
        damageInfoHeader: {
            text: "We'll replace your {custom:GLASSPARTS}",
        },
        processedHeader: {
            text: "We'll replace your windshield and passenger side window",
        },
    },
    vehicle: {
        year: "2020",
        make: "Honda",
        model: "Civic",
    },
    damage: {
        glassType: "windshield",
        location: "passenger",
    },
    damageInfoWordingText: "windshield and passenger side window",
    displayContent: {
        vehicleInfo: "2020 Honda Civic",
    },
};

let cmsContent;

describe("Parity Damage Review Block", () => {
    beforeEach(() => {
        cmsContent = {
            DamageInfoHeaderWidget: {
                Text: testConstants.cms.damageInfoHeader.text,
            },
        };

        // Mock the damage helper function
        getDamageInfoWordingText.mockReturnValue(testConstants.damageInfoWordingText);
    });

    afterEach(() => {
        jest.clearAllMocks();
    });

    test("Should display processed damage info header text with custom replacement", async () => {
        // Arrange
        let props = generateDefaultProps();

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

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

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

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

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

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

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

    test("Should call getDamageInfoWordingText with damage prop", async () => {
        // Arrange
        let props = generateDefaultProps();

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

        // Act
        await wrapper.vm.$nextTick();
        const result = wrapper.vm.damageInfoWordingText;

        // Assert
        expect(getDamageInfoWordingText).toHaveBeenCalledWith(testConstants.damage);
        expect(result).toEqual(testConstants.damageInfoWordingText);
    });

    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();
    });
});

function generateDefaultProps() {
    return {
        cmsWidgetName: "DamageReviewWidget",
        vehicle: {
            year: testConstants.vehicle.year,
            make: testConstants.vehicle.make,
            model: testConstants.vehicle.model,
        },
        damage: {
            glassType: testConstants.damage.glassType,
            location: testConstants.damage.location,
        },
    };
}

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(parityDamageReview, mountOptions);
    wrapper.vm.setCmsContent = jest.fn();
    return { wrapper };
}
