import waitFor from "@insite/client-framework/Common/Utilities/waitFor";
import { createHandlerChainRunnerOptionalParameter, Handler } from "@insite/client-framework/HandlerCreator";
import { getAddressFieldsDataView } from "@insite/client-framework/Store/Data/AddressFields/AddressFieldsSelector";
import loadAddressFields from "@insite/client-framework/Store/Data/AddressFields/Handlers/LoadAddressFields";
import {
    getCartState,
    getCurrentCartState,
    isCartLoadedWithLines,
    isCartLoadedWithoutLines,
} from "@insite/client-framework/Store/Data/Carts/CartsSelector";
import loadCart from "@insite/client-framework/Store/Data/Carts/Handlers/LoadCart";
import loadCurrentCart from "@insite/client-framework/Store/Data/Carts/Handlers/LoadCurrentCart";
import { getCurrentCountries } from "@insite/client-framework/Store/Data/Countries/CountriesSelectors";
import loadCurrentCountries from "@insite/client-framework/Store/Data/Countries/Handlers/LoadCurrentCountries";
import {
    getCurrentPromotionsDataView,
    getPromotionsDataView,
} from "@insite/client-framework/Store/Data/Promotions/PromotionsSelectors";

type HandlerType = Handler<{
    cartId?: string;
    onSuccess?: () => void;
}>;

export const LoadData: HandlerType = props => {
    const state = props.getState();
    if (!getCurrentCountries(state)) {
        props.dispatch(loadCurrentCountries());
    }
    if (!getAddressFieldsDataView(state).value) {
        props.dispatch(loadAddressFields());
    }

    const { cartId } = props.parameter;
    if (cartId) {
        const cartState = getCartState(state, cartId);
        if (!cartState.value && !cartState.isLoading) {
            const promotionsState = getPromotionsDataView(state, cartId);
            const shouldLoadPromotions = !promotionsState.value && !promotionsState.isLoading;
            props.dispatch(loadCart({ cartId, getPromotions: shouldLoadPromotions, shouldLoadFullCart: true }));
        }
    } else {
        const currentCartState = getCurrentCartState(state);
        if (
            (!currentCartState.value ||
                (currentCartState.value.lineCount && !currentCartState.value.cartLines?.length) ||
                !currentCartState.value.carriers) &&
            !currentCartState.isLoading
        ) {
            const currentPromotionsState = getCurrentPromotionsDataView(state);
            const shouldLoadPromotions = !currentPromotionsState.value && !currentPromotionsState.isLoading;
            props.dispatch(loadCurrentCart({ getPromotions: shouldLoadPromotions, shouldLoadFullCart: true }));
        }
    }
};

export const WaitForData: HandlerType = async props => {
    const checkData = () => {
        const state = props.getState();
        if (!getCurrentCountries(state)) {
            return false;
        }
        if (!getAddressFieldsDataView(state).value) {
            return false;
        }

        const { cartId } = props.parameter;
        if (cartId) {
            const promotions = getPromotionsDataView(state, cartId);
            if (!promotions || promotions.isLoading) {
                return false;
            }
            const cartState = getCartState(state, cartId);
            if (!isCartLoadedWithLines(cartState)) {
                if (isCartLoadedWithoutLines(cartState)) {
                    props.dispatch(loadCart({ cartId, getPromotions: true, shouldLoadFullCart: true }));
                }
                return false;
            }
        } else {
            const currentPromotions = getCurrentPromotionsDataView(state);
            if (!currentPromotions || currentPromotions.isLoading) {
                return false;
            }
            const currentCartState = getCurrentCartState(state);
            if (!isCartLoadedWithLines(currentCartState)) {
                if (isCartLoadedWithoutLines(currentCartState)) {
                    props.dispatch(loadCurrentCart({ getPromotions: true, shouldLoadFullCart: true }));
                }
                return false;
            }
        }

        return true;
    };

    await waitFor(checkData);
};

export const ExecuteOnSuccessCallback: HandlerType = props => {
    props.parameter.onSuccess?.();
};

export const chain = [LoadData, WaitForData, ExecuteOnSuccessCallback];

const loadDataIfNeeded = createHandlerChainRunnerOptionalParameter(chain, {}, "LoadDataIfNeeded");
export default loadDataIfNeeded;
