import { storeActions } from "@/constants/store-actions.js";
import {
    getFunnelCookie,
    updateOrCreateFunnelCookie,
    deleteFunnelCookie,
} from "@/helpers/heritage-integration/cookie-helper.js";
import baseMixin from "@/mixins/base-mixin";
import store from "@/store";
import { storeMutations } from "@/constants/store-mutations";

/*
    Will call API and hydrate state with data from API if present. If there is no order present
    method will return null. If the cookie dictates the state should be reset
    it will reset the state and go back to the start of the funnel.

*/
export async function loadSessionIfPresent(isConceptInsurance, pageNameToLog) {
    const funnelCookie = getFunnelCookie();

    // Do nothing if there is no cookie or session to use for loading.
    if (
        funnelCookie == null ||
        funnelCookie.SavedSessionId == null ||
        funnelCookie.ReferralCorrelationId == null ||
        !funnelCookie.ReferralNumber
    ) {
        return null;
    }

    // Reset state if cookie says to.
    if (funnelCookie.ShouldResetState) {
        baseMixin.methods.dispatchStoreAction(storeActions.RESET_STATE);
        deleteFunnelCookie();
        return null;
    }

    // Loads session including referral if there is a cookie, and it doesn't indicate it needs a state reset.
    return (
        await loadSession(
            funnelCookie.SavedSessionId,
            funnelCookie.ReferralNumber,
            funnelCookie.ReferralDate,
            funnelCookie.ReferralParentAccountNumber,
            funnelCookie.ReferralCorrelationId,
            isConceptInsurance,
            pageNameToLog
        )
    )?.data;
}

/*
    Will call API to save existing order, or create new one depending where it's called from.
    This will also set Referral information in the store after saving, and then
    update the cookie. To force synchronous behavior pass in 'true' for shouldAwaitSaveSessionQueue
*/
export async function saveSession({
    pageNameToLog,
    shouldAwaitSaveSessionQueue = false,
    submitAfterSave = false,
    createUnscheduledStatusWorkOrderForPIA = false,
}) {
    var saveSessionPromise;
    if (store.getters.applicationUser.saveSessionPromise) {
        // queue newest request after current saveSessionPromise resolves
        saveSessionPromise = store.getters.applicationUser.saveSessionPromise.then(() => {
            // get a new saveSessionPromise
            return saveSessionHelper(
                pageNameToLog,
                submitAfterSave,
                createUnscheduledStatusWorkOrderForPIA
            );
        });
    } else {
        // create an initial saveSessionPromise
        saveSessionPromise = saveSessionHelper(
            pageNameToLog,
            submitAfterSave,
            createUnscheduledStatusWorkOrderForPIA
        );
    }
    store.commit(storeMutations.UPDATE_SAVE_SESSION_PROMISE, saveSessionPromise);
    // await here to allow for a caller to await and make the function synchronous
    if (!store.getters.applicationUser.savedSessionId || shouldAwaitSaveSessionQueue) {
        await saveSessionPromise;
    }
}

export async function submitWorkOrder({
    pageNameToLog,
    submitAfterSave = false,
    createUnscheduledStatusWorkOrderForPIA = false,
}) {
    await saveSession({
        pageNameToLog: pageNameToLog,
        shouldAwaitSaveSessionQueue: true,
        submitAfterSave: submitAfterSave,
        createUnscheduledStatusWorkOrderForPIA: createUnscheduledStatusWorkOrderForPIA,
    });
}

export async function saveQuote({ pageNameToLog }) {
    await baseMixin.methods.dispatchStoreActionWithLogging(
        storeActions.SAVE_QUOTE,
        {},
        pageNameToLog,
        false
    );

    // save session back to sv2 so the email gets saved just in case they refresh or step away and come back later
    await saveSession({
        pageNameToLog: pageNameToLog,
        shouldAwaitSaveSessionQueue: true,
        submitAfterSave: false,
        createUnscheduledStatusWorkOrderForPIA: false,
    });

    return;
}

// PRIVATE FUNCTIONS //

/*
    Calls API to load session given the referral number, referralDate, and referralCorrelationId
    and returns the response.
*/
async function loadSession(
    savedSessionId,
    referralNumber,
    referralDate,
    parentAccountNumber,
    referralCorrelationId,
    isConceptInsurance,
    pageNameToLog
) {
    // await the saveSessionPromise in the store to make sure we're loading up to date information
    await store.getters.applicationUser.saveSessionPromise;

    const response = await baseMixin.methods.dispatchStoreActionWithLogging(
        storeActions.LOAD_SESSION,
        {
            savedSessionId: savedSessionId?.toString(),
            referralNumber,
            referralDate,
            referralCorrelationId,
            parentAccountNumber,
            isConceptInsurance,
        },
        pageNameToLog,
        false
    );

    return response;
}

/*
    Encapsulates asynchronous Save Session logic inside a promise to allow for Save Session queuing 
*/
async function saveSessionHelper(
    pageNameToLog,
    submitAfterSave = false,
    createUnscheduledStatusWorkOrderForPIA = false
) {
    const savedSessionInfo = await baseMixin.methods.dispatchStoreActionWithLogging(
        storeActions.SAVE_SESSION,
        {
            submitAfterSave: submitAfterSave,
            createUnscheduledStatusWorkOrderForPIA: createUnscheduledStatusWorkOrderForPIA,
        },
        pageNameToLog
    );
    // Update the store with information received from the saveSession response
    await baseMixin.methods.dispatchStoreAction(
        storeActions.UPDATE_STORE_WITH_SAVE_SESSION_RESPONSE,
        {
            referralNumber: savedSessionInfo.data.referralNumber?.toString(),
            referralSequenceNumber: savedSessionInfo.data.referralSequenceNumber,
            referralCorrelationId: savedSessionInfo.data.referralCorrelationId,
            referralDate: savedSessionInfo.data.referralDate,
            parentAccountNumber: savedSessionInfo.data.parentAccountNumber?.toString(),
            savedSessionId: savedSessionInfo.data.savedSessionId,
            crmCustomerId: savedSessionInfo.data.crmCustomerId?.toString(),
            eon: savedSessionInfo.data.eon,
            workOrderNumber: savedSessionInfo.data.workOrderNumber,
            workOrderId: savedSessionInfo.data.workOrderId,
            customerPortalLoginToken: savedSessionInfo.data.customerPortalLoginToken,
            lockToken: savedSessionInfo.data.lockToken,
            settledTenderAmount: savedSessionInfo.data.settledTenderAmount,
            billToAccountNumber: savedSessionInfo.data.billToAccountNumber,
        },
        false
    );

    // Update the cookie with the referral information when saved.
    updateOrCreateFunnelCookie();
}
