import formatDateWithTimezone from "@insite/client-framework/Common/Utilities/formatDateWithTimezone";
import {
    ApiHandlerDiscreteParameter,
    createHandlerChainRunner,
    HasOnSuccess,
    markSkipOnCompleteIfOnSuccessIsSet,
} from "@insite/client-framework/HandlerCreator";
import {
    CartResult,
    UpdateCartApiParameter,
    updateCartWithResult,
} from "@insite/client-framework/Services/CartService";
import { getCartState, getCurrentCartState } from "@insite/client-framework/Store/Data/Carts/CartsSelector";
import loadCurrentCart from "@insite/client-framework/Store/Data/Carts/Handlers/LoadCurrentCart";

const convertDateToApiFormat = (date: Date | null) => (date ? formatDateWithTimezone(date) : "");

type HandlerType = ApiHandlerDiscreteParameter<HasOnSuccess<string>, UpdateCartApiParameter, CartResult>;

export const DispatchBeginPlaceOrderForApproval: HandlerType = props => {
    props.dispatch({
        type: "Pages/OnePageCheckout/BeginPlaceOrderForApproval",
    });
};

export const PopulateApiParameter: HandlerType = props => {
    const state = props.getState();
    const {
        pages: {
            onePageCheckout: { cartId, requestedDeliveryDate, requestedPickupDate, editedCartNotes },
        },
    } = state;
    const cart = cartId ? getCartState(state, cartId).value : getCurrentCartState(state).value;

    if (!cart) {
        throw new Error("There was no current cart and we are trying to place the current cart as an order.");
    }

    const tempDeliveryDate =
        typeof requestedDeliveryDate !== "undefined" ? requestedDeliveryDate : cart.requestedDeliveryDateDisplay;
    const tempPickupDate =
        typeof requestedPickupDate !== "undefined" ? requestedPickupDate : cart.requestedPickupDateDisplay;
    const notes = typeof editedCartNotes === "undefined" ? cart.notes : editedCartNotes;

    props.apiParameter = {
        cart: {
            ...cart,
            status: "AwaitingApproval",
            requestedDeliveryDate: convertDateToApiFormat(tempDeliveryDate),
            requestedPickupDate: convertDateToApiFormat(tempPickupDate),
            notes,
        },
    };
};

export const UpdateCart: HandlerType = async props => {
    const result = await updateCartWithResult(props.apiParameter);
    if (result.successful) {
        props.apiResult = result.result;
    } else {
        props.dispatch({
            type: "Pages/OnePageCheckout/SetPlaceOrderErrorMessage",
            errorMessage: result.errorMessage,
        });
        props.dispatch({
            type: "Pages/OnePageCheckout/CompletePlaceOrderForApproval",
        });
        return false;
    }
};

export const ReloadCurrentCart: HandlerType = props => {
    props.dispatch(loadCurrentCart());
};

export const ExecuteOnSuccessCallback: HandlerType = props => {
    if (props.parameter.onSuccess) {
        markSkipOnCompleteIfOnSuccessIsSet(props);
        props.parameter.onSuccess(props.apiResult.cart.id);
    }
};

export const DispatchCompletePlaceOrderForApproval: HandlerType = props => {
    props.dispatch({
        type: "Pages/OnePageCheckout/CompletePlaceOrderForApproval",
    });
};

export const DispatchResetOrders: HandlerType = props => {
    props.dispatch({
        type: "Data/Orders/Reset",
    });
};

export const DispatchResetQuotes: HandlerType = props => {
    const state = props.getState();
    const { cartId } = state.pages.onePageCheckout;
    if (cartId) {
        props.dispatch({
            type: "Data/Quotes/Reset",
        });
        props.dispatch({
            type: "Data/JobQuotes/Reset",
        });
    }
};

export const chain = [
    DispatchBeginPlaceOrderForApproval,
    PopulateApiParameter,
    UpdateCart,
    ReloadCurrentCart,
    ExecuteOnSuccessCallback,
    DispatchCompletePlaceOrderForApproval,
    DispatchResetOrders,
    DispatchResetQuotes,
];

const placeOrderForApproval = createHandlerChainRunner(chain, "PlaceOrderForApproval");
export default placeOrderForApproval;
