import parseQueryString from "@insite/client-framework/Common/Utilities/parseQueryString";
import { CartContext } from "@insite/client-framework/Components/CartContext";
import DelayedSpinner from "@insite/client-framework/Components/DelayedSpinner";
import Zone from "@insite/client-framework/Components/Zone";
import { FulfillmentMethod } from "@insite/client-framework/Services/SessionService";
import siteMessage from "@insite/client-framework/SiteMessage";
import ApplicationState from "@insite/client-framework/Store/ApplicationState";
import { getSession } from "@insite/client-framework/Store/Context/ContextSelectors";
import changeCustomerContext from "@insite/client-framework/Store/Context/Handlers/ChangeCustomerContext";
import { getCurrentAccountState } from "@insite/client-framework/Store/Data/Accounts/AccountsSelector";
import loadCurrentAccount from "@insite/client-framework/Store/Data/Accounts/Handlers/LoadCurrentAccount";
import { getOrderApprovalsState } from "@insite/client-framework/Store/Data/OrderApprovals/OrderApprovalsSelectors";
import { getLocation } from "@insite/client-framework/Store/Data/Pages/PageSelectors";
import { getPageLinkByPageType } from "@insite/client-framework/Store/Links/LinksSelectors";
import approveOrder from "@insite/client-framework/Store/Pages/OrderApprovalDetails/Handlers/ApproveOrder";
import displayOrder from "@insite/client-framework/Store/Pages/OrderApprovalDetails/Handlers/DisplayOrder";
import translate from "@insite/client-framework/Translate";
import PageModule from "@insite/client-framework/Types/PageModule";
import PageProps from "@insite/client-framework/Types/PageProps";
import { PageErrorWrapper } from "@insite/content-library/Components/PageErrorWrapper";
import Page from "@insite/mobius/Page";
import { HasToasterContext, withToaster } from "@insite/mobius/Toast/ToasterContext";
import { HasHistory, withHistory } from "@insite/mobius/utilities/HistoryContext";
import React, { useEffect } from "react";
import { connect, ResolveThunks } from "react-redux";

const mapStateToProps = (state: ApplicationState) => {
    const location = getLocation(state);
    let cartId;
    let externalApproval;
    if (location && location.search) {
        const parsedQuery = parseQueryString<{ cartId: string; "external-approval": boolean }>(location.search);
        cartId = parsedQuery.cartId;
        externalApproval = parsedQuery["external-approval"];
    }

    return {
        cartId,
        orderApprovalsState: getOrderApprovalsState(state, cartId),
        account: getCurrentAccountState(state).value,
        orderApprovalListPageLink: getPageLinkByPageType(state, "OrderApprovalListPage"),
        orderApprovalDetailsPage: getPageLinkByPageType(state, "OrderApprovalDetailsPage"),
        cartPageLink: getPageLinkByPageType(state, "CartPage"),
        externalApproval,
        session: getSession(state),
    };
};

const mapDispatchToProps = {
    displayOrder,
    loadCurrentAccount,
    approveOrder,
    changeCustomerContext,
};

type Props = PageProps &
    HasToasterContext &
    HasHistory &
    ReturnType<typeof mapStateToProps> &
    ResolveThunks<typeof mapDispatchToProps>;

const OrderApprovalDetailsPage = ({
    id,
    cartId,
    history,
    orderApprovalsState,
    displayOrder,
    account,
    loadCurrentAccount,
    orderApprovalListPageLink,
    orderApprovalDetailsPage,
    cartPageLink,
    approveOrder,
    externalApproval,
    toaster,
    session,
    changeCustomerContext,
}: Props) => {
    useEffect(() => {
        if (cartId) {
            displayOrder({ cartId });
        }

        if (!account) {
            loadCurrentAccount();
        }
    }, [account, cartId]);

    useEffect(() => {
        if (orderApprovalListPageLink && orderApprovalsState?.value?.status === "Submitted") {
            toaster.addToast({ body: translate("This order has already been approved."), messageType: "warning" });
            history.push(orderApprovalListPageLink.url);
        }
    }, [orderApprovalsState]);

    useEffect(() => {
        if (
            !account ||
            !cartPageLink ||
            !orderApprovalDetailsPage ||
            !orderApprovalListPageLink ||
            !orderApprovalsState?.value?.status ||
            !externalApproval
        ) {
            return;
        }

        if (!account.canViewApprovalOrders) {
            window.location.href = "/NotFoundErrorPage";
        }

        if (account.canApproveOrders && orderApprovalsState?.value?.status === "AwaitingApproval") {
            const { billToId, shipToId, fulfillmentMethod, pickUpWarehouse, hasDefaultCustomer } = session;

            if (
                orderApprovalsState.value?.shipTo?.id &&
                orderApprovalsState.value?.billTo?.id &&
                (orderApprovalsState.value.billTo.id !== billToId || orderApprovalsState.value.shipTo.id !== shipToId)
            ) {
                changeCustomerContext({
                    billToId: orderApprovalsState.value?.shipTo?.id,
                    shipToId: orderApprovalsState.value?.billTo?.id,
                    fulfillmentMethod,
                    pickUpWarehouse: fulfillmentMethod === FulfillmentMethod.PickUp ? pickUpWarehouse : null,
                    isDefault: hasDefaultCustomer,
                    skipRedirect: true,
                    onSuccess: () => {
                        approveOrder({
                            onSuccess: () => {
                                history.push(cartPageLink.url);
                            },
                        });
                    },
                    onError: () => {
                        toaster.addToast({
                            body: translate("There was a problem approving the order. Please try again."),
                            messageType: "warning",
                        });
                        history.push(`${orderApprovalDetailsPage.url}?cartId=${cartId}`);
                    },
                });
            } else {
                approveOrder({
                    onSuccess: () => {
                        history.push(cartPageLink.url);
                    },
                });
            }
        } else {
            history.push(`${orderApprovalDetailsPage.url}?cartId=${cartId}`);
        }
    }, [orderApprovalsState, account, cartPageLink, orderApprovalListPageLink]);

    return (
        <Page>
            <PageErrorWrapper
                value={orderApprovalsState}
                badRequestMessage={siteMessage("OrderApproval_BadRequest")}
                notAuthorizedMessage={siteMessage("OrderApproval_NotAuthorized")}
                notFoundMessage={siteMessage("OrderApproval_NotFound")}
            >
                {externalApproval ? (
                    <DelayedSpinner isWidget={false}></DelayedSpinner>
                ) : (
                    <CartContext.Provider value={orderApprovalsState?.value}>
                        <Zone contentId={id} zoneName="Content" />
                    </CartContext.Provider>
                )}
            </PageErrorWrapper>
        </Page>
    );
};

const pageModule: PageModule = {
    component: connect(mapStateToProps, mapDispatchToProps)(withHistory(withToaster(OrderApprovalDetailsPage))),
    definition: {
        hasEditableUrlSegment: true,
        hasEditableTitle: true,
        pageType: "System",
    },
};

export default pageModule;

/**
 * @deprecated Use string literal "OrderApprovalDetailsPage" instead of this constant.
 */
export const OrderApprovalDetailsPageContext = "OrderApprovalDetailsPage";
