import { storeActions } from "@/constants/store-actions";
import { storeMutations } from "@/constants/store-mutations.js";
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios.js";
import { vehicleCategories } from "@/constants/vehicle-categories.js";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import { cookieNames } from "@/constants/cookie-names";
import { Form } from "vee-validate";
import baseMixin from "@/mixins/base-mixin";
import {
    getCookieDomainValue,
    setCookieProperties,
} from "@/helpers/heritage-integration/cookie-helper";
import {
    analyticsPageEvents,
    GaCategories,
    GaActions,
    GaLabels,
    GaEvents,
    ValueToLogTypes,
} from "@/constants/analytics";
import { queryStrings } from "@/constants/query-strings";
import { routerParams } from "@/router/router-constants/router-params";

// Common methods
export function getMountOptions(mockData) {
    // Define our mocks to attached to the 'global' object for Vue/Jest.
    const mocks = {};

    //this is mocking if you use the mixin directly(baseMixin.methods.dispatchStoreAction) vs this.dispatchStoreAction
    setupBaseMixinDispatchStoreAction(mockData);

    mocks.pushEventToGA = jest.fn();
    mocks.pushPageViewToGA = jest.fn();
    mocks.logEvent = jest.fn();
    mocks.pushExperimentsToDataLayer = jest.fn();
    mocks.prependActionToMethod = jest.fn();
    mocks.dispatchStoreAction = jest.fn();
    mocks.dispatchStoreAction.mockImplementation((actionName) => {
        let actionFilterResult = mockData.actionList?.filter((x) => x.actionName == actionName);

        if (actionFilterResult?.length === 1) {
            return Promise.resolve({
                data: actionFilterResult[0].data,
            });
        }
    });
    mocks.dispatchStoreActionWithLogging = jest.fn();
    mocks.dispatchStoreActionWithLogging.mockImplementation((actionName) => {
        let actionFilterResult = mockData.actionList?.filter((x) => x.actionName == actionName);

        if (actionFilterResult?.length === 1) {
            return Promise.resolve({
                data: actionFilterResult[0].data,
            });
        }
    });

    // Mock const files
    mocks.storeActions = storeActions;
    mocks.storeMutations = storeMutations;
    mocks.navigationScenarios = navigationScenarios;
    mocks.vehicleCategories = vehicleCategories;
    mocks.fmgPageValues = fmgPageValues;
    mocks.analyticsPageEvents = analyticsPageEvents;
    mocks.GaCategories = GaCategories;
    mocks.GaActions = GaActions;
    mocks.GaLabels = GaLabels;
    mocks.GaEvents = GaEvents;
    mocks.ValueToLogTypes = ValueToLogTypes;
    mocks.queryStrings = queryStrings;
    mocks.routerParams = routerParams;

    // Mock $store and $router when accessing this.$store/$router
    mocks.$store = mockData.store;
    mocks.$router = mockData.router;
    mocks.$route = mockData.route;
    mocks.$loadScript = mockData.loadScript;

    const global = {
        mocks: mocks,
        mixins: mockData.mixins,
        stubs: { Form },
    };
    const props = mockData.propsData || {};

    return { global, props };
}

export function setupMocksForJsFiles(mockData = {}) {
    setupBaseMixinDispatchStoreAction(mockData);

    return { baseMixin };
}

// Heritage integration common methods
export const cookies = {
    [cookieNames.FUNNEL_SESSION_INFO]: `{"ReferralNumber":"1566818","ReferralDate":"2022-03-15T10:56:24.597","ReferralCorrelationId":"404d2b04-f86e-45c3-b373-127b6217b060","ShouldResetState":false,"DidHeritageFunnelUpdateLast":true}`,
    UNIQUE_SESSION_ID: "33756020-b58e-4ec7-b8b8-3f1576719c40",
    anotherCookie: "{}",
    someOtherCookie: "{}",
    dxdev: "did=21b9b94a-ec23-42c1-aaac-e2ae4e4dbffe",
    sid: "cba0c3d1-3c1b-4305-bb56-31aa50f58e27",
    [cookieNames.FUNNEL_SESSION_KEY]: "12345",
    [cookieNames.FUNNEL_USER_ID]: "11aec5e8-92ba-4dc9-a8b6-179a916d8d7a",
};

// Removes test cookies for testing cookie-helper and order-helper
export function removeAllTestCookies() {
    Object.keys(cookies).forEach((key) => {
        document.cookie = `${key}=;Max-Age=0;`;
        document.cookie = `${key}=;Max-Age=0;path=/;${getCookieDomainValue()}`;
    });
}

export function getMockOrderInfo(
    mockReferralNumber,
    mockCorrelationId,
    mockReferralDate,
    parentAccountNumber = "0",
    savedSessionId,
    crmCustomerId
) {
    return {
        referralNumber: mockReferralNumber,
        referralCorrelationId: mockCorrelationId,
        referralDate: mockReferralDate,
        parentAccountNumber: parentAccountNumber,
        savedSessionId: savedSessionId,
        crmCustomerId: crmCustomerId,
    };
}

export function setupCookies({ funnelCookieValue = "", includeHeritageCookie = true }) {
    Object.keys(cookies).forEach((key) => {
        const cookieValue =
            key == cookieNames.FUNNEL_SESSION_INFO ? funnelCookieValue : cookies[key];
        if (includeHeritageCookie || key != cookieNames.FUNNEL_SESSION_INFO)
            setCookieProperties({ [key]: cookieValue }, { isSecure: false });
    });
}

export function setupAffiliateCookies(cookie) {
    setCookieProperties({ [cookie.CookieName]: cookie.CookieValue }, { isSecure: false });
}

export function setupCrypto(mockValue) {
    global.crypto = {
        randomUUID: jest.fn(),
    };

    global.crypto.randomUUID.mockImplementation(() => mockValue);
}

// Private methods
function setupBaseMixinDispatchStoreAction(mockData) {
    if (mockData.actionList !== undefined) {
        baseMixin.methods.dispatchStoreAction = jest.fn();
        baseMixin.methods.dispatchStoreAction.mockImplementation((actionName) => {
            let actionFilterResult = mockData.actionList.filter((x) => x.actionName == actionName);

            if (actionFilterResult.length > 0 && actionFilterResult.length === 1) {
                return Promise.resolve({
                    data: actionFilterResult[0].data,
                });
            }
        });

        baseMixin.methods.dispatchStoreActionWithLogging = jest.fn();
        baseMixin.methods.dispatchStoreActionWithLogging.mockImplementation((actionName) => {
            let actionFilterResult = mockData.actionList.filter((x) => x.actionName == actionName);

            if (actionFilterResult.length > 0 && actionFilterResult.length === 1) {
                return Promise.resolve({
                    data: actionFilterResult[0].data,
                });
            }
        });
    }
}
